changed how comments are handled such as delete, edit & reply, now you can add reactions to comments, left issue,pr & commits descriptions. #194. probably this will be closed tomorrow.

This commit is contained in:
Kosh 2017-03-29 22:36:35 +08:00
parent 19a168174c
commit 2a972785d2
27 changed files with 601 additions and 161 deletions

View File

@ -197,9 +197,9 @@
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE"/>
</intent-filter>
</service>
<service android:name=".provider.tasks.notification.ReadNotificationService"/>
<service android:name=".provider.tasks.git.GithubActionService"/>
<service android:name=".provider.tasks.git.ReactionService"/>
</application>
</manifest>

View File

@ -0,0 +1,30 @@
package com.fastaccess.data.dao;
import android.os.Parcel;
import android.os.Parcelable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* Created by Kosh on 29 Mar 2017, 9:50 PM
*/
@Getter @Setter @NoArgsConstructor @AllArgsConstructor public class PostReactionModel implements Parcelable {
private String content;
@Override public int describeContents() { return 0; }
@Override public void writeToParcel(Parcel dest, int flags) {dest.writeString(this.content);}
protected PostReactionModel(Parcel in) {this.content = in.readString();}
public static final Parcelable.Creator<PostReactionModel> CREATOR = new Parcelable.Creator<PostReactionModel>() {
@Override public PostReactionModel createFromParcel(Parcel source) {return new PostReactionModel(source);}
@Override public PostReactionModel[] newArray(int size) {return new PostReactionModel[size];}
};
}

View File

@ -14,6 +14,7 @@ import lombok.Setter;
@Getter @Setter public class ReactionsModel implements Parcelable {
private long id;
private String url;
private int total_count;
@SerializedName("+1") private int plusOne; // FIXME check this code
@ -23,9 +24,12 @@ import lombok.Setter;
private int confused;
private int heart;
public ReactionsModel() {}
@Override public int describeContents() { return 0; }
@Override public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(this.id);
dest.writeString(this.url);
dest.writeInt(this.total_count);
dest.writeInt(this.plusOne);
@ -36,9 +40,8 @@ import lombok.Setter;
dest.writeInt(this.heart);
}
public ReactionsModel() {}
protected ReactionsModel(Parcel in) {
this.id = in.readLong();
this.url = in.readString();
this.total_count = in.readInt();
this.plusOne = in.readInt();
@ -49,7 +52,7 @@ import lombok.Setter;
this.heart = in.readInt();
}
public static final Parcelable.Creator<ReactionsModel> CREATOR = new Parcelable.Creator<ReactionsModel>() {
public static final Creator<ReactionsModel> CREATOR = new Creator<ReactionsModel>() {
@Override public ReactionsModel createFromParcel(Parcel source) {return new ReactionsModel(source);}
@Override public ReactionsModel[] newArray(int size) {return new ReactionsModel[size];}

View File

@ -0,0 +1,23 @@
package com.fastaccess.data.dao.types;
/**
* Created by Kosh on 29 Mar 2017, 10:11 PM
*/
public enum ReactionTypes {
HEART("heart"),
HOORAY("hooray"),
PLUS_ONE("+1"),
MINUS_ONE("-1"),
CONFUSED("confused"),
LAUGH("laugh");
private String content;
ReactionTypes(String content) {this.content = content;}
public String getContent() {
return content;
}
}

View File

@ -0,0 +1,32 @@
package com.fastaccess.data.service;
import android.support.annotation.NonNull;
import com.fastaccess.data.dao.PostReactionModel;
import retrofit2.http.Body;
import retrofit2.http.Headers;
import retrofit2.http.POST;
import retrofit2.http.Path;
import rx.Observable;
/**
* Created by Kosh on 29 Mar 2017, 9:48 PM
*/
public interface ReactionsService {
@POST("/repos/{owner}/{repo}/issues/comments/{id}/reactions")
@Headers("Accept: application/vnd.github.squirrel-girl-preview")
Observable<Boolean> postIssueReaction(@NonNull @Body PostReactionModel body,
@NonNull @Path("owner") String owner,
@Path("repo") @NonNull String repo,
@Path("id") long id);
@POST("/repos/{owner}/{repo}/comments/{id}/reactions")
@Headers("Accept: application/vnd.github.squirrel-girl-preview")
Observable<Boolean> postCommitReaction(@NonNull @Body PostReactionModel body,
@NonNull @Path("owner") String owner,
@Path("repo") @NonNull String repo,
@Path("id") long id);
}

View File

@ -23,7 +23,7 @@ public class RxHelper {
.observeOn(AndroidSchedulers.mainThread());
}
public static <T> Observable<T> saveObserable(@NonNull Observable<T> observable) {
public static <T> Observable<T> safeObservable(@NonNull Observable<T> observable) {
return getObserver(observable).onErrorReturn(throwable -> null);
}
}

View File

@ -16,6 +16,7 @@ import com.fastaccess.data.service.GistService;
import com.fastaccess.data.service.IssueService;
import com.fastaccess.data.service.NotificationService;
import com.fastaccess.data.service.PullRequestService;
import com.fastaccess.data.service.ReactionsService;
import com.fastaccess.data.service.RepoService;
import com.fastaccess.data.service.SearchService;
import com.fastaccess.data.service.UserRestService;
@ -157,6 +158,10 @@ public class RestProvider {
return provideRetrofit().create(NotificationService.class);
}
@NonNull public static ReactionsService getReactionsService() {
return provideRetrofit().create(ReactionsService.class);
}
@Nullable public static GitHubErrorResponse getErrorResponse(@NonNull Throwable throwable) {
ResponseBody body = null;
if (throwable instanceof HttpException) {

View File

@ -0,0 +1,105 @@
package com.fastaccess.provider.tasks.git;
import android.app.IntentService;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import com.fastaccess.R;
import com.fastaccess.data.dao.PostReactionModel;
import com.fastaccess.data.dao.types.ReactionTypes;
import com.fastaccess.helper.BundleConstant;
import com.fastaccess.helper.Bundler;
import com.fastaccess.helper.InputHelper;
import com.fastaccess.helper.RxHelper;
import com.fastaccess.provider.rest.RestProvider;
/**
* Created by Kosh on 29 Mar 2017, 9:59 PM
*/
public class ReactionService extends IntentService {
private NotificationCompat.Builder notification;
private NotificationManager notificationManager;
public static void start(@NonNull Context context, @NonNull String login, @NonNull String repo,
long commentId, ReactionTypes reactionType, boolean isCommit) {
Intent intent = new Intent(context, ReactionService.class);
intent.putExtras(Bundler.start()
.put(BundleConstant.EXTRA, isCommit)
.put(BundleConstant.EXTRA_TWO, login)
.put(BundleConstant.EXTRA_THREE, repo)
.put(BundleConstant.ID, commentId)
.put(BundleConstant.EXTRA_TYPE, reactionType)
.end());
context.startService(intent);
}
public ReactionService() {
super(ReactionService.class.getSimpleName());
}
@Override protected void onHandleIntent(@Nullable Intent intent) {
if (intent != null && intent.getExtras() != null) {
Bundle bundle = intent.getExtras();
ReactionTypes reactionType = (ReactionTypes) bundle.getSerializable(BundleConstant.EXTRA_TYPE);
boolean isCommit = bundle.getBoolean(BundleConstant.EXTRA);
String login = bundle.getString(BundleConstant.EXTRA_TWO);
String repo = bundle.getString(BundleConstant.EXTRA_THREE);
long commentId = bundle.getLong(BundleConstant.ID);
if (InputHelper.isEmpty(login) || InputHelper.isEmpty(repo) || reactionType == null) {
stopSelf();
return;
}
if (isCommit) {
postCommit(reactionType, login, repo, commentId);
} else {
post(reactionType, login, repo, commentId);
}
}
}
private void post(@NonNull ReactionTypes reactionType, @NonNull String login, @NonNull String repo, long commentId) {
RxHelper.safeObservable(RestProvider.getReactionsService()
.postIssueReaction(new PostReactionModel(reactionType.getContent()), login, repo, commentId))
.doOnSubscribe(() -> showNotificatin(getNotification(reactionType), (int) commentId))
.subscribe(response -> hideNotificat((int) commentId), throwable -> hideNotificat((int) commentId));
}
private void postCommit(@NonNull ReactionTypes reactionType, @NonNull String login, @NonNull String repo, long commentId) {
RxHelper.safeObservable(RestProvider.getReactionsService()
.postCommitReaction(new PostReactionModel(reactionType.getContent()), login, repo, commentId))
.doOnSubscribe(() -> showNotificatin(getNotification(reactionType), (int) commentId))
.subscribe(response -> hideNotificat((int) commentId), throwable -> hideNotificat((int) commentId));
}
public NotificationCompat.Builder getNotification(@NonNull ReactionTypes reactionTypes) {
if (notification == null) {
notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_sync)
.setProgress(0, 100, true);
}
notification.setContentTitle(getString(R.string.posting_reaction, reactionTypes.getContent()));
return notification;
}
public NotificationManager getNotificationManager() {
if (notificationManager == null) {
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
return notificationManager;
}
private void showNotificatin(@NonNull NotificationCompat.Builder builder, int id) {
getNotificationManager().notify(id, builder.build());
}
private void hideNotificat(int id) {
getNotificationManager().cancel(id);
}
}

View File

@ -91,7 +91,7 @@ public class NotificationSchedulerJobTask extends JobService {
private void onSave(@Nullable List<Notification> notificationThreadModels) {
if (notificationThreadModels != null) {
RxHelper.saveObserable(Notification.save(notificationThreadModels)).subscribe();
RxHelper.safeObservable(Notification.save(notificationThreadModels)).subscribe();
onNotifyUser(notificationThreadModels);
}
}

View File

@ -4,6 +4,8 @@ import android.support.annotation.NonNull;
import android.view.ViewGroup;
import com.fastaccess.data.dao.model.Comment;
import com.fastaccess.data.dao.model.Login;
import com.fastaccess.ui.adapter.callback.OnToggleView;
import com.fastaccess.ui.adapter.viewholder.CommentsViewHolder;
import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter;
import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder;
@ -16,12 +18,17 @@ import java.util.ArrayList;
public class CommentsAdapter extends BaseRecyclerAdapter<Comment, CommentsViewHolder, BaseViewHolder.OnItemClickListener<Comment>> {
public CommentsAdapter(@NonNull ArrayList<Comment> eventsModels) {
private final OnToggleView onToggleView;
private final String login;
public CommentsAdapter(@NonNull ArrayList<Comment> eventsModels, @NonNull OnToggleView onToggleView) {
super(eventsModels);
this.onToggleView = onToggleView;
this.login = Login.getUser().getLogin();
}
@Override protected CommentsViewHolder viewHolder(ViewGroup parent, int viewType) {
return CommentsViewHolder.newInstance(parent, this);
return CommentsViewHolder.newInstance(parent, this, login, onToggleView);
}
@Override protected void onBindView(CommentsViewHolder holder, int position) {

View File

@ -4,6 +4,7 @@ import android.support.annotation.NonNull;
import android.view.ViewGroup;
import com.fastaccess.data.dao.CommitFileModel;
import com.fastaccess.ui.adapter.callback.OnToggleView;
import com.fastaccess.ui.adapter.viewholder.CommitFilesViewHolder;
import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter;
import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder;
@ -17,21 +18,16 @@ import java.util.ArrayList;
public class CommitFilesAdapter extends BaseRecyclerAdapter<CommitFileModel, CommitFilesViewHolder, BaseViewHolder
.OnItemClickListener<CommitFileModel>> {
public interface OnTogglePatch {
void onToggle(int position, boolean isCollapsed);
boolean isCollapsed(int position);
}
@NonNull private OnToggleView onToggleView;
@NonNull private OnTogglePatch onTogglePatch;
public CommitFilesAdapter(@NonNull ArrayList<CommitFileModel> eventsModels, @NonNull OnTogglePatch onTogglePatch) {
public CommitFilesAdapter(@NonNull ArrayList<CommitFileModel> eventsModels, @NonNull OnToggleView onToggleView) {
super(eventsModels);
this.onTogglePatch = onTogglePatch;
this.onToggleView = onToggleView;
}
@Override protected CommitFilesViewHolder viewHolder(ViewGroup parent, int viewType) {
return CommitFilesViewHolder.newInstance(parent, this, onTogglePatch);
return CommitFilesViewHolder.newInstance(parent, this, onToggleView);
}
@Override protected void onBindView(CommitFilesViewHolder holder, int position) {

View File

@ -0,0 +1,7 @@
package com.fastaccess.ui.adapter.callback;
public interface OnToggleView {
void onToggle(int position, boolean isCollapsed);
boolean isCollapsed(int position);
}

View File

@ -2,6 +2,8 @@ package com.fastaccess.ui.adapter.viewholder;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatImageView;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
@ -10,6 +12,7 @@ import com.fastaccess.data.dao.model.Comment;
import com.fastaccess.data.dao.model.ReactionsModel;
import com.fastaccess.helper.InputHelper;
import com.fastaccess.helper.ParseDateFormat;
import com.fastaccess.ui.adapter.callback.OnToggleView;
import com.fastaccess.ui.widgets.AvatarLayout;
import com.fastaccess.ui.widgets.FontTextView;
import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter;
@ -32,24 +35,71 @@ public class CommentsViewHolder extends BaseViewHolder<Comment> {
@BindView(R.id.thumbsDown) FontTextView thumbsDown;
@BindView(R.id.laugh) FontTextView laugh;
@BindView(R.id.sad) FontTextView sad;
@BindView(R.id.hurray) FontTextView hurray;
@BindView(R.id.hurray) FontTextView hooray;
@BindView(R.id.heart) FontTextView heart;
@BindView(R.id.toggle) View toggle;
@BindView(R.id.delete) AppCompatImageView delete;
@BindView(R.id.reply) AppCompatImageView reply;
@BindView(R.id.edit) AppCompatImageView edit;
@BindView(R.id.commentOptions) View commentOptions;
@BindView(R.id.toggleHolder) View toggleHolder;
private String login;
private OnToggleView onToggleView;
@Override public void onClick(View v) {
super.onClick(v);
if (v.getId() == R.id.toggle || v.getId() == R.id.toggleHolder) {
if (onToggleView != null) {
int position = getAdapterPosition();
onToggleView.onToggle(position, !onToggleView.isCollapsed(position));
}
} else {
switch (v.getId()) {
case R.id.heart:
break;
case R.id.sad:
break;
case R.id.thumbsDown:
break;
case R.id.thumbsUp:
break;
case R.id.laugh:
break;
case R.id.hurray:
break;
}
super.onClick(v);
}
}
private CommentsViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) {
private CommentsViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter,
@NonNull String login, @NonNull OnToggleView onToggleView) {
super(itemView, adapter);
this.login = login;
this.onToggleView = onToggleView;
itemView.setOnClickListener(null);
itemView.setOnLongClickListener(null);
reply.setOnClickListener(this);
edit.setOnClickListener(this);
delete.setOnClickListener(this);
toggleHolder.setOnClickListener(this);
laugh.setOnClickListener(this);
sad.setOnClickListener(this);
thumbsDown.setOnClickListener(this);
thumbsUp.setOnClickListener(this);
hooray.setOnClickListener(this);
heart.setOnClickListener(this);
}
public static CommentsViewHolder newInstance(@NonNull ViewGroup viewGroup, @Nullable BaseRecyclerAdapter adapter) {
return new CommentsViewHolder(getView(viewGroup, R.layout.comments_row_item), adapter);
public static CommentsViewHolder newInstance(@NonNull ViewGroup viewGroup, @Nullable BaseRecyclerAdapter adapter,
@NonNull String login, @NonNull OnToggleView onToggleView) {
return new CommentsViewHolder(getView(viewGroup, R.layout.comments_row_item), adapter, login, onToggleView);
}
@Override public void bind(@NonNull Comment commentsModel) {
if (commentsModel.getUser() != null) {
avatar.setUrl(commentsModel.getUser().getAvatarUrl(), commentsModel.getUser().getLogin());
delete.setVisibility(TextUtils.equals(commentsModel.getUser().getLogin(), login) ? View.VISIBLE : View.GONE);
edit.setVisibility(TextUtils.equals(commentsModel.getUser().getLogin(), login) ? View.VISIBLE : View.GONE);
} else {
avatar.setUrl(null, null);
}
@ -65,8 +115,15 @@ public class CommentsViewHolder extends BaseViewHolder<Comment> {
thumbsDown.setText(String.valueOf(reaction.getMinusOne()));
sad.setText(String.valueOf(reaction.getConfused()));
laugh.setText(String.valueOf(reaction.getLaugh()));
hurray.setText(String.valueOf(reaction.getHooray()));
hooray.setText(String.valueOf(reaction.getHooray()));
heart.setText(String.valueOf(reaction.getHeart()));
}
if (onToggleView != null) onToggle(onToggleView.isCollapsed(getAdapterPosition()));
}
private void onToggle(boolean expanded) {
toggle.setRotation(!expanded ? 0.0F : 180F);
commentOptions.setVisibility(!expanded ? View.GONE : View.VISIBLE);
}
}

View File

@ -12,7 +12,7 @@ import android.view.ViewGroup;
import com.fastaccess.R;
import com.fastaccess.data.dao.CommitFileModel;
import com.fastaccess.ui.adapter.CommitFilesAdapter;
import com.fastaccess.ui.adapter.callback.OnToggleView;
import com.fastaccess.ui.widgets.DiffLineSpan;
import com.fastaccess.ui.widgets.FontTextView;
import com.fastaccess.ui.widgets.SpannableBuilder;
@ -44,11 +44,11 @@ public class CommitFilesViewHolder extends BaseViewHolder<CommitFileModel> {
@BindColor(R.color.patch_ref_color) int patchRefColor;
private String pathText;
private CommitFilesAdapter.OnTogglePatch onTogglePatch;
private OnToggleView onToggleView;
@Override public void onClick(View v) {
int position = getAdapterPosition();
onTogglePatch.onToggle(position, !onTogglePatch.isCollapsed(position));
onToggleView.onToggle(position, !onToggleView.isCollapsed(position));
}
private void onToggle(boolean expanded) {
@ -64,14 +64,14 @@ public class CommitFilesViewHolder extends BaseViewHolder<CommitFileModel> {
}
private CommitFilesViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter,
@NonNull CommitFilesAdapter.OnTogglePatch onTogglePatch) {
@NonNull OnToggleView onToggleView) {
super(itemView, adapter);
this.onTogglePatch = onTogglePatch;
this.onToggleView = onToggleView;
}
public static CommitFilesViewHolder newInstance(ViewGroup viewGroup, BaseRecyclerAdapter adapter,
@NonNull CommitFilesAdapter.OnTogglePatch onTogglePatch) {
return new CommitFilesViewHolder(getView(viewGroup, R.layout.commit_file_row_item), adapter, onTogglePatch);
@NonNull OnToggleView onToggleView) {
return new CommitFilesViewHolder(getView(viewGroup, R.layout.commit_file_row_item), adapter, onToggleView);
}
@Override public void bind(@NonNull CommitFileModel commit) {
@ -94,7 +94,7 @@ public class CommitFilesViewHolder extends BaseViewHolder<CommitFileModel> {
.append("\n")
.bold(String.valueOf(commit.getStatus())));
onToggle(onTogglePatch.isCollapsed(getAdapterPosition()));
onToggle(onToggleView.isCollapsed(getAdapterPosition()));
}
private void setPatchText(@NonNull String text) {

View File

@ -8,6 +8,7 @@ import android.support.v4.widget.SwipeRefreshLayout;
import com.fastaccess.data.dao.model.Comment;
import com.fastaccess.data.dao.model.User;
import com.fastaccess.provider.rest.loadmore.OnLoadMore;
import com.fastaccess.ui.adapter.callback.OnToggleView;
import com.fastaccess.ui.base.mvp.BaseMvp;
import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder;
@ -20,7 +21,7 @@ import java.util.ArrayList;
interface GistCommentsMvp {
interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener,
android.view.View.OnClickListener {
android.view.View.OnClickListener, OnToggleView {
void onNotifyAdapter();

View File

@ -76,7 +76,6 @@ class GistCommentsPresenter extends BasePresenter<GistCommentsMvp.View> implemen
return comments;
}
@Override public void onHandleDeletion(@Nullable Bundle bundle) {
if (bundle != null) {
long commId = bundle.getLong(BundleConstant.EXTRA, 0);

View File

@ -10,6 +10,7 @@ import android.support.v4.widget.SwipeRefreshLayout;
import android.view.View;
import com.fastaccess.R;
import com.fastaccess.data.dao.SparseBooleanArrayParcelable;
import com.fastaccess.data.dao.model.Comment;
import com.fastaccess.data.dao.model.User;
import com.fastaccess.helper.BundleConstant;
@ -23,6 +24,7 @@ import com.fastaccess.ui.widgets.dialog.MessageDialogView;
import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView;
import butterknife.BindView;
import icepick.State;
import static com.fastaccess.helper.BundleConstant.ExtraTYpe.EDIT_GIST_COMMENT_EXTRA;
import static com.fastaccess.helper.BundleConstant.ExtraTYpe.NEW_GIST_COMMENT_EXTRA;
@ -36,7 +38,7 @@ public class GistCommentsView extends BaseFragment<GistCommentsMvp.View, GistCom
@BindView(R.id.recycler) DynamicRecyclerView recycler;
@BindView(R.id.refresh) SwipeRefreshLayout refresh;
@BindView(R.id.stateLayout) StateLayout stateLayout;
@State SparseBooleanArrayParcelable sparseBooleanArray;
private String gistId;
private CommentsAdapter adapter;
private OnLoadMore<String> onLoadMore;
@ -59,13 +61,14 @@ public class GistCommentsView extends BaseFragment<GistCommentsMvp.View, GistCom
recycler.setItemViewCacheSize(10);
refresh.setOnRefreshListener(this);
stateLayout.setOnReloadListener(this);
adapter = new CommentsAdapter(getPresenter().getComments());
adapter = new CommentsAdapter(getPresenter().getComments(), this);
adapter.setListener(getPresenter());
getLoadMore().setCurrent_page(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal());
recycler.setAdapter(adapter);
recycler.addOnScrollListener(getLoadMore());
recycler.addNormalSpacingDivider();
if (getPresenter().getComments().isEmpty() && !getPresenter().isApiCalled()) {
sparseBooleanArray = new SparseBooleanArrayParcelable();
onRefresh();
}
}
@ -203,4 +206,20 @@ public class GistCommentsView extends BaseFragment<GistCommentsMvp.View, GistCom
getPresenter().onHandleDeletion(bundle);
}
}
@Override public void onToggle(int position, boolean isCollapsed) {
getSparseBooleanArray().put(position, isCollapsed);
adapter.notifyItemChanged(position);
}
@Override public boolean isCollapsed(int position) {
return getSparseBooleanArray().get(position);
}
private SparseBooleanArrayParcelable getSparseBooleanArray() {
if (sparseBooleanArray == null) {
sparseBooleanArray = new SparseBooleanArrayParcelable();
}
return sparseBooleanArray;
}
}

View File

@ -8,6 +8,7 @@ import android.support.v4.widget.SwipeRefreshLayout;
import com.fastaccess.data.dao.model.Comment;
import com.fastaccess.data.dao.model.User;
import com.fastaccess.provider.rest.loadmore.OnLoadMore;
import com.fastaccess.ui.adapter.callback.OnToggleView;
import com.fastaccess.ui.base.mvp.BaseMvp;
import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder;
@ -20,7 +21,7 @@ import java.util.ArrayList;
interface CommitCommentsMvp {
interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener,
android.view.View.OnClickListener {
android.view.View.OnClickListener, OnToggleView {
void onNotifyAdapter();

View File

@ -1,17 +1,20 @@
package com.fastaccess.ui.modules.repos.code.commit.details.comments;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.View;
import com.fastaccess.R;
import com.fastaccess.data.dao.model.Comment;
import com.fastaccess.data.dao.model.Login;
import com.fastaccess.data.dao.types.ReactionTypes;
import com.fastaccess.helper.BundleConstant;
import com.fastaccess.helper.RxHelper;
import com.fastaccess.provider.rest.RestProvider;
import com.fastaccess.provider.tasks.git.ReactionService;
import com.fastaccess.ui.base.mvp.presenter.BasePresenter;
import java.util.ArrayList;
@ -124,25 +127,52 @@ class CommitCommentsPresenter extends BasePresenter<CommitCommentsMvp.View> impl
}
@Override public void onItemClick(int position, View v, Comment item) {
Login login = Login.getUser();
if (getView() != null) {
if (item.getUser() != null) {
Login login = Login.getUser();
if (v.getId() == R.id.delete) {
if (login != null && item.getUser().getLogin().equals(login.getLogin())) {
if (getView() != null) getView().onShowDeleteMsg(item.getId());
}
} else if (v.getId() == R.id.reply) {
getView().onTagUser(item.getUser());
} else if (v.getId() == R.id.edit) {
if (login != null && item.getUser().getLogin().equals(login.getLogin())) {
getView().onEditComment(item);
} else {
getView().onTagUser(item.getUser());
}
} else {
getView().onTagUser(item.getUser());
handleReactions(v.getId(), item.getId(), v.getContext());
}
}
}
@Override public void onItemLongClick(int position, View v, Comment item) {
if (item.getUser() != null && TextUtils.equals(item.getUser().getLogin(), Login.getUser().getLogin())) {
if (getView() != null) getView().onShowDeleteMsg(item.getId());
} else {
onItemClick(position, v, item);
private void handleReactions(@IdRes int id, long commentId, @NonNull Context context) {
ReactionTypes type = null;
switch (id) {
case R.id.heart:
type = ReactionTypes.HEART;
break;
case R.id.sad:
type = ReactionTypes.CONFUSED;
break;
case R.id.thumbsDown:
type = ReactionTypes.PLUS_ONE;
break;
case R.id.thumbsUp:
type = ReactionTypes.MINUS_ONE;
break;
case R.id.laugh:
type = ReactionTypes.LAUGH;
break;
case R.id.hurray:
type = ReactionTypes.HOORAY;
break;
}
if (type != null) {
ReactionService.start(context, login, repoId, commentId, type, true);
}
}
@Override public void onItemLongClick(int position, View v, Comment item) {
onItemClick(position, v, item);
}
}

View File

@ -10,6 +10,7 @@ import android.support.v4.widget.SwipeRefreshLayout;
import android.view.View;
import com.fastaccess.R;
import com.fastaccess.data.dao.SparseBooleanArrayParcelable;
import com.fastaccess.data.dao.model.Comment;
import com.fastaccess.data.dao.model.User;
import com.fastaccess.helper.BundleConstant;
@ -23,6 +24,7 @@ import com.fastaccess.ui.widgets.dialog.MessageDialogView;
import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView;
import butterknife.BindView;
import icepick.State;
/**
* Created by Kosh on 11 Nov 2016, 12:36 PM
@ -33,6 +35,8 @@ public class CommitCommentsView extends BaseFragment<CommitCommentsMvp.View, Com
@BindView(R.id.recycler) DynamicRecyclerView recycler;
@BindView(R.id.refresh) SwipeRefreshLayout refresh;
@BindView(R.id.stateLayout) StateLayout stateLayout;
@State SparseBooleanArrayParcelable sparseBooleanArray;
private CommentsAdapter adapter;
private OnLoadMore onLoadMore;
@ -57,13 +61,14 @@ public class CommitCommentsView extends BaseFragment<CommitCommentsMvp.View, Com
recycler.setItemViewCacheSize(10);
refresh.setOnRefreshListener(this);
stateLayout.setOnReloadListener(this);
adapter = new CommentsAdapter(getPresenter().getComments());
adapter = new CommentsAdapter(getPresenter().getComments(), this);
adapter.setListener(getPresenter());
getLoadMore().setCurrent_page(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal());
recycler.setAdapter(adapter);
recycler.addOnScrollListener(getLoadMore());
recycler.addNormalSpacingDivider();
if (getPresenter().getComments().isEmpty() && !getPresenter().isApiCalled()) {
sparseBooleanArray = new SparseBooleanArrayParcelable();
onRefresh();
}
}
@ -198,4 +203,20 @@ public class CommitCommentsView extends BaseFragment<CommitCommentsMvp.View, Com
hideProgress();
stateLayout.showReload(adapter.getItemCount());
}
@Override public void onToggle(int position, boolean isCollapsed) {
getSparseBooleanArray().put(position, isCollapsed);
adapter.notifyItemChanged(position);
}
@Override public boolean isCollapsed(int position) {
return getSparseBooleanArray().get(position);
}
private SparseBooleanArrayParcelable getSparseBooleanArray() {
if (sparseBooleanArray == null) {
sparseBooleanArray = new SparseBooleanArrayParcelable();
}
return sparseBooleanArray;
}
}

View File

@ -6,7 +6,7 @@ import android.support.annotation.Nullable;
import com.fastaccess.data.dao.CommitFileListModel;
import com.fastaccess.data.dao.CommitFileModel;
import com.fastaccess.ui.adapter.CommitFilesAdapter;
import com.fastaccess.ui.adapter.callback.OnToggleView;
import com.fastaccess.ui.base.mvp.BaseMvp;
import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder;
@ -16,7 +16,7 @@ import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder;
interface CommitFilesMvp {
interface View extends BaseMvp.FAView, CommitFilesAdapter.OnTogglePatch {
interface View extends BaseMvp.FAView, OnToggleView {
void onNotifyAdapter();

View File

@ -8,6 +8,7 @@ import android.support.v4.widget.SwipeRefreshLayout;
import com.fastaccess.data.dao.model.Comment;
import com.fastaccess.data.dao.model.User;
import com.fastaccess.provider.rest.loadmore.OnLoadMore;
import com.fastaccess.ui.adapter.callback.OnToggleView;
import com.fastaccess.ui.base.mvp.BaseMvp;
import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder;
@ -20,7 +21,7 @@ import java.util.ArrayList;
interface IssueCommentsMvp {
interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener,
android.view.View.OnClickListener {
android.view.View.OnClickListener, OnToggleView {
void onNotifyAdapter();

View File

@ -1,17 +1,20 @@
package com.fastaccess.ui.modules.repos.issues.issue.details.comments;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.View;
import com.fastaccess.R;
import com.fastaccess.data.dao.model.Comment;
import com.fastaccess.data.dao.model.Login;
import com.fastaccess.data.dao.types.ReactionTypes;
import com.fastaccess.helper.BundleConstant;
import com.fastaccess.helper.RxHelper;
import com.fastaccess.provider.rest.RestProvider;
import com.fastaccess.provider.tasks.git.ReactionService;
import com.fastaccess.ui.base.mvp.BaseMvp;
import com.fastaccess.ui.base.mvp.presenter.BasePresenter;
@ -131,25 +134,52 @@ class IssueCommentsPresenter extends BasePresenter<IssueCommentsMvp.View> implem
}
@Override public void onItemClick(int position, View v, Comment item) {
Login login = Login.getUser();
if (getView() != null) {
if (item.getUser() != null) {
Login userModel = Login.getUser();
if (userModel != null && item.getUser().getLogin().equals(userModel.getLogin())) {
if (v.getId() == R.id.delete) {
if (login != null && item.getUser().getLogin().equals(login.getLogin())) {
if (getView() != null) getView().onShowDeleteMsg(item.getId());
}
} else if (v.getId() == R.id.reply) {
getView().onTagUser(item.getUser());
} else if (v.getId() == R.id.edit) {
if (login != null && item.getUser().getLogin().equals(login.getLogin())) {
getView().onEditComment(item);
} else {
getView().onTagUser(item.getUser());
}
} else {
getView().onTagUser(item.getUser());
handleReactions(v.getId(), item.getId(), v.getContext());
}
}
}
@Override public void onItemLongClick(int position, View v, Comment item) {
if (item.getUser() != null && TextUtils.equals(item.getUser().getLogin(), Login.getUser().getLogin())) {
if (getView() != null) getView().onShowDeleteMsg(item.getId());
} else {
onItemClick(position, v, item);
private void handleReactions(@IdRes int id, long commentId, @NonNull Context context) {
ReactionTypes type = null;
switch (id) {
case R.id.heart:
type = ReactionTypes.HEART;
break;
case R.id.sad:
type = ReactionTypes.CONFUSED;
break;
case R.id.thumbsDown:
type = ReactionTypes.PLUS_ONE;
break;
case R.id.thumbsUp:
type = ReactionTypes.MINUS_ONE;
break;
case R.id.laugh:
type = ReactionTypes.LAUGH;
break;
case R.id.hurray:
type = ReactionTypes.HOORAY;
break;
}
if (type != null) {
ReactionService.start(context, login, repoId, commentId, type, false);
}
}
@Override public void onItemLongClick(int position, View v, Comment item) {
onItemClick(position, v, item);
}
}

View File

@ -10,6 +10,7 @@ import android.support.v4.widget.SwipeRefreshLayout;
import android.view.View;
import com.fastaccess.R;
import com.fastaccess.data.dao.SparseBooleanArrayParcelable;
import com.fastaccess.data.dao.model.Comment;
import com.fastaccess.data.dao.model.User;
import com.fastaccess.helper.BundleConstant;
@ -24,6 +25,7 @@ import com.fastaccess.ui.widgets.dialog.MessageDialogView;
import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView;
import butterknife.BindView;
import icepick.State;
import uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt;
/**
@ -35,6 +37,7 @@ public class IssueCommentsView extends BaseFragment<IssueCommentsMvp.View, Issue
@BindView(R.id.recycler) DynamicRecyclerView recycler;
@BindView(R.id.refresh) SwipeRefreshLayout refresh;
@BindView(R.id.stateLayout) StateLayout stateLayout;
@State SparseBooleanArrayParcelable sparseBooleanArray;
private CommentsAdapter adapter;
private OnLoadMore onLoadMore;
@ -53,13 +56,16 @@ public class IssueCommentsView extends BaseFragment<IssueCommentsMvp.View, Issue
}
@Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
if (savedInstanceState == null) getPresenter().onFragmentCreated(getArguments());
if (savedInstanceState == null) {
sparseBooleanArray = new SparseBooleanArrayParcelable();
getPresenter().onFragmentCreated(getArguments());
}
stateLayout.setEmptyText(R.string.no_comments);
recycler.setEmptyView(stateLayout, refresh);
recycler.setItemViewCacheSize(10);
refresh.setOnRefreshListener(this);
stateLayout.setOnReloadListener(this);
adapter = new CommentsAdapter(getPresenter().getComments());
adapter = new CommentsAdapter(getPresenter().getComments(), this);
adapter.setListener(getPresenter());
getLoadMore().setCurrent_page(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal());
recycler.setAdapter(adapter);
@ -211,8 +217,24 @@ public class IssueCommentsView extends BaseFragment<IssueCommentsMvp.View, Issue
}
}
@Override public void onToggle(int position, boolean isCollapsed) {
getSparseBooleanArray().put(position, isCollapsed);
adapter.notifyItemChanged(position);
}
@Override public boolean isCollapsed(int position) {
return getSparseBooleanArray().get(position);
}
private void showReload() {
hideProgress();
stateLayout.showReload(adapter.getItemCount());
}
private SparseBooleanArrayParcelable getSparseBooleanArray() {
if (sparseBooleanArray == null) {
sparseBooleanArray = new SparseBooleanArrayParcelable();
}
return sparseBooleanArray;
}
}

View File

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/commentOptions"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:showIn="@layout/comments_row_item">
<HorizontalScrollView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
tools:showIn="@layout/comments_row_item">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingEnd="@dimen/spacing_normal"
android:paddingStart="@dimen/spacing_normal"
android:paddingTop="@dimen/spacing_normal">
<com.fastaccess.ui.widgets.FontTextView
android:id="@+id/thumbsUp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="@dimen/spacing_micro"
android:layout_marginStart="@dimen/spacing_micro"
android:background="?android:selectableItemBackgroundBorderless"
android:drawablePadding="@dimen/spacing_micro"
android:drawableStart="@drawable/ic_thumbs_up"
android:gravity="center"
tools:text="100"/>
<com.fastaccess.ui.widgets.FontTextView
android:id="@+id/thumbsDown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="@dimen/spacing_micro"
android:layout_marginStart="@dimen/spacing_micro"
android:background="?android:selectableItemBackgroundBorderless"
android:drawablePadding="@dimen/spacing_micro"
android:drawableStart="@drawable/ic_thumbs_down"
android:gravity="center"
tools:text="100"/>
<com.fastaccess.ui.widgets.FontTextView
android:id="@+id/laugh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="@dimen/spacing_micro"
android:layout_marginStart="@dimen/spacing_micro"
android:background="?android:selectableItemBackgroundBorderless"
android:drawablePadding="@dimen/spacing_micro"
android:drawableStart="@drawable/ic_laughing"
android:gravity="center"
tools:text="100"/>
<com.fastaccess.ui.widgets.FontTextView
android:id="@+id/hurray"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="@dimen/spacing_micro"
android:layout_marginStart="@dimen/spacing_micro"
android:background="?android:selectableItemBackgroundBorderless"
android:drawablePadding="@dimen/spacing_micro"
android:drawableStart="@drawable/ic_huray"
android:gravity="center"
tools:text="100"/>
<com.fastaccess.ui.widgets.FontTextView
android:id="@+id/sad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="@dimen/spacing_micro"
android:layout_marginStart="@dimen/spacing_micro"
android:background="?android:selectableItemBackgroundBorderless"
android:drawablePadding="@dimen/spacing_micro"
android:drawableStart="@drawable/ic_sad"
android:gravity="center"
tools:text="100"/>
<com.fastaccess.ui.widgets.FontTextView
android:id="@+id/heart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="@dimen/spacing_micro"
android:layout_marginStart="@dimen/spacing_micro"
android:background="?android:selectableItemBackgroundBorderless"
android:drawablePadding="@dimen/spacing_micro"
android:drawableStart="@drawable/ic_emoji_heart"
android:gravity="center"
tools:text="100"/>
</LinearLayout>
</HorizontalScrollView>
<android.support.v7.widget.AppCompatImageView
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:padding="@dimen/spacing_normal"
android:src="@drawable/ic_trash"
android:visibility="gone"
tools:visibility="visible"/>
<android.support.v7.widget.AppCompatImageView
android:id="@+id/reply"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:padding="@dimen/spacing_normal"
android:src="@drawable/ic_undo"/>
<android.support.v7.widget.AppCompatImageView
android:id="@+id/edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:padding="@dimen/spacing_normal"
android:src="@drawable/ic_edit"
android:visibility="gone"
tools:visibility="visible"/>
</LinearLayout>

View File

@ -7,7 +7,6 @@
android:layout_height="wrap_content"
android:layout_margin="@dimen/grid_spacing"
android:background="@color/card_background"
android:foreground="?android:selectableItemBackground"
android:paddingBottom="@dimen/spacing_normal"
android:paddingEnd="@dimen/spacing_xs_large"
android:paddingTop="@dimen/spacing_normal"
@ -19,6 +18,7 @@
android:orientation="vertical">
<LinearLayout
android:id="@+id/toggleHolder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
@ -39,7 +39,7 @@
android:layout_marginEnd="@dimen/spacing_normal"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:maxLines="2"
android:textColor="?android:textColorPrimary"
tools:text="When one acquires"/>
@ -51,7 +51,17 @@
android:layout_gravity="center"
android:maxLines="1"
android:textColor="?android:attr/textColorSecondary"
tools:text="50 minutes ago"/>
tools:text="50 minutes"/>
<android.support.v7.widget.AppCompatImageView
android:id="@+id/toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="?selectableItemBackgroundBorderless"
android:padding="@dimen/spacing_normal"
android:scaleType="centerCrop"
android:src="@drawable/ic_arrow_drop_down"/>
</LinearLayout>
<com.prettifier.pretty.PrettifyWebView
@ -62,99 +72,7 @@
android:layout_marginStart="@dimen/avatar_margin"
android:layout_marginTop="@dimen/spacing_normal"/>
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:paddingEnd="@dimen/spacing_normal"
android:paddingStart="@dimen/spacing_normal"
android:paddingTop="@dimen/spacing_normal">
<com.fastaccess.ui.widgets.FontTextView
android:id="@+id/thumbsUp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="@dimen/spacing_micro"
android:layout_marginStart="@dimen/spacing_micro"
android:background="?android:selectableItemBackgroundBorderless"
android:drawablePadding="@dimen/spacing_normal"
android:drawableStart="@drawable/ic_thumbs_up"
android:gravity="center"
tools:text="100"/>
<com.fastaccess.ui.widgets.FontTextView
android:id="@+id/thumbsDown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="@dimen/spacing_micro"
android:layout_marginStart="@dimen/spacing_micro"
android:background="?android:selectableItemBackgroundBorderless"
android:drawablePadding="@dimen/spacing_normal"
android:drawableStart="@drawable/ic_thumbs_down"
android:gravity="center"
tools:text="100"/>
<com.fastaccess.ui.widgets.FontTextView
android:id="@+id/laugh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="@dimen/spacing_micro"
android:layout_marginStart="@dimen/spacing_micro"
android:background="?android:selectableItemBackgroundBorderless"
android:drawablePadding="@dimen/spacing_normal"
android:drawableStart="@drawable/ic_laughing"
android:gravity="center"
tools:text="100"/>
<com.fastaccess.ui.widgets.FontTextView
android:id="@+id/hurray"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="@dimen/spacing_micro"
android:layout_marginStart="@dimen/spacing_micro"
android:background="?android:selectableItemBackgroundBorderless"
android:drawablePadding="@dimen/spacing_normal"
android:drawableStart="@drawable/ic_huray"
android:gravity="center"
tools:text="100"/>
<com.fastaccess.ui.widgets.FontTextView
android:id="@+id/sad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="@dimen/spacing_micro"
android:layout_marginStart="@dimen/spacing_micro"
android:background="?android:selectableItemBackgroundBorderless"
android:drawablePadding="@dimen/spacing_normal"
android:drawableStart="@drawable/ic_sad"
android:gravity="center"
tools:text="100"/>
<com.fastaccess.ui.widgets.FontTextView
android:id="@+id/heart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="@dimen/spacing_micro"
android:layout_marginStart="@dimen/spacing_micro"
android:background="?android:selectableItemBackgroundBorderless"
android:drawablePadding="@dimen/spacing_normal"
android:drawableStart="@drawable/ic_emoji_heart"
android:gravity="center"
tools:text="100"/>
</LinearLayout>
</HorizontalScrollView>
<include layout="@layout/comments_dropdown_layout"/>
</LinearLayout>

View File

@ -321,4 +321,5 @@
<string name="my_gists">My Gists</string>
<string name="changelog">Changelog</string>
<string name="notifications_hint">Click to open notifications list or swipe to dismiss</string>
<string name="posting_reaction" formatted="true">Posting reaction %s</string>
</resources>