diff options
author | Alex Ning <chineseperson5@gmail.com> | 2019-01-11 03:33:32 +0000 |
---|---|---|
committer | Alex Ning <chineseperson5@gmail.com> | 2019-01-11 03:33:32 +0000 |
commit | e48bb565a5aa871be18cae4003cb781ef6e2e154 (patch) | |
tree | 92efb6bf6b5d9db8f7411c1c6df83e18ccde06b5 | |
parent | f0b149ce82cf11df1f5cf84c7d644e5e670ad0b2 (diff) | |
download | infinity-for-reddit-e48bb565a5aa871be18cae4003cb781ef6e2e154.tar infinity-for-reddit-e48bb565a5aa871be18cae4003cb781ef6e2e154.tar.gz infinity-for-reddit-e48bb565a5aa871be18cae4003cb781ef6e2e154.tar.bz2 infinity-for-reddit-e48bb565a5aa871be18cae4003cb781ef6e2e154.tar.lz infinity-for-reddit-e48bb565a5aa871be18cae4003cb781ef6e2e154.tar.xz infinity-for-reddit-e48bb565a5aa871be18cae4003cb781ef6e2e154.tar.zst infinity-for-reddit-e48bb565a5aa871be18cae4003cb781ef6e2e154.zip |
View user details in ViewUserDetailActivity. Follow or unfollow user is not properly implemented right now. Change users and subscribed_users databases' schemes. Press Profile in navigation drawer to view my reddit info. Press the username in the post to view that account's info.
29 files changed, 704 insertions, 120 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a36ebe04..5d815b6d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -50,8 +50,8 @@ android:theme="@style/AppTheme.NoActionBarWithTranslucentStatusBar" /> <activity android:name=".ViewUserDetailActivity" - android:label="@string/title_activity_view_user_detail" - android:theme="@style/AppTheme.NoActionBar" /> + android:parentActivityName=".MainActivity" + android:theme="@style/AppTheme.NoActionBarWithTranslucentStatusBar" /> </application> </manifest>
\ No newline at end of file diff --git a/app/src/main/java/SubredditDatabase/SubredditDao.java b/app/src/main/java/SubredditDatabase/SubredditDao.java index ac291f9a..df763c93 100644 --- a/app/src/main/java/SubredditDatabase/SubredditDao.java +++ b/app/src/main/java/SubredditDatabase/SubredditDao.java @@ -14,7 +14,7 @@ public interface SubredditDao { @Query("DELETE FROM subreddits") void deleteAllSubreddits(); - @Query("SELECT * from subreddits WHERE name = :namePrefixed") + @Query("SELECT * from subreddits WHERE name = :namePrefixed LIMIT 1") LiveData<SubredditData> getSubredditLiveDataByName(String namePrefixed); @Query("SELECT * from subreddits WHERE name = :namePrefixed LIMIT 1") diff --git a/app/src/main/java/SubredditDatabase/SubredditRepository.java b/app/src/main/java/SubredditDatabase/SubredditRepository.java index 495f6e3d..4e435da9 100644 --- a/app/src/main/java/SubredditDatabase/SubredditRepository.java +++ b/app/src/main/java/SubredditDatabase/SubredditRepository.java @@ -20,14 +20,14 @@ public class SubredditRepository { } public void insert(SubredditData subredditData) { - new SubredditRepository.insertAsyncTask(mSubredditDao).execute(subredditData); + new InsertAsyncTask(mSubredditDao).execute(subredditData); } - private static class insertAsyncTask extends AsyncTask<SubredditData, Void, Void> { + private static class InsertAsyncTask extends AsyncTask<SubredditData, Void, Void> { private SubredditDao mAsyncTaskDao; - insertAsyncTask(SubredditDao dao) { + InsertAsyncTask(SubredditDao dao) { mAsyncTaskDao = dao; } diff --git a/app/src/main/java/SubredditDatabase/SubredditViewModel.java b/app/src/main/java/SubredditDatabase/SubredditViewModel.java index a9d176b3..19c2d726 100644 --- a/app/src/main/java/SubredditDatabase/SubredditViewModel.java +++ b/app/src/main/java/SubredditDatabase/SubredditViewModel.java @@ -11,7 +11,7 @@ public class SubredditViewModel extends AndroidViewModel { private SubredditRepository mSubredditRepository; private LiveData<SubredditData> mSubredditLiveData; - SubredditViewModel(Application application, String id) { + public SubredditViewModel(Application application, String id) { super(application); mSubredditRepository = new SubredditRepository(application, id); mSubredditLiveData = mSubredditRepository.getSubredditLiveData(); diff --git a/app/src/main/java/SubscribedUserDatabase/SubscribedUserDao.java b/app/src/main/java/SubscribedUserDatabase/SubscribedUserDao.java index 2b61a666..83bdf6fe 100644 --- a/app/src/main/java/SubscribedUserDatabase/SubscribedUserDao.java +++ b/app/src/main/java/SubscribedUserDatabase/SubscribedUserDao.java @@ -16,6 +16,12 @@ public interface SubscribedUserDao { @Query("DELETE FROM subscribed_users") void deleteAllSubscribedUsers(); - @Query("SELECT * from subscribed_users ORDER BY name COLLATE NOCASE ASC") + @Query("SELECT * FROM subscribed_users ORDER BY name COLLATE NOCASE ASC") LiveData<List<SubscribedUserData>> getAllSubscribedUsers(); + + @Query("SELECT * FROM subscribed_users WHERE name = :userName LIMIT 1") + SubscribedUserData getSubscribedUser(String userName); + + @Query("DELETE FROM subscribed_users WHERE name = :userName") + void deleteSubscribedUser(String userName); } diff --git a/app/src/main/java/SubscribedUserDatabase/SubscribedUserData.java b/app/src/main/java/SubscribedUserDatabase/SubscribedUserData.java index 8494e784..41947efe 100644 --- a/app/src/main/java/SubscribedUserDatabase/SubscribedUserData.java +++ b/app/src/main/java/SubscribedUserDatabase/SubscribedUserData.java @@ -9,24 +9,17 @@ import android.support.annotation.NonNull; public class SubscribedUserData { @PrimaryKey @NonNull - @ColumnInfo(name = "id") - private String id; @ColumnInfo(name = "name") private String name; @ColumnInfo(name = "icon") private String iconUrl; - public SubscribedUserData(@NonNull String id, String name, String iconUrl) { - this.id = id; + public SubscribedUserData(@NonNull String name, String iconUrl) { this.name = name; this.iconUrl = iconUrl; } @NonNull - public String getId() { - return id; - } - public String getName() { return name; } diff --git a/app/src/main/java/User/UserDao.java b/app/src/main/java/User/UserDao.java index ec6bb7e2..7aba086d 100644 --- a/app/src/main/java/User/UserDao.java +++ b/app/src/main/java/User/UserDao.java @@ -1,5 +1,6 @@ package User; +import android.arch.lifecycle.LiveData; import android.arch.persistence.room.Dao; import android.arch.persistence.room.Insert; import android.arch.persistence.room.OnConflictStrategy; @@ -8,11 +9,14 @@ import android.arch.persistence.room.Query; @Dao public interface UserDao { @Insert(onConflict = OnConflictStrategy.REPLACE) - void insert(User user); + void insert(UserData userData); @Query("DELETE FROM users") void deleteAllUsers(); - @Query("SELECT * FROM users WHERE user_name = :userName LIMIT 1") - User getUserData(String userName); + @Query("SELECT * FROM users WHERE name = :userName LIMIT 1") + LiveData<UserData> getUserLiveData(String userName); + + @Query("SELECT * FROM users WHERE name = :userName LIMIT 1") + UserData getUserData(String userName); } diff --git a/app/src/main/java/User/User.java b/app/src/main/java/User/UserData.java index 3fd8dcb3..89eafb96 100644 --- a/app/src/main/java/User/User.java +++ b/app/src/main/java/User/UserData.java @@ -2,17 +2,12 @@ package User; import android.arch.persistence.room.ColumnInfo; import android.arch.persistence.room.Entity; -import android.arch.persistence.room.PrimaryKey; import android.support.annotation.NonNull; +import SubscribedUserDatabase.SubscribedUserData; + @Entity(tableName = "users") -public class User { - @PrimaryKey - @NonNull - @ColumnInfo(name = "user_name") - private String userName; - @ColumnInfo(name = "icon") - private String icon; +public class UserData extends SubscribedUserData { @ColumnInfo(name = "banner") private String banner; @ColumnInfo(name = "karma") @@ -22,24 +17,14 @@ public class User { @ColumnInfo(name = "is_friend") private boolean isFriend; - User(@NonNull String userName, String icon, String banner, int karma, boolean isGold, boolean isFriend) { - this.userName = userName; - this.icon = icon; + public UserData(@NonNull String name, String iconUrl, String banner, int karma, boolean isGold, boolean isFriend) { + super(name, iconUrl); this.banner = banner; this.karma = karma; this.isGold = isGold; this.isFriend = isFriend; } - @NonNull - public String getUserName() { - return userName; - } - - public String getIcon() { - return icon; - } - public String getBanner() { return banner; } diff --git a/app/src/main/java/User/UserRepository.java b/app/src/main/java/User/UserRepository.java new file mode 100644 index 00000000..d505db2b --- /dev/null +++ b/app/src/main/java/User/UserRepository.java @@ -0,0 +1,39 @@ +package User; + +import android.app.Application; +import android.arch.lifecycle.LiveData; +import android.os.AsyncTask; + +public class UserRepository { + private UserDao mUserDao; + private LiveData<UserData> mUserLiveData; + + UserRepository(Application application, String userName) { + mUserDao = UserRoomDatabase.getDatabase(application).userDao(); + + mUserLiveData = mUserDao.getUserLiveData(userName); + } + + LiveData<UserData> getUserLiveData() { + return mUserLiveData; + } + + public void insert(UserData userData) { + new InsertAsyncTask(mUserDao).execute(userData); + } + + private static class InsertAsyncTask extends AsyncTask<UserData, Void, Void> { + + private UserDao mAsyncTaskDao; + + InsertAsyncTask(UserDao dao) { + mAsyncTaskDao = dao; + } + + @Override + protected Void doInBackground(final UserData... params) { + mAsyncTaskDao.insert(params[0]); + return null; + } + } +} diff --git a/app/src/main/java/User/UserRoomDatabase.java b/app/src/main/java/User/UserRoomDatabase.java index 31ca1259..288400a6 100644 --- a/app/src/main/java/User/UserRoomDatabase.java +++ b/app/src/main/java/User/UserRoomDatabase.java @@ -5,7 +5,7 @@ import android.arch.persistence.room.Room; import android.arch.persistence.room.RoomDatabase; import android.content.Context; -@Database(entities = {User.class}, version = 1) +@Database(entities = {UserData.class}, version = 1) public abstract class UserRoomDatabase extends RoomDatabase { private static UserRoomDatabase INSTANCE; diff --git a/app/src/main/java/User/UserViewModel.java b/app/src/main/java/User/UserViewModel.java new file mode 100644 index 00000000..a006e253 --- /dev/null +++ b/app/src/main/java/User/UserViewModel.java @@ -0,0 +1,48 @@ +package User; + +import android.app.Application; +import android.arch.lifecycle.AndroidViewModel; +import android.arch.lifecycle.LiveData; +import android.arch.lifecycle.ViewModel; +import android.arch.lifecycle.ViewModelProvider; +import android.support.annotation.NonNull; + +import SubredditDatabase.SubredditViewModel; + +public class UserViewModel extends AndroidViewModel { + private UserRepository mSubredditRepository; + private LiveData<UserData> mUserLiveData; + + public UserViewModel(Application application, String id) { + super(application); + mSubredditRepository = new UserRepository(application, id); + mUserLiveData = mSubredditRepository.getUserLiveData(); + } + + public LiveData<UserData> getUserLiveData() { + return mUserLiveData; + } + + public void insert(UserData userData) { + mSubredditRepository.insert(userData); + } + + public static class Factory extends ViewModelProvider.NewInstanceFactory { + + @NonNull + private final Application mApplication; + + private final String userName; + + public Factory(@NonNull Application application, String userName) { + mApplication = application; + this.userName = userName; + } + + @Override + public <T extends ViewModel> T create(Class<T> modelClass) { + //noinspection unchecked + return (T) new UserViewModel(mApplication, userName); + } + } +} diff --git a/app/src/main/java/User/FetchUserData.java b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchUserData.java index edaa3b14..9bfcf7c3 100644 --- a/app/src/main/java/User/FetchUserData.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/FetchUserData.java @@ -1,16 +1,16 @@ -package User; +package ml.docilealligator.infinityforreddit; import android.support.annotation.NonNull; import android.util.Log; -import ml.docilealligator.infinityforreddit.RedditAPI; +import User.UserData; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Retrofit; public class FetchUserData { public interface FetchUserDataListener { - void onFetchUserDataSuccess(User user); + void onFetchUserDataSuccess(UserData userData); void onFetchUserDataFail(); } @@ -23,10 +23,10 @@ public class FetchUserData { @Override public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) { if(response.isSuccessful()) { - ParseUserData.parseMyInfo(response.body(), new ParseUserData.ParseUserDataListener() { + ParseUserData.parseUserData(response.body(), new ParseUserData.ParseUserDataListener() { @Override - public void onParseUserDataSuccess(User user) { - fetchUserDataListener.onFetchUserDataSuccess(user); + public void onParseUserDataSuccess(UserData userData) { + fetchUserDataListener.onFetchUserDataSuccess(userData); } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/InsertUserDataAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/InsertUserDataAsyncTask.java index 823e014e..6db03920 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/InsertUserDataAsyncTask.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/InsertUserDataAsyncTask.java @@ -2,27 +2,27 @@ package ml.docilealligator.infinityforreddit; import android.os.AsyncTask; -import User.User; +import User.UserData; import User.UserDao; public class InsertUserDataAsyncTask extends AsyncTask<Void, Void, Void> { private UserDao userDao; - private User user; + private UserData userData; private InsertUserDataCallback insertUserDataCallback; public interface InsertUserDataCallback { void insertSuccess(); } - public InsertUserDataAsyncTask(UserDao userDao, User user, InsertUserDataCallback insertUserDataCallback) { + public InsertUserDataAsyncTask(UserDao userDao, UserData userData, InsertUserDataCallback insertUserDataCallback) { this.userDao = userDao; - this.user = user; + this.userData = userData; this.insertUserDataCallback = insertUserDataCallback; } @Override protected Void doInBackground(Void... voids) { - userDao.insert(user); + userDao.insert(userData); return null; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/LoadUserDataAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/LoadUserDataAsyncTask.java index be8c182c..704c3e08 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/LoadUserDataAsyncTask.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/LoadUserDataAsyncTask.java @@ -2,8 +2,7 @@ package ml.docilealligator.infinityforreddit; import android.os.AsyncTask; -import User.FetchUserData; -import User.User; +import User.UserData; import User.UserDao; import retrofit2.Retrofit; @@ -29,7 +28,7 @@ public class LoadUserDataAsyncTask extends AsyncTask<Void, Void, Void> { @Override protected Void doInBackground(Void... voids) { if(userDao.getUserData(userName) != null) { - iconImageUrl = userDao.getUserData(userName).getIcon(); + iconImageUrl = userDao.getUserData(userName).getIconUrl(); hasUserInDb = true; } else { hasUserInDb = false; @@ -45,13 +44,8 @@ public class LoadUserDataAsyncTask extends AsyncTask<Void, Void, Void> { } else { FetchUserData.fetchUserData(retrofit, userName, new FetchUserData.FetchUserDataListener() { @Override - public void onFetchUserDataSuccess(User user) { - new InsertUserDataAsyncTask(userDao, user, new InsertUserDataAsyncTask.InsertUserDataCallback() { - @Override - public void insertSuccess() { - loadUserDataAsyncTaskListener.loadUserDataSuccess(user.getIcon()); - } - }).execute(); + public void onFetchUserDataSuccess(UserData userData) { + new InsertUserDataAsyncTask(userDao, userData, () -> loadUserDataAsyncTaskListener.loadUserDataSuccess(userData.getIconUrl())).execute(); } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java index 773ec885..7254bfcf 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java @@ -20,6 +20,7 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import com.bumptech.glide.Glide; @@ -61,6 +62,7 @@ public class MainActivity extends AppCompatActivity { @BindView(R.id.subscriptions_label_main_activity) TextView subscriptionsLabelTextView; @BindView(R.id.subscribed_user_recycler_view_main_activity) RecyclerView subscribedUserRecyclerView; @BindView(R.id.following_label_main_activity) TextView followingLabelTextView; + @BindView(R.id.profile_linear_layout_main_activity) LinearLayout profileLinearLayout; private TextView mNameTextView; private TextView mKarmaTextView; @@ -153,13 +155,14 @@ public class MainActivity extends AppCompatActivity { glide.load(mBannerImageUrl).into(mBannerImageView); } - final SubscribedSubredditRecyclerViewAdapter subredditadapter = new SubscribedSubredditRecyclerViewAdapter(this, - new SubscribedSubredditRecyclerViewAdapter.OnItemClickListener() { - @Override - public void onClick() { - drawer.closeDrawers(); - } - }); + profileLinearLayout.setOnClickListener(view -> { + Intent intent = new Intent(MainActivity.this, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mName); + startActivity(intent); + }); + + final SubscribedSubredditRecyclerViewAdapter subredditadapter = + new SubscribedSubredditRecyclerViewAdapter(this, drawer::closeDrawers); subscribedSubredditRecyclerView.setAdapter(subredditadapter); mSubscribedSubredditViewModel = ViewModelProviders.of(this).get(SubscribedSubredditViewModel.class); @@ -176,13 +179,8 @@ public class MainActivity extends AppCompatActivity { } }); - final SubscribedUserRecyclerViewAdapter userAdapter = new SubscribedUserRecyclerViewAdapter(this, - new SubscribedUserRecyclerViewAdapter.OnItemClickListener() { - @Override - public void onClick() { - drawer.closeDrawers(); - } - }); + final SubscribedUserRecyclerViewAdapter userAdapter = + new SubscribedUserRecyclerViewAdapter(this, drawer::closeDrawers); subscribedUserRecyclerView.setAdapter(userAdapter); mSubscribedUserViewModel = ViewModelProviders.of(this).get(SubscribedUserViewModel.class); mSubscribedUserViewModel.getAllSubscribedUsers().observe(this, new Observer<List<SubscribedUserData>>() { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/NetworkComponent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/NetworkComponent.java index 354dfbea..747dead0 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/NetworkComponent.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/NetworkComponent.java @@ -11,4 +11,5 @@ interface NetworkComponent { void inject(PostFragment postFragment); void inject(ViewPostDetailActivity viewPostDetailActivity); void inject(ViewSubredditDetailActivity viewSubredditDetailActivity); + void inject(ViewUserDetailActivity viewUserDetailActivity); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubscribedThing.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubscribedThing.java index 6b9ef580..fc69c82b 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubscribedThing.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseSubscribedThing.java @@ -94,7 +94,7 @@ class ParseSubscribedThing { if(data.getString(JSONUtils.SUBREDDIT_TYPE_KEY) .equals(JSONUtils.SUBREDDIT_TYPE_VALUE_USER)) { //It's a user - newSubscribedUserData.add(new SubscribedUserData(id, name.substring(2), iconUrl)); + newSubscribedUserData.add(new SubscribedUserData(name.substring(2), iconUrl)); } else { String subredditFullName = data.getString(JSONUtils.DISPLAY_NAME); String description = data.getString(JSONUtils.PUBLIC_DESCRIPTION_KEY).trim(); diff --git a/app/src/main/java/User/ParseUserData.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseUserData.java index b6a7a39c..12402f03 100644 --- a/app/src/main/java/User/ParseUserData.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParseUserData.java @@ -1,4 +1,4 @@ -package User; +package ml.docilealligator.infinityforreddit; import android.os.AsyncTask; import android.util.Log; @@ -6,15 +6,15 @@ import android.util.Log; import org.json.JSONException; import org.json.JSONObject; -import ml.docilealligator.infinityforreddit.JSONUtils; +import User.UserData; public class ParseUserData { interface ParseUserDataListener { - void onParseUserDataSuccess(User user); + void onParseUserDataSuccess(UserData userData); void onParseUserDataFail(); } - static void parseMyInfo(String response, ParseUserDataListener parseUserDataListener) { + static void parseUserData(String response, ParseUserDataListener parseUserDataListener) { new ParseUserDataAsyncTask(response, parseUserDataListener).execute(); } @@ -23,15 +23,16 @@ public class ParseUserData { private ParseUserDataListener parseUserDataListener; private boolean parseFailed; - private User user; + private UserData userData; ParseUserDataAsyncTask(String response, ParseUserDataListener parseUserDataListener){ try { + Log.i("response", response); jsonResponse = new JSONObject(response); this.parseUserDataListener = parseUserDataListener; parseFailed = false; } catch (JSONException e) { - Log.i("user data json error", e.getMessage()); + Log.i("userdata json error", e.getMessage()); parseUserDataListener.onParseUserDataFail(); } } @@ -43,7 +44,7 @@ public class ParseUserData { String userName = jsonResponse.getString(JSONUtils.NAME_KEY); String iconImageUrl = jsonResponse.getString(JSONUtils.ICON_IMG_KEY); String bannerImageUrl = ""; - if(!jsonResponse.isNull(JSONUtils.SUBREDDIT_KEY)) { + if(jsonResponse.has(JSONUtils.SUBREDDIT_KEY) && !jsonResponse.isNull(JSONUtils.SUBREDDIT_KEY)) { bannerImageUrl = jsonResponse.getJSONObject(JSONUtils.SUBREDDIT_KEY).getString(JSONUtils.BANNER_IMG_KEY); } int linkKarma = jsonResponse.getInt(JSONUtils.LINK_KARMA_KEY); @@ -52,7 +53,7 @@ public class ParseUserData { boolean isGold = jsonResponse.getBoolean(JSONUtils.IS_GOLD_KEY); boolean isFriend = jsonResponse.getBoolean(JSONUtils.IS_FRIEND_KEY); - user = new User(userName, iconImageUrl, bannerImageUrl, karma, isGold, isFriend); + userData = new UserData(userName, iconImageUrl, bannerImageUrl, karma, isGold, isFriend); } catch (JSONException e) { parseFailed = true; Log.i("parse user data error", e.getMessage()); @@ -63,7 +64,7 @@ public class ParseUserData { @Override protected void onPostExecute(Void aVoid) { if(!parseFailed) { - parseUserDataListener.onParseUserDataSuccess(user); + parseUserDataListener.onParseUserDataSuccess(userData); } else { parseUserDataListener.onParseUserDataFail(); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostRecyclerViewAdapter.java index bc851a8f..35e95b75 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/PostRecyclerViewAdapter.java @@ -300,6 +300,7 @@ class PostRecyclerViewAdapter extends PagedListAdapter<Post, RecyclerView.ViewHo if(canStartActivity) { canStartActivity = false; Intent intent = new Intent(mContext, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, post.getAuthor()); mContext.startActivity(intent); } }); @@ -310,6 +311,7 @@ class PostRecyclerViewAdapter extends PagedListAdapter<Post, RecyclerView.ViewHo if(canStartActivity) { canStartActivity = false; Intent intent = new Intent(mContext, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, post.getAuthor()); mContext.startActivity(intent); } }); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java index 25b74317..25f83bbd 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java @@ -3,11 +3,13 @@ package ml.docilealligator.infinityforreddit; import java.util.Map; import retrofit2.Call; +import retrofit2.http.DELETE; import retrofit2.http.FieldMap; import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; import retrofit2.http.HeaderMap; import retrofit2.http.POST; +import retrofit2.http.PUT; import retrofit2.http.Path; import retrofit2.http.Query; @@ -45,4 +47,10 @@ public interface RedditAPI { @FormUrlEncoded @POST("api/subscribe") Call<String> subredditSubscription(@HeaderMap Map<String, String> headers, @FieldMap Map<String, String> params); + + @PUT("/api/v1/me/friends/username") + Call<String> subscribeUser(@HeaderMap Map<String, String> headers); + + @DELETE("/api/v1/me/friends/username") + Call<String> unsubscribeUser(@HeaderMap Map<String, String> headers); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditUtils.java index d598f684..627b7f10 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditUtils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditUtils.java @@ -30,7 +30,7 @@ public class RedditUtils { 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_KEY = "UserData-Agent"; static final String USER_AGENT = ""; static final String GRANT_TYPE_KEY = "grant_type"; @@ -47,6 +47,7 @@ public class RedditUtils { static final String ACTION_KEY = "action"; static final String SR_NAME_KEY = "sr_name"; + static final String SR_KEY = "sr"; static Map<String, String> getHttpBasicAuthHeader() { Map<String, String> params = new HashMap<>(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedUserRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedUserRecyclerViewAdapter.java index 013d75c1..bec617c6 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedUserRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedUserRecyclerViewAdapter.java @@ -1,6 +1,7 @@ package ml.docilealligator.infinityforreddit; import android.content.Context; +import android.content.Intent; import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; import android.support.annotation.NonNull; @@ -27,6 +28,7 @@ import jp.wasabeef.glide.transformations.RoundedCornersTransformation; public class SubscribedUserRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private List<SubscribedUserData> mSubscribedUserData; + private Context mContext; private RequestManager glide; private OnItemClickListener mOnItemClickListener; @@ -35,6 +37,7 @@ public class SubscribedUserRecyclerViewAdapter extends RecyclerView.Adapter<Recy } SubscribedUserRecyclerViewAdapter(Context context, OnItemClickListener onItemClickListener) { + mContext = context; glide = Glide.with(context.getApplicationContext()); mOnItemClickListener = onItemClickListener; } @@ -47,13 +50,11 @@ public class SubscribedUserRecyclerViewAdapter extends RecyclerView.Adapter<Recy @Override public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder viewHolder, int i) { - viewHolder.itemView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - //Need to be implemented - - mOnItemClickListener.onClick(); - } + viewHolder.itemView.setOnClickListener(view -> { + Intent intent = new Intent(mContext, ViewUserDetailActivity.class); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, mSubscribedUserData.get(viewHolder.getAdapterPosition()).getName()); + mContext.startActivity(intent); + mOnItemClickListener.onClick(); }); if(!mSubscribedUserData.get(i).getIconUrl().equals("")) { glide.load(mSubscribedUserData.get(i).getIconUrl()) diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/UserFollowing.java b/app/src/main/java/ml/docilealligator/infinityforreddit/UserFollowing.java new file mode 100644 index 00000000..c5af5a26 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/UserFollowing.java @@ -0,0 +1,117 @@ +package ml.docilealligator.infinityforreddit; + +import android.content.SharedPreferences; +import android.os.AsyncTask; +import android.support.annotation.NonNull; +import android.util.Log; + +import java.util.HashMap; +import java.util.Map; + +import SubscribedUserDatabase.SubscribedUserDao; +import SubscribedUserDatabase.SubscribedUserData; +import User.UserData; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Retrofit; + +class UserFollowing { + interface UserFollowingListener { + void onUserFollowingSuccess(); + void onUserFollowingFail(); + } + + static void followUser(Retrofit oauthRetrofit, Retrofit retrofit, + SharedPreferences authInfoSharedPreferences, String userName, + SubscribedUserDao subscribedUserDao, + UserFollowingListener userFollowingListener) { + userFollowing(oauthRetrofit, retrofit, authInfoSharedPreferences, userName, "sub", + subscribedUserDao, userFollowingListener); + } + + static void unfollowUser(Retrofit oauthRetrofit, Retrofit retrofit, + SharedPreferences authInfoSharedPreferences, String userName, + SubscribedUserDao subscribedUserDao, + UserFollowingListener userFollowingListener) { + userFollowing(oauthRetrofit, retrofit, authInfoSharedPreferences, userName, "unsub", + subscribedUserDao, userFollowingListener); + } + + private static void userFollowing(Retrofit oauthRetrofit, Retrofit retrofit, SharedPreferences authInfoSharedPreferences, + String userName, String action, SubscribedUserDao subscribedUserDao, + UserFollowingListener userFollowingListener) { + RedditAPI api = oauthRetrofit.create(RedditAPI.class); + + String accessToken = authInfoSharedPreferences.getString(SharedPreferencesUtils.ACCESS_TOKEN_KEY, ""); + + Map<String, String> params = new HashMap<>(); + params.put(RedditUtils.ACTION_KEY, action); + params.put(RedditUtils.SR_KEY, "u/" + userName); + + Call<String> subredditSubscriptionCall = api.subredditSubscription(RedditUtils.getOAuthHeader(accessToken), params); + subredditSubscriptionCall.enqueue(new Callback<String>() { + @Override + public void onResponse(@NonNull Call<String> call, @NonNull retrofit2.Response<String> response) { + if(response.isSuccessful()) { + if(action.equals("sub")) { + FetchUserData.fetchUserData(retrofit, userName, new FetchUserData.FetchUserDataListener() { + @Override + public void onFetchUserDataSuccess(UserData userData) { + new UpdateSubscriptionAsyncTask(subscribedUserDao, userData, true).execute(); + } + + @Override + public void onFetchUserDataFail() { + + } + }); + } else { + new UpdateSubscriptionAsyncTask(subscribedUserDao, userName, false).execute(); + } + userFollowingListener.onUserFollowingSuccess(); + } else { + Log.i("call failed", response.message()); + userFollowingListener.onUserFollowingFail(); + } + } + + @Override + public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { + Log.i("call failed", t.getMessage()); + userFollowingListener.onUserFollowingFail(); + } + }); + } + + private static class UpdateSubscriptionAsyncTask extends AsyncTask<Void, Void, Void> { + + private SubscribedUserDao subscribedUserDao; + private String userName; + private SubscribedUserData subscribedUserData; + private boolean isSubscribing; + + UpdateSubscriptionAsyncTask(SubscribedUserDao subscribedUserDao, String userName, + boolean isSubscribing) { + this.subscribedUserDao = subscribedUserDao; + this.userName = userName; + this.isSubscribing = isSubscribing; + } + + UpdateSubscriptionAsyncTask(SubscribedUserDao subscribedUserDao, SubscribedUserData subscribedUserData, + boolean isSubscribing) { + this.subscribedUserDao = subscribedUserDao; + this.subscribedUserData = subscribedUserData; + this.isSubscribing = isSubscribing; + } + + @Override + protected Void doInBackground(Void... voids) { + if(isSubscribing) { + subscribedUserDao.insert(subscribedUserData); + } else { + subscribedUserDao.deleteSubscribedUser(userName);; + } + return null; + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewSubredditDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewSubredditDetailActivity.java index cf9b0f9a..67042e55 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewSubredditDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewSubredditDetailActivity.java @@ -22,7 +22,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; -import android.widget.Toast; import com.bumptech.glide.Glide; import com.bumptech.glide.RequestManager; @@ -104,11 +103,11 @@ public class ViewSubredditDetailActivity extends AppCompatActivity { ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); params.topMargin = statusBarHeight; - final String subredditName = getIntent().getExtras().getString(EXTRA_SUBREDDIT_NAME_KEY); + String subredditName = getIntent().getExtras().getString(EXTRA_SUBREDDIT_NAME_KEY); - final String title = "r/" + subredditName; - final CollapsingToolbarLayout collapsingToolbarLayout = findViewById(R.id.collapsing_toolbar_layout_view_subreddit_detail_activity); - final AppBarLayout appBarLayout = findViewById(R.id.app_bar_layout_view_subreddit_detail_activity); + String title = "r/" + subredditName; + CollapsingToolbarLayout collapsingToolbarLayout = findViewById(R.id.collapsing_toolbar_layout_view_subreddit_detail_activity); + AppBarLayout appBarLayout = findViewById(R.id.app_bar_layout_view_subreddit_detail_activity); appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { int previousVerticalOffset = 0; @@ -136,10 +135,10 @@ public class ViewSubredditDetailActivity extends AppCompatActivity { }); subscribedSubredditDao = SubscribedSubredditRoomDatabase.getDatabase(this).subscribedSubredditDao(); - glide = Glide.with(ViewSubredditDetailActivity.this); + glide = Glide.with(this); - SubredditViewModel.Factory factory = new SubredditViewModel.Factory(getApplication(), subredditName); - mSubredditViewModel = ViewModelProviders.of(this, factory).get(SubredditViewModel.class); + mSubredditViewModel = ViewModelProviders.of(this, new SubredditViewModel.Factory(getApplication(), subredditName)) + .get(SubredditViewModel.class); mSubredditViewModel.getSubredditLiveData().observe(this, subredditData -> { if(subredditData != null) { if(subredditData.getBannerUrl().equals("")) { @@ -279,7 +278,7 @@ public class ViewSubredditDetailActivity extends AppCompatActivity { @Override public void onParseSubredditDataFail() { - Toast.makeText(ViewSubredditDetailActivity.this, "Cannot fetch subreddit info", Toast.LENGTH_SHORT).show(); + makeSnackbar(R.string.cannot_fetch_subreddit_info); } }); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java index 0ec59030..8b3fa0a1 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java @@ -1,13 +1,78 @@ package ml.docilealligator.infinityforreddit; +import android.arch.lifecycle.ViewModelProviders; +import android.content.Intent; +import android.content.SharedPreferences; +import android.graphics.drawable.Animatable; +import android.graphics.drawable.Drawable; +import android.os.AsyncTask; import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.design.chip.Chip; +import android.support.design.widget.AppBarLayout; +import android.support.design.widget.CollapsingToolbarLayout; +import android.support.design.widget.CoordinatorLayout; +import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; +import android.view.MenuItem; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +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.RequestOptions; +import com.bumptech.glide.request.target.Target; +import com.felipecsl.gifimageview.library.GifImageView; + +import javax.inject.Inject; +import javax.inject.Named; + +import SubscribedUserDatabase.SubscribedUserDao; +import SubscribedUserDatabase.SubscribedUserData; +import SubscribedUserDatabase.SubscribedUserRoomDatabase; +import User.UserDao; +import User.UserData; +import User.UserRoomDatabase; +import User.UserViewModel; +import butterknife.BindView; +import butterknife.ButterKnife; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; +import retrofit2.Retrofit; public class ViewUserDetailActivity extends AppCompatActivity { static final String EXTRA_USER_NAME_KEY = "EUNK"; + @BindView(R.id.coordinator_layout_view_user_detail_activity) CoordinatorLayout coordinatorLayout; + @BindView(R.id.banner_image_view_view_user_detail_activity) ImageView bannerImageView; + @BindView(R.id.icon_gif_image_view_view_user_detail_activity) GifImageView iconGifImageView; + @BindView(R.id.user_name_text_view_view_user_detail_activity) TextView userNameTextView; + @BindView(R.id.subscribe_user_chip_view_user_detail_activity) Chip subscribeUserChip; + @BindView(R.id.karma_text_view_view_user_detail_activity) TextView karmaTextView; + + private SubscribedUserDao subscribedUserDao; + private RequestManager glide; + private UserViewModel userViewModel; + + private boolean subscriptionReady = false; + + @Inject + @Named("no_oauth") + Retrofit mRetrofit; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + @Named("auth_info") + SharedPreferences sharedPreferences; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -15,6 +80,254 @@ public class ViewUserDetailActivity extends AppCompatActivity { Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); - + ButterKnife.bind(this); + + ((Infinity) getApplication()).getmNetworkComponent().inject(this); + + setSupportActionBar(toolbar); + + //Get status bar height + int statusBarHeight = 0; + int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (resourceId > 0) { + statusBarHeight = getResources().getDimensionPixelSize(resourceId); + } + + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams(); + params.topMargin = statusBarHeight; + + String userName = getIntent().getExtras().getString(EXTRA_USER_NAME_KEY); + String title = "u/" + userName; + + CollapsingToolbarLayout collapsingToolbarLayout = findViewById(R.id.collapsing_toolbar_layout_view_user_detail_activity); + AppBarLayout appBarLayout = findViewById(R.id.app_bar_layout_view_user_detail_activity); + + appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { + int previousVerticalOffset = 0; + int scrollRange = -1; + + @Override + public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { + if(scrollRange == -1) { + scrollRange = appBarLayout.getTotalScrollRange(); + } else { + if(verticalOffset < previousVerticalOffset) { + //Scroll down + if(scrollRange - Math.abs(verticalOffset) <= toolbar.getHeight()) { + collapsingToolbarLayout.setTitle(title); + } + } else { + //Scroll up + if(scrollRange - Math.abs(verticalOffset) > toolbar.getHeight()) { + collapsingToolbarLayout.setTitle(" ");//carefull there should a space between double quote otherwise it wont work + } + } + previousVerticalOffset = verticalOffset; + } + } + }); + + subscribeUserChip.setOnClickListener(view -> { + if(subscriptionReady) { + subscriptionReady = false; + if(subscribeUserChip.getText().equals(getResources().getString(R.string.subscribe))) { + UserFollowing.followUser(mOauthRetrofit, mRetrofit, sharedPreferences, + userName, subscribedUserDao, new UserFollowing.UserFollowingListener() { + @Override + public void onUserFollowingSuccess() { + subscribeUserChip.setText(R.string.unfollow); + subscribeUserChip.setChipBackgroundColor(getResources().getColorStateList(R.color.colorAccent)); + makeSnackbar(R.string.followed); + subscriptionReady = true; + } + + @Override + public void onUserFollowingFail() { + makeSnackbar(R.string.follow_failed); + subscriptionReady = true; + } + }); + } else { + UserFollowing.unfollowUser(mOauthRetrofit, mRetrofit, sharedPreferences, + userName, subscribedUserDao, new UserFollowing.UserFollowingListener() { + @Override + public void onUserFollowingSuccess() { + subscribeUserChip.setText(R.string.follow); + subscribeUserChip.setChipBackgroundColor(getResources().getColorStateList(R.color.colorPrimaryDark)); + makeSnackbar(R.string.unfollowed); + subscriptionReady = true; + } + + @Override + public void onUserFollowingFail() { + makeSnackbar(R.string.unfollow_failed); + subscriptionReady = true; + } + }); + } + } + }); + + subscribedUserDao = SubscribedUserRoomDatabase.getDatabase(this).subscribedUserDao(); + + new CheckIsFollowingUserAsyncTask(subscribedUserDao, userName, new CheckIsFollowingUserAsyncTask.CheckIsFollowingUserListener() { + @Override + public void isSubscribed() { + subscribeUserChip.setText(R.string.unfollow); + subscribeUserChip.setChipBackgroundColor(getResources().getColorStateList(R.color.colorAccent)); + subscriptionReady = true; + } + + @Override + public void isNotSubscribed() { + subscribeUserChip.setText(R.string.follow); + subscribeUserChip.setChipBackgroundColor(getResources().getColorStateList(R.color.colorPrimaryDark)); + subscriptionReady = true; + } + }).execute(); + + glide = Glide.with(this); + + userViewModel = ViewModelProviders.of(this, new UserViewModel.Factory(getApplication(), userName)) + .get(UserViewModel.class); + userViewModel.getUserLiveData().observe(this, userData -> { + if(userData != null) { + if(userData.getBanner().equals("")) { + bannerImageView.setOnClickListener(view -> { + //Do nothing since the user has no banner image + }); + } else { + glide.load(userData.getBanner()).into(bannerImageView); + bannerImageView.setOnClickListener(view -> { + Intent intent = new Intent(this, ViewImageActivity.class); + intent.putExtra(ViewImageActivity.TITLE_KEY, title); + intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, userData.getBanner()); + intent.putExtra(ViewImageActivity.FILE_NAME_KEY, userName + "-banner"); + startActivity(intent); + }); + } + + if(userData.getIconUrl().equals("")) { + glide.load(getDrawable(R.drawable.subreddit_default_icon)) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(216, 0))) + .into(iconGifImageView); + iconGifImageView.setOnClickListener(view -> { + //Do nothing since the user has no icon image + }); + } else { + glide.load(userData.getIconUrl()) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(216, 0))) + .error(glide.load(R.drawable.subreddit_default_icon)) + .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) { + if(resource instanceof Animatable) { + //This is a gif + ((Animatable) resource).start(); + iconGifImageView.startAnimation(); + } + return false; + } + }) + .into(iconGifImageView); + iconGifImageView.setOnClickListener(view -> { + Intent intent = new Intent(this, ViewImageActivity.class); + intent.putExtra(ViewImageActivity.TITLE_KEY, title); + intent.putExtra(ViewImageActivity.IMAGE_URL_KEY, userData.getIconUrl()); + intent.putExtra(ViewImageActivity.FILE_NAME_KEY, userName + "-icon"); + startActivity(intent); + }); + } + + String userFullName = "u/" + userData.getName(); + userNameTextView.setText(userFullName); + String karma = getString(R.string.karma_info, userData.getKarma()); + karmaTextView.setText(karma); + } + }); + + FetchUserData.fetchUserData(mRetrofit, userName, new FetchUserData.FetchUserDataListener() { + @Override + public void onFetchUserDataSuccess(UserData userData) { + new InsertUserDataAsyncTask(UserRoomDatabase.getDatabase(ViewUserDetailActivity.this).userDao(), userData).execute(); + } + + @Override + public void onFetchUserDataFail() { + makeSnackbar(R.string.cannot_fetch_user_info); + } + }); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + } + return false; + } + + private void makeSnackbar(int resId) { + Snackbar.make(coordinatorLayout, resId, Snackbar.LENGTH_SHORT).show(); + } + + private static class InsertUserDataAsyncTask extends AsyncTask<Void, Void, Void> { + + private UserDao userDao; + private UserData subredditData; + + InsertUserDataAsyncTask(UserDao userDao, UserData userData) { + this.userDao = userDao; + this.subredditData = userData; + } + + @Override + protected Void doInBackground(final Void... params) { + userDao.insert(subredditData); + return null; + } + } + + private static class CheckIsFollowingUserAsyncTask extends AsyncTask<Void, Void, Void> { + + private SubscribedUserDao subscribedUserDao; + private String userName; + private SubscribedUserData subscribedUserData; + private CheckIsFollowingUserListener checkIsFollowingUserListener; + + interface CheckIsFollowingUserListener { + void isSubscribed(); + void isNotSubscribed(); + } + + CheckIsFollowingUserAsyncTask(SubscribedUserDao subscribedUserDao, String userName, + CheckIsFollowingUserListener checkIsFollowingUserListener) { + this.subscribedUserDao = subscribedUserDao; + this.userName = userName; + this.checkIsFollowingUserListener = checkIsFollowingUserListener; + } + + @Override + protected Void doInBackground(Void... voids) { + subscribedUserData = subscribedUserDao.getSubscribedUser(userName); + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + if(subscribedUserData != null) { + checkIsFollowingUserListener.isSubscribed(); + } else { + checkIsFollowingUserListener.isNotSubscribed(); + } + } } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 4e6dd8aa..5da5a9d3 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -35,6 +35,7 @@ layout="@layout/nav_header_main" /> <LinearLayout + android:id="@+id/profile_linear_layout_main_activity" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" diff --git a/app/src/main/res/layout/activity_view_user_detail.xml b/app/src/main/res/layout/activity_view_user_detail.xml index 76dbba91..a292d390 100644 --- a/app/src/main/res/layout/activity_view_user_detail.xml +++ b/app/src/main/res/layout/activity_view_user_detail.xml @@ -4,33 +4,97 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:fitsSystemWindows="true" + android:id="@+id/coordinator_layout_view_user_detail_activity" tools:context=".ViewUserDetailActivity"> <android.support.design.widget.AppBarLayout - android:id="@+id/app_bar" + android:id="@+id/app_bar_layout_view_user_detail_activity" android:layout_width="match_parent" - android:layout_height="@dimen/app_bar_height" - android:fitsSystemWindows="true" + android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.design.widget.CollapsingToolbarLayout - android:id="@+id/toolbar_layout" + android:id="@+id/collapsing_toolbar_layout_view_user_detail_activity" android:layout_width="match_parent" android:layout_height="match_parent" - android:fitsSystemWindows="true" app:contentScrim="?attr/colorPrimary" - app:layout_scrollFlags="scroll|exitUntilCollapsed" + app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed" app:toolbarId="@+id/toolbar"> + <RelativeLayout + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <ImageView + android:id="@+id/banner_image_view_view_user_detail_activity" + android:layout_width="match_parent" + android:scaleType="centerCrop" + android:layout_height="180dp" + android:contentDescription="@string/content_description_banner_imageview" /> + + <com.felipecsl.gifimageview.library.GifImageView + android:id="@+id/icon_gif_image_view_view_user_detail_activity" + android:layout_width="72dp" + android:layout_height="72dp" + android:layout_marginTop="-36dp" + app:civ_border_color="@android:color/white" + app:civ_border_width="1dp" + android:layout_below="@id/banner_image_view_view_user_detail_activity" + android:layout_centerHorizontal="true" + android:elevation="4dp" + app:civ_circle_background_color="@android:color/white"/> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:paddingTop="36dp" + android:paddingStart="16dp" + android:paddingEnd="16dp" + android:layout_below="@id/banner_image_view_view_user_detail_activity" + android:background="@android:color/white"> + + <TextView + android:id="@+id/user_name_text_view_view_user_detail_activity" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:textSize="18sp" + android:textColor="@color/colorAccent" + android:layout_gravity="center_horizontal"/> + + <TextView + android:id="@+id/karma_text_view_view_user_detail_activity" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:textColor="@android:color/black" + android:layout_gravity="center_horizontal"/> + + <android.support.design.chip.Chip + android:id="@+id/subscribe_user_chip_view_user_detail_activity" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:layout_marginBottom="16dp" + android:textColor="@android:color/white" + android:layout_gravity="center_horizontal"/> + + </LinearLayout> + + </RelativeLayout> + <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin" - app:popupTheme="@style/AppTheme.PopupOverlay" /> + app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed" + app:popupTheme="@style/AppTheme.PopupOverlay" + app:navigationIcon="?attr/homeAsUpIndicator"/> </android.support.design.widget.CollapsingToolbarLayout> + </android.support.design.widget.AppBarLayout> <include layout="@layout/content_view_user_detail" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7084659c..cab97bbb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -26,6 +26,8 @@ <string name="subscriptions">Subscriptions</string> <string name="subscribers_number_detail">Subscribers: %1$d</string> <string name="online_subscribers_number_detail">Online: %1$d</string> + <string name="cannot_fetch_subreddit_info">Cannot fetch subreddit info</string> + <string name="cannot_fetch_user_info">Cannot fetch user info</string> <string name="gilded">x%1$d</string> <string name="title_activity_view_user_detail">ViewUserDetailActivity</string> @@ -49,15 +51,15 @@ "and use of imagery guide visual treatments. These elements do far more than please the " "eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge " "imagery, large scale typography, and intentional white space create a bold and graphic " - "interface that immerse the user in the experience.\n" - "An emphasis on user actions makes core functionality immediately apparent and provides " - "waypoints for the user.\n\n" + "interface that immerse the userData in the experience.\n" + "An emphasis on userData actions makes core functionality immediately apparent and provides " + "waypoints for the userData.\n\n" "Motion provides meaning.\n\n" - "Motion respects and reinforces the user as the prime mover. Primary user actions are " + "Motion respects and reinforces the userData as the prime mover. Primary userData actions are " "inflection points that initiate motion, transforming the whole design.\n" - "All action takes place in a single environment. Objects are presented to the user without " + "All action takes place in a single environment. Objects are presented to the userData without " "breaking the continuity of experience even as they transform and reorganize.\n" "Motion is meaningful and appropriate, serving to focus attention and maintain continuity. " "Feedback is subtle yet clear. Transitions are efficient yet coherent.\n\n" @@ -96,7 +98,7 @@ "Responsive elevation and dynamic elevation offsets.\n\n" "Some component types have responsive elevation, meaning they change elevation in response " - "to user input (e.g., normal, focused, and pressed) or system events. These elevation " + "to userData input (e.g., normal, focused, and pressed) or system events. These elevation " "changes are consistently implemented using dynamic elevation offsets.\n" "Dynamic elevation offsets are the goal elevation that a component moves towards, relative " "to the component’s resting state. They ensure that elevation changes are consistent " @@ -113,10 +115,10 @@ "whether on a per component basis or using the entire app layout.\n" "On a component level, components can move or be removed before they cause interference. " "For example, a floating action button (FAB) can disappear or move off screen before a " - "user picks up a card, or it can move if a snackbar appears.\n" + "userData picks up a card, or it can move if a snackbar appears.\n" "On the layout level, design your app layout to minimize opportunities for interference. " "For example, position the FAB to one side of stream of a cards so the FAB won’t interfere " - "when a user tries to pick up one of cards.\n\n" + "when a userData tries to pick up one of cards.\n\n" </string> <string name="subscribe">Subscribe</string> @@ -126,5 +128,12 @@ <string name="unsubscribed">Unsubscribed</string>" <string name="unsubscribe_failed">Unsubscribe Failed</string> + <string name="follow">Follow</string> + <string name="unfollow">Unfollow</string> + <string name="followed">Followed</string> + <string name="follow_failed">Following Failed</string> + <string name="unfollowed">Unfollowed</string> + <string name="unfollow_failed">Unfollowing Failed</string> + <string name="content_description_banner_imageview">Subreddit Banner Image</string> </resources> @@ -119,7 +119,7 @@ if $cygwin ; then SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments + # Add a userData-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi |