Skip to content

Commit

Permalink
Add support for 'cross referenced' issue event.
Browse files Browse the repository at this point in the history
Switch issue/PR fragments to use the timeline API in order to get that
event.
  • Loading branch information
maniac103 committed Feb 11, 2022
1 parent a668d64 commit f8168cb
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 7 deletions.
22 changes: 21 additions & 1 deletion app/src/main/java/com/gh4a/adapter/timeline/EventViewHolder.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

import com.gh4a.R;
import com.gh4a.activities.CommitActivity;
import com.gh4a.activities.IssueActivity;
import com.gh4a.activities.PullRequestActivity;
import com.gh4a.activities.UserActivity;
import com.gh4a.model.TimelineItem;
import com.gh4a.utils.ApiHelpers;
Expand All @@ -21,6 +23,7 @@
import com.gh4a.widget.StyleableTextView;
import com.gh4a.widget.TimestampToastSpan;

import com.meisolsson.githubsdk.model.Issue;
import com.meisolsson.githubsdk.model.IssueEvent;
import com.meisolsson.githubsdk.model.IssueEventType;
import com.meisolsson.githubsdk.model.Label;
Expand Down Expand Up @@ -62,6 +65,7 @@ class EventViewHolder
EVENT_ICONS.put(IssueEventType.ReviewRequestRemoved, R.drawable.timeline_event_review_request_removed);
EVENT_ICONS.put(IssueEventType.ConvertToDraft, R.drawable.timeline_event_branch);
EVENT_ICONS.put(IssueEventType.ReadyForReview, R.drawable.timeline_event_review);
EVENT_ICONS.put(IssueEventType.CrossReferenced, R.drawable.timeline_event_cross_referenced);
}

private final Context mContext;
Expand Down Expand Up @@ -240,7 +244,11 @@ private CharSequence formatEvent(final IssueEvent event, final User user, int ty
textResId = R.string.pull_request_event_convert_to_draft;
break;
case ReadyForReview:
textResId = R.string.pull_request_event_ready_for_review;
break;
case CrossReferenced:
textResId = mIsPullRequest
? R.string.pull_request_event_mentioned
: R.string.issue_event_mentioned;
break;
default:
return null;
Expand Down Expand Up @@ -287,6 +295,18 @@ private CharSequence formatEvent(final IssueEvent event, final User user, int ty
StringUtils.addUserTypeSpan(mContext, text, pos, mContext.getString(R.string.user_type_bot));
}

pos = text.toString().indexOf("[source]");
if (pos >= 0) {
final Issue source = event.source().issue();
String sourceLabel = "#" + source.number();
text.replace(pos, pos + 8, sourceLabel);
text.setSpan(new IntentSpan(mContext, context -> {
return source.pullRequest() != null
? PullRequestActivity.makeIntent(context, source)
: IssueActivity.makeIntent(context, source);
}), pos, pos + sourceLabel.length(), 0);
}

CharSequence time = event.createdAt() != null
? StringUtils.formatRelativeTime(mContext, event.createdAt(), true) : "";

Expand Down
5 changes: 3 additions & 2 deletions app/src/main/java/com/gh4a/fragment/IssueFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.meisolsson.githubsdk.model.IssueState;
import com.meisolsson.githubsdk.service.issues.IssueCommentService;
import com.meisolsson.githubsdk.service.issues.IssueEventService;
import com.meisolsson.githubsdk.service.issues.IssueTimelineService;

import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -74,7 +75,7 @@ public void onClick(View v) {
@Override
protected Single<List<TimelineItem>> onCreateDataSingle(boolean bypassCache) {
final int issueNumber = mIssue.number();
final IssueEventService eventService = ServiceFactory.get(IssueEventService.class, bypassCache);
final IssueTimelineService timelineService = ServiceFactory.get(IssueTimelineService.class, bypassCache);
final IssueCommentService commentService =
ServiceFactory.get(IssueCommentService.class, bypassCache);

Expand All @@ -83,7 +84,7 @@ protected Single<List<TimelineItem>> onCreateDataSingle(boolean bypassCache) {
.compose(RxUtils.mapList(TimelineItem.TimelineComment::new))
.subscribeOn(Schedulers.io());
Single<List<TimelineItem.TimelineEvent>> eventSingle = ApiHelpers.PageIterator
.toSingle(page -> eventService.getIssueEvents(mRepoOwner, mRepoName, issueNumber, page))
.toSingle(page -> timelineService.getTimeline(mRepoOwner, mRepoName, issueNumber, page))
.compose(RxUtils.filter(event -> INTERESTING_EVENTS.contains(event.event())))
.compose((RxUtils.mapList(TimelineItem.TimelineEvent::new)))
.subscribeOn(Schedulers.io());
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/com/gh4a/fragment/IssueFragmentBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ public abstract class IssueFragmentBase extends ListDataBaseFragment<TimelineIte
IssueEventType.Renamed, IssueEventType.HeadRefDeleted, IssueEventType.HeadRefRestored,
IssueEventType.HeadRefForcePushed, IssueEventType.CommentDeleted,
IssueEventType.ReviewRequested, IssueEventType.ReviewRequestRemoved,
IssueEventType.ConvertToDraft, IssueEventType.ReadyForReview
IssueEventType.ConvertToDraft, IssueEventType.ReadyForReview,
IssueEventType.CrossReferenced
);

protected View mListHeaderView;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import com.meisolsson.githubsdk.service.git.GitService;
import com.meisolsson.githubsdk.service.issues.IssueCommentService;
import com.meisolsson.githubsdk.service.issues.IssueEventService;
import com.meisolsson.githubsdk.service.issues.IssueTimelineService;
import com.meisolsson.githubsdk.service.pull_request.PullRequestReviewCommentService;
import com.meisolsson.githubsdk.service.pull_request.PullRequestReviewService;
import com.meisolsson.githubsdk.service.pull_request.PullRequestService;
Expand Down Expand Up @@ -194,8 +195,8 @@ private void fillStatus(List<StatusWrapper> statuses) {
@Override
protected Single<List<TimelineItem>> onCreateDataSingle(boolean bypassCache) {
final int issueNumber = mIssue.number();
final IssueEventService eventService =
ServiceFactory.get(IssueEventService.class, bypassCache);
final IssueTimelineService timelineService =
ServiceFactory.get(IssueTimelineService.class, bypassCache);
final IssueCommentService commentService =
ServiceFactory.get(IssueCommentService.class, bypassCache);
final PullRequestReviewService reviewService =
Expand All @@ -207,7 +208,7 @@ protected Single<List<TimelineItem>> onCreateDataSingle(boolean bypassCache) {
.toSingle(page -> commentService.getIssueComments(mRepoOwner, mRepoName, issueNumber, page))
.compose(RxUtils.mapList(TimelineItem.TimelineComment::new));
Single<List<TimelineItem>> eventsSingle = ApiHelpers.PageIterator
.toSingle(page -> eventService.getIssueEvents(mRepoOwner, mRepoName, issueNumber, page))
.toSingle(page -> timelineService.getTimeline(mRepoOwner, mRepoName, issueNumber, page))
.compose(RxUtils.filter(event -> INTERESTING_EVENTS.contains(event.event())))
.compose(RxUtils.mapList(TimelineItem.TimelineEvent::new));

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillAlpha="1"
android:fillColor="#d6d6d6"
android:pathData="M12,-0C18.636,-0 24,5.364 24,12 24,18.636 18.636,24 12,24 5.364,24 0,18.636 0,12 0,5.364 5.364,-0 12,-0"
android:strokeWidth="1.20000005" />

<path
android:fillColor="#303030"
android:pathData="M 17.6,5 H 6.4 C 5.63,5 5,5.63 5,6.4 v 8.4 c 0,0.77 0.63,1.4 1.4,1.4 h 2.8 v 2.1 c 0,0.42 0.28,0.7 0.7,0.7 h 0.35 c 0.14,0 0.35,-0.07 0.49,-0.21 l 2.59,-2.59 h 4.27 c 0.77,0 1.4,-0.63 1.4,-1.4 V 6.4 C 19,5.63 18.37,5 17.6,5 M 12,13.4 11.16,12.56 12.42,11.3 H 9.2 V 9.9 h 3.15 L 11.09,8.64 12,7.8 l 2.8,2.8 z"
android:strokeWidth="0.7" />

</vector>
18 changes: 18 additions & 0 deletions app/src/main/res/drawable/timeline_event_cross_referenced.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillAlpha="1"
android:fillColor="#858585"
android:pathData="M12,-0C18.636,-0 24,5.364 24,12 24,18.636 18.636,24 12,24 5.364,24 0,18.636 0,12 0,5.364 5.364,-0 12,-0"
android:strokeWidth="1.20000005" />

<path
android:fillColor="#ffffff"
android:pathData="M 17.6,5 H 6.4 C 5.63,5 5,5.63 5,6.4 v 8.4 c 0,0.77 0.63,1.4 1.4,1.4 h 2.8 v 2.1 c 0,0.42 0.28,0.7 0.7,0.7 h 0.35 c 0.14,0 0.35,-0.07 0.49,-0.21 l 2.59,-2.59 h 4.27 c 0.77,0 1.4,-0.63 1.4,-1.4 V 6.4 C 19,5.63 18.37,5 17.6,5 M 12,13.4 11.16,12.56 12.42,11.3 H 9.2 V 9.9 h 3.15 L 11.09,8.64 12,7.8 l 2.8,2.8 z"
android:strokeWidth="0.7" />

</vector>
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@
<string name="issue_event_renamed">[b]%1$s[/b] changed the title from [b]%2$s[/b] to [b]%3$s[/b] [time]</string>
<string name="issue_event_locked">[b]%1$s[/b] locked and limited conversation to collaborators [time]</string>
<string name="issue_event_unlocked">[b]%1$s[/b] unlocked this conversation [time]</string>
<string name="issue_event_mentioned">[b]%1$s[/b] mentioned this issue in [b][source][/b] [time]</string>

<!-- Pull request events -->
<string name="pull_request_event_closed">[b]%1$s[/b] closed this pull request [time]</string>
Expand All @@ -325,6 +326,7 @@
<string name="pull_request_event_comment_deleted">[b]%1$s[/b] deleted a comment [time]</string>
<string name="pull_request_event_convert_to_draft">[b]%1$s[/b] marked this pull request as draft [time]</string>
<string name="pull_request_event_ready_for_review">[b]%1$s[/b] marked this pull request as ready for review [time]</string>
<string name="pull_request_event_mentioned">[b]%1$s[/b] mentioned this pull request in [b][source][/b] [time]</string>

<!-- Commit -->
<string name="commit_title">Commit %1$s</string>
Expand Down

4 comments on commit f8168cb

@Fs00
Copy link
Contributor

@Fs00 Fs00 commented on f8168cb Feb 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Now that we use the timeline API, we could also display commits in the conversation timeline as the GH web UI does 🤩

I've found a couple of issues with this implementation:

    android.content.res.Resources$NotFoundException: String resource ID #0x0
        at android.content.res.Resources.getText(Resources.java:444)
        at android.content.res.Resources.getString(Resources.java:537)
        at android.content.res.Resources.getString(Resources.java:561)
        at android.content.Context.getString(Context.java:661)
        at com.gh4a.adapter.timeline.EventViewHolder.formatEvent(EventViewHolder.java:258)
        at com.gh4a.adapter.timeline.EventViewHolder.bind(EventViewHolder.java:112)
        at com.gh4a.adapter.timeline.EventViewHolder.bind(EventViewHolder.java:38)
        at com.gh4a.adapter.timeline.TimelineItemAdapter.onBindViewHolder(TimelineItemAdapter.java:272)
        at com.gh4a.adapter.timeline.TimelineItemAdapter.onBindViewHolder(TimelineItemAdapter.java:30)
        at com.gh4a.adapter.RootAdapter.onBindViewHolder(RootAdapter.java:234)
        at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7254)
        at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7337)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6194)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6460)
        at androidx.recyclerview.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:288)
        at androidx.recyclerview.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:345)
        at androidx.recyclerview.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:361)
        at androidx.recyclerview.widget.GapWorker.prefetch(GapWorker.java:368)
        at androidx.recyclerview.widget.GapWorker.run(GapWorker.java:399)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

@maniac103
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed the former by myself already as well. I'll look into it.

@maniac103
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, the latter is the 'ReadyForReview' text assigned that I removed accidentally. Will fix it.

@maniac103
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First issue is an API issue. In your example, event.source.url is https://api.github.com/repos/PowerShell/PowerShell/issues/64789 while event.source.htmlUrl is https://github.com/dotnet/runtime/issues/64789. I contacted their support; I'll switch to using the repository object if available as a workaround.

Please sign in to comment.