mirror of
https://github.com/k0shk0sh/FastHub.git
synced 2026-01-25 14:47:05 +00:00
Merge pull request #883 from k0shk0sh/pullrequest_timeline
Pullrequest timeline
This commit is contained in:
commit
d2b02cc78d
17
.travis.yml
17
.travis.yml
@ -8,6 +8,14 @@ jdk: oraclejdk8
|
||||
|
||||
sudo: required
|
||||
|
||||
before_install:
|
||||
# Skip build if the commit message contains [skip travis] or [travis skip]
|
||||
- >
|
||||
echo "$TRAVIS_COMMIT_MESSAGE"
|
||||
| grep -E '\[(skip travis|travis skip)\]'
|
||||
&& echo "[skip travis] has been found, exiting."
|
||||
&& exit 0 || true
|
||||
|
||||
before_script:
|
||||
- (while sleep 3; do echo "y"; done) | $ANDROID_HOME/tools/bin/sdkmanager "platform-tools" "extras;android;m2repository" "extras;google;m2repository" "build-tools;26.0.0" "platforms;android-26"
|
||||
|
||||
@ -27,5 +35,10 @@ after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
notifications:
|
||||
slack: fasthub:mjJWGD8UpgSgKawKa5OqMNlR
|
||||
email: false
|
||||
webhooks:
|
||||
urls:
|
||||
- https://discordapp.com/api/webhooks/341508199612153857/_86ddhBkrka3SaPzYJtL2LBH-sKeVI_tSAp0L2h4cPoy2m4CLa4lpqqJu4rjxHs86V0i
|
||||
on_success: always
|
||||
on_failure: always
|
||||
on_start: never
|
||||
email: false
|
||||
|
||||
@ -32,7 +32,7 @@ We have configured snapshots of FastHub, which can be downloaded from [AppVeyor
|
||||
- Markdown and code highlighting support
|
||||
- Notifications overview and "Mark all as read"
|
||||
- Search users/orgs, repos, issues/prs & code.
|
||||
- Pinned Repos
|
||||
- FastHub & GitHub Pinned Repos
|
||||
- Trending
|
||||
- Wiki
|
||||
- **Repositories**
|
||||
@ -65,6 +65,7 @@ We have configured snapshots of FastHub, which can be downloaded from [AppVeyor
|
||||
- Comment on Commits/Gists
|
||||
- Manage Commit/Gist comments
|
||||
- Create/Delete Gists
|
||||
- Edit Gist & Gist Files
|
||||
- React to Commit comments with reactions
|
||||
- Comment on line number in Files/Code changes.
|
||||
- **Orgs**
|
||||
@ -73,6 +74,7 @@ We have configured snapshots of FastHub, which can be downloaded from [AppVeyor
|
||||
- Teams & Teams repos
|
||||
- Repos
|
||||
- **Users**
|
||||
- GitHub Pinned Repos
|
||||
- Follow/Unfollow users
|
||||
- View user feeds
|
||||
- Contribution graph.
|
||||
@ -177,7 +179,7 @@ Read the [**contribution guide**](.github/CONTRIBUTING.md) for more detailed inf
|
||||
[Google+](https://plus.google.com/+CookiconsDesign) | [Twitter](https://twitter.com/mcookie)
|
||||
Designer website [Cookicons](https://cookicons.co/).
|
||||
|
||||
**OLD FastHub** logo is designed by **Kevin Aguilar**.
|
||||
**OLD FastHub** logo was designed by **Kevin Aguilar**.
|
||||
[Google+](https://plus.google.com/+KevinAguilarC) | [Twitter](https://twitter.com/kevttob)
|
||||
Designer at [221 Pixels](https://www.221pixels.com/).
|
||||
Laus Deo Semper
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'com.apollographql.android'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'com.novoda.build-properties'
|
||||
apply plugin: 'jacoco-android'
|
||||
apply plugin: 'io.fabric'
|
||||
if (isProduction) apply plugin: 'io.fabric'
|
||||
|
||||
buildProperties {
|
||||
notThere {
|
||||
@ -23,7 +24,7 @@ android {
|
||||
}
|
||||
}
|
||||
compileSdkVersion 26
|
||||
buildToolsVersion "26.0.0"
|
||||
buildToolsVersion "26.0.1"
|
||||
defaultConfig {
|
||||
applicationId "com.fastaccess.github"
|
||||
minSdkVersion 21
|
||||
@ -58,7 +59,6 @@ android {
|
||||
}
|
||||
applicationIdSuffix ".debug"
|
||||
versionNameSuffix "-debug"
|
||||
ext.alwaysUpdateBuildId = false
|
||||
}
|
||||
|
||||
}
|
||||
@ -110,13 +110,12 @@ repositories {
|
||||
maven { url "https://clojars.org/repo/" }
|
||||
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
||||
maven { url "https://jitpack.io" }
|
||||
maven { url 'https://maven.fabric.io/public' }
|
||||
if (isProduction) maven { url 'https://maven.fabric.io/public' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation "com.android.support:appcompat-v7:${supportVersion}"
|
||||
implementation 'com.jaredrummler:android-device-names:1.1.4'
|
||||
implementation "com.android.support:design:${supportVersion}"
|
||||
implementation "com.android.support:cardview-v7:${supportVersion}"
|
||||
implementation "com.android.support:recyclerview-v7:${supportVersion}"
|
||||
@ -129,10 +128,9 @@ dependencies {
|
||||
implementation "com.squareup.retrofit2:converter-gson:${retrofit}"
|
||||
implementation "com.squareup.retrofit2:adapter-rxjava2:${retrofit}"
|
||||
implementation "com.github.bumptech.glide:glide:3.7.0"
|
||||
// implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
|
||||
implementation 'cn.gavinliu.android.lib:ShapedImageView:0.8.3'
|
||||
implementation "com.jakewharton:butterknife:${butterKnifeVersion}"
|
||||
implementation 'it.sephiroth.android.library.bottomnavigation:bottom-navigation:2.0.1-rc1'
|
||||
implementation 'it.sephiroth.android.library.bottomnavigation:bottom-navigation:2.0.2'
|
||||
implementation 'io.reactivex.rxjava2:rxjava:2.1.0'
|
||||
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0'
|
||||
@ -146,26 +144,34 @@ dependencies {
|
||||
implementation 'com.github.nightwhistler:HtmlSpanner:0.4'
|
||||
implementation 'net.sourceforge.htmlcleaner:htmlcleaner:2.2'
|
||||
implementation 'com.github.matthiasrobbers:shortbread:1.0.1'
|
||||
implementation 'com.atlassian.commonmark:commonmark:0.9.0'
|
||||
implementation "com.atlassian.commonmark:commonmark:${commonmark}"
|
||||
implementation "com.atlassian.commonmark:commonmark-ext-autolink:${commonmark}"
|
||||
implementation "com.atlassian.commonmark:commonmark-ext-gfm-strikethrough:${commonmark}"
|
||||
implementation "com.atlassian.commonmark:commonmark-ext-gfm-tables:${commonmark}"
|
||||
implementation "com.atlassian.commonmark:commonmark-ext-ins:${commonmark}"
|
||||
implementation "com.atlassian.commonmark:commonmark-ext-yaml-front-matter:${commonmark}"
|
||||
implementation "com.google.firebase:firebase-messaging:${gms}"
|
||||
implementation "com.google.android.gms:play-services-ads:${gms}"
|
||||
implementation "com.google.firebase:firebase-database:${gms}"
|
||||
implementation "com.google.android.gms:play-services-base:${gms}"
|
||||
implementation('com.github.b3er.rxfirebase:firebase-database-kotlin:11.2.0') { transitive = false }
|
||||
implementation('com.github.b3er.rxfirebase:firebase-database:11.2.0') { transitive = false }
|
||||
implementation 'com.firebase:firebase-jobdispatcher:0.7.0'
|
||||
implementation('com.crashlytics.sdk.android:crashlytics:2.6.8@aar') { transitive = true }
|
||||
if (isProduction) implementation('com.crashlytics.sdk.android:crashlytics:2.6.8@aar') { transitive = true }
|
||||
implementation "com.github.miguelbcr:RxBillingService:0.0.3"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
|
||||
implementation 'org.jsoup:jsoup:1.10.2'
|
||||
implementation "com.evernote:android-state:${state_version}"
|
||||
implementation "petrov.kristiyan:colorpicker-library:1.1.4"
|
||||
implementation 'com.apollographql.apollo:apollo-rx2-support:0.4.0'
|
||||
implementation 'com.jaredrummler:android-device-names:1.1.4'
|
||||
implementation 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:2.1.0'
|
||||
compileOnly "org.projectlombok:lombok:${lombokVersion}"
|
||||
kapt "io.requery:requery-processor:${requery}"
|
||||
kapt "org.projectlombok:lombok:${lombokVersion}"
|
||||
kapt "com.evernote:android-state-processor:${state_version}"
|
||||
kapt "com.jakewharton:butterknife-compiler:${butterKnifeVersion}"
|
||||
kapt 'com.github.matthiasrobbers:shortbread-compiler:1.0.1'
|
||||
kapt "org.projectlombok:lombok:${lombokVersion}"
|
||||
kapt "io.requery:requery-processor:${requery}"
|
||||
// testImplementation "net.grandcentrix.thirtyinch:thirtyinch-test:$thirtyinchVersion"
|
||||
testImplementation "junit:junit:${junitVersion}"
|
||||
testImplementation "org.mockito:mockito-core:${mockitoVersion}"
|
||||
@ -178,4 +184,5 @@ dependencies {
|
||||
androidTestImplementation "com.android.support.test.espresso:espresso-core:${espresseVersion}"
|
||||
}
|
||||
|
||||
apply plugin: 'ManifestClasspath'
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
@ -83,7 +83,8 @@
|
||||
<activity
|
||||
android:name=".ui.modules.repos.issues.issue.details.IssuePagerActivity"
|
||||
android:label="@string/issue"
|
||||
android:parentActivityName=".ui.modules.repos.RepoPagerActivity">
|
||||
android:parentActivityName=".ui.modules.repos.RepoPagerActivity"
|
||||
android:windowSoftInputMode="stateAlwaysHidden">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".ui.modules.repos.RepoPagerActivity"/>
|
||||
@ -103,7 +104,8 @@
|
||||
<activity
|
||||
android:name=".ui.modules.repos.code.commit.details.CommitPagerActivity"
|
||||
android:label="@string/commit"
|
||||
android:parentActivityName=".ui.modules.repos.RepoPagerActivity">
|
||||
android:parentActivityName=".ui.modules.repos.RepoPagerActivity"
|
||||
android:windowSoftInputMode="stateAlwaysHidden">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".ui.modules.repos.RepoPagerActivity"/>
|
||||
@ -115,7 +117,8 @@
|
||||
<activity
|
||||
android:name=".ui.modules.editor.EditorActivity"
|
||||
android:configChanges="keyboard|orientation|screenSize"
|
||||
android:label="@string/markdown"/>
|
||||
android:label="@string/markdown"
|
||||
android:windowSoftInputMode="adjustResize"/>
|
||||
<activity
|
||||
android:name=".ui.modules.gists.create.CreateGistActivity"
|
||||
android:configChanges="keyboard|orientation|screenSize"
|
||||
@ -123,7 +126,8 @@
|
||||
<activity
|
||||
android:name=".ui.modules.gists.gist.GistActivity"
|
||||
android:label="@string/gist"
|
||||
android:parentActivityName=".ui.modules.main.MainActivity">
|
||||
android:parentActivityName=".ui.modules.main.MainActivity"
|
||||
android:windowSoftInputMode="stateAlwaysHidden">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".ui.modules.main.MainActivity"/>
|
||||
@ -170,8 +174,14 @@
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".ui.modules.repos.RepoPagerActivity"/>
|
||||
</activity>
|
||||
<activity android:name=".ui.modules.settings.SettingsActivity"/>
|
||||
<activity android:name=".ui.modules.settings.category.SettingsCategoryActivity"/>
|
||||
<activity
|
||||
android:name=".ui.modules.settings.SettingsActivity"
|
||||
android:configChanges="keyboard|orientation|screenSize"/>
|
||||
|
||||
<activity
|
||||
android:name=".ui.modules.settings.category.SettingsCategoryActivity"
|
||||
android:configChanges="keyboard|orientation|screenSize"/>
|
||||
|
||||
<activity
|
||||
android:name=".ui.modules.repos.code.releases.ReleasesListActivity"
|
||||
android:label="@string/releases"
|
||||
|
||||
28
app/src/main/graphql/pr/PinnedRepos.graphql
Normal file
28
app/src/main/graphql/pr/PinnedRepos.graphql
Normal file
@ -0,0 +1,28 @@
|
||||
query getPinnedRepos($login: String!) {
|
||||
user(login: $login) {
|
||||
pinnedRepositories(first: 100) {
|
||||
edges {
|
||||
node {
|
||||
name
|
||||
url
|
||||
issues(states: OPEN) {
|
||||
totalCount
|
||||
}
|
||||
pullRequests(states: OPEN) {
|
||||
totalCount
|
||||
}
|
||||
stargazers {
|
||||
totalCount
|
||||
}
|
||||
forks {
|
||||
totalCount
|
||||
}
|
||||
primaryLanguage {
|
||||
name
|
||||
color
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
521
app/src/main/graphql/pr/PullRequestTimeline.graphql
Normal file
521
app/src/main/graphql/pr/PullRequestTimeline.graphql
Normal file
@ -0,0 +1,521 @@
|
||||
query PullRequestTimeline($owner: String!, $name: String!, $number: Int!, $page: String) {
|
||||
repository(owner: $owner, name: $name) {
|
||||
pullRequest(number: $number) {
|
||||
pullRequestCommits: commits(last: 1) {
|
||||
pullRequestCommit: nodes {
|
||||
commit {
|
||||
status {
|
||||
state
|
||||
contexts {
|
||||
state
|
||||
context
|
||||
description
|
||||
targetUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
timeline(first: 30 after: $page) {
|
||||
edges {
|
||||
cursor
|
||||
}
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
startCursor
|
||||
endCursor
|
||||
}
|
||||
totalCount
|
||||
nodes {
|
||||
... on Commit {
|
||||
id
|
||||
oid
|
||||
url
|
||||
committedDate
|
||||
messageHeadline
|
||||
status {
|
||||
state
|
||||
}
|
||||
author {
|
||||
name
|
||||
user {
|
||||
login
|
||||
url
|
||||
avatarUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
... on CommitCommentThread {
|
||||
path
|
||||
position
|
||||
commit {
|
||||
oid
|
||||
}
|
||||
comments(first: 30) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
authorAssociation
|
||||
bodyHTML
|
||||
body
|
||||
createdAt
|
||||
reactionGroups {
|
||||
viewerHasReacted
|
||||
content
|
||||
users {
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
lastEditedAt
|
||||
author {
|
||||
avatarUrl
|
||||
login
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
... on PullRequestReview {
|
||||
id
|
||||
url
|
||||
bodyHTML
|
||||
submittedAt
|
||||
createdAt
|
||||
state
|
||||
author {
|
||||
login
|
||||
url
|
||||
avatarUrl
|
||||
}
|
||||
comments(first: 30) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
authorAssociation
|
||||
bodyHTML
|
||||
diffHunk
|
||||
createdAt
|
||||
url
|
||||
originalPosition
|
||||
path
|
||||
position
|
||||
author {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
reactionGroups {
|
||||
viewerHasReacted
|
||||
content
|
||||
users {
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
... on IssueComment {
|
||||
id
|
||||
bodyHTML
|
||||
createdAt
|
||||
updatedAt
|
||||
viewerCanReact
|
||||
viewerCanDelete
|
||||
viewerCanUpdate
|
||||
viewerDidAuthor
|
||||
authorAssociation
|
||||
lastEditedAt
|
||||
author {
|
||||
login
|
||||
url
|
||||
avatarUrl
|
||||
}
|
||||
reactionGroups {
|
||||
viewerHasReacted
|
||||
content
|
||||
users {
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
}
|
||||
... on ClosedEvent {
|
||||
createdAt
|
||||
actor {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
commit {
|
||||
oid
|
||||
url
|
||||
messageHeadline
|
||||
}
|
||||
}
|
||||
... on ReopenedEvent {
|
||||
createdAt
|
||||
actor {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
}
|
||||
... on MergedEvent {
|
||||
id
|
||||
url
|
||||
createdAt
|
||||
mergeRefName
|
||||
commit {
|
||||
oid
|
||||
}
|
||||
actor {
|
||||
avatarUrl
|
||||
login
|
||||
url
|
||||
}
|
||||
}
|
||||
... on ReferencedEvent {
|
||||
id
|
||||
createdAt
|
||||
isCrossRepository
|
||||
isDirectReference
|
||||
actor {
|
||||
avatarUrl
|
||||
login
|
||||
url
|
||||
}
|
||||
commitRepository {
|
||||
nameWithOwner
|
||||
url
|
||||
}
|
||||
commit {
|
||||
oid
|
||||
}
|
||||
subject {
|
||||
__typename
|
||||
... on Issue {
|
||||
title
|
||||
number
|
||||
}
|
||||
... on PullRequest {
|
||||
title
|
||||
number
|
||||
}
|
||||
}
|
||||
}
|
||||
... on AssignedEvent {
|
||||
id
|
||||
createdAt
|
||||
actor {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
user {
|
||||
avatarUrl
|
||||
login
|
||||
url
|
||||
}
|
||||
}
|
||||
... on UnassignedEvent {
|
||||
id
|
||||
createdAt
|
||||
actor {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
user {
|
||||
avatarUrl
|
||||
login
|
||||
url
|
||||
}
|
||||
}
|
||||
... on LabeledEvent {
|
||||
createdAt
|
||||
actor {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
label {
|
||||
color
|
||||
name
|
||||
}
|
||||
}
|
||||
... on UnlabeledEvent {
|
||||
createdAt
|
||||
actor {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
label {
|
||||
color
|
||||
name
|
||||
}
|
||||
}
|
||||
... on MilestonedEvent {
|
||||
createdAt
|
||||
id
|
||||
milestoneTitle
|
||||
actor {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
}
|
||||
... on DemilestonedEvent {
|
||||
createdAt
|
||||
id
|
||||
milestoneTitle
|
||||
actor {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
}
|
||||
... on RenamedTitleEvent {
|
||||
id
|
||||
createdAt
|
||||
currentTitle
|
||||
previousTitle
|
||||
actor {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
}
|
||||
... on LockedEvent {
|
||||
createdAt
|
||||
actor {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
}
|
||||
... on UnlockedEvent {
|
||||
createdAt
|
||||
actor {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
}
|
||||
... on DeployedEvent {
|
||||
createdAt
|
||||
actor {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
ref {
|
||||
name
|
||||
prefix
|
||||
}
|
||||
deployment {
|
||||
createdAt
|
||||
state
|
||||
creator {
|
||||
avatarUrl
|
||||
login
|
||||
url
|
||||
}
|
||||
latestStatus {
|
||||
description
|
||||
environmentUrl
|
||||
state
|
||||
}
|
||||
statuses(first: 30) {
|
||||
edges {
|
||||
node {
|
||||
creator {
|
||||
avatarUrl
|
||||
login
|
||||
url
|
||||
}
|
||||
logUrl
|
||||
state
|
||||
description
|
||||
environmentUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
... on HeadRefDeletedEvent {
|
||||
createdAt
|
||||
headRefName
|
||||
actor {
|
||||
avatarUrl
|
||||
login
|
||||
url
|
||||
}
|
||||
}
|
||||
... on HeadRefRestoredEvent {
|
||||
actor {
|
||||
avatarUrl
|
||||
login
|
||||
url
|
||||
}
|
||||
createdAt
|
||||
pullRequest {
|
||||
number
|
||||
headRefName
|
||||
}
|
||||
}
|
||||
... on HeadRefForcePushedEvent {
|
||||
createdAt
|
||||
ref {
|
||||
name
|
||||
prefix
|
||||
}
|
||||
actor {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
afterCommit {
|
||||
oid
|
||||
url
|
||||
}
|
||||
beforeCommit {
|
||||
oid
|
||||
url
|
||||
status {
|
||||
state
|
||||
contexts {
|
||||
context
|
||||
createdAt
|
||||
description
|
||||
state
|
||||
targetUrl
|
||||
creator {
|
||||
avatarUrl
|
||||
login
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
... on BaseRefForcePushedEvent {
|
||||
createdAt
|
||||
ref {
|
||||
name
|
||||
prefix
|
||||
}
|
||||
actor {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
afterCommit {
|
||||
oid
|
||||
url
|
||||
}
|
||||
beforeCommit {
|
||||
oid
|
||||
url
|
||||
status {
|
||||
state
|
||||
contexts {
|
||||
context
|
||||
createdAt
|
||||
description
|
||||
state
|
||||
targetUrl
|
||||
creator {
|
||||
avatarUrl
|
||||
login
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
... on ReviewRequestedEvent {
|
||||
id
|
||||
createdAt
|
||||
actor {
|
||||
avatarUrl
|
||||
login
|
||||
url
|
||||
}
|
||||
subject {
|
||||
avatarUrl
|
||||
login
|
||||
url
|
||||
}
|
||||
}
|
||||
... on ReviewRequestRemovedEvent {
|
||||
id
|
||||
createdAt
|
||||
actor {
|
||||
avatarUrl
|
||||
login
|
||||
url
|
||||
}
|
||||
subject {
|
||||
avatarUrl
|
||||
login
|
||||
url
|
||||
}
|
||||
}
|
||||
... on ReviewDismissedEvent {
|
||||
id
|
||||
createdAt
|
||||
messageHtml
|
||||
previousReviewState
|
||||
review {
|
||||
id
|
||||
submittedAt
|
||||
authorAssociation
|
||||
bodyHTML
|
||||
state
|
||||
viewerDidAuthor
|
||||
author {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
comments(first: 30) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
authorAssociation
|
||||
bodyHTML
|
||||
diffHunk
|
||||
createdAt
|
||||
url
|
||||
originalPosition
|
||||
path
|
||||
position
|
||||
author {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
reactionGroups {
|
||||
viewerHasReacted
|
||||
content
|
||||
users {
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rateLimit {
|
||||
cost
|
||||
remaining
|
||||
limit
|
||||
}
|
||||
}
|
||||
34201
app/src/main/graphql/pr/schema.json
Normal file
34201
app/src/main/graphql/pr/schema.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -4,17 +4,18 @@ import android.app.Application;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.preference.PreferenceManager;
|
||||
|
||||
import com.crashlytics.android.Crashlytics;
|
||||
import com.crashlytics.android.core.CrashlyticsCore;
|
||||
import com.apollographql.apollo.ApolloClient;
|
||||
import com.fastaccess.data.dao.model.Models;
|
||||
import com.fastaccess.helper.DeviceNameGetter;
|
||||
import com.fastaccess.helper.PrefGetter;
|
||||
import com.fastaccess.helper.TypeFaceHelper;
|
||||
import com.fastaccess.provider.colors.ColorsProvider;
|
||||
import com.fastaccess.provider.emoji.EmojiManager;
|
||||
import com.fastaccess.provider.fabric.FabricProvider;
|
||||
import com.fastaccess.provider.rest.RestProvider;
|
||||
import com.fastaccess.provider.tasks.notification.NotificationSchedulerJobTask;
|
||||
import com.miguelbcr.io.rx_billing_service.RxBillingService;
|
||||
|
||||
import io.fabric.sdk.android.Fabric;
|
||||
import io.requery.Persistable;
|
||||
import io.requery.android.sqlite.DatabaseSource;
|
||||
import io.requery.meta.EntityModel;
|
||||
@ -33,6 +34,7 @@ import shortbread.Shortbread;
|
||||
public class App extends Application {
|
||||
private static App instance;
|
||||
private ReactiveEntityStore<Persistable> dataStore;
|
||||
private ApolloClient apolloClient;
|
||||
|
||||
@Override public void onCreate() {
|
||||
super.onCreate();
|
||||
@ -45,7 +47,7 @@ public class App extends Application {
|
||||
}
|
||||
|
||||
private void init() {
|
||||
initFabric();
|
||||
FabricProvider.initFabric(this);
|
||||
RxBillingService.register(this);
|
||||
deleteDatabase("database.db");
|
||||
getDataStore();//init requery before anything.
|
||||
@ -58,16 +60,6 @@ public class App extends Application {
|
||||
DeviceNameGetter.getInstance().loadDevice();
|
||||
}
|
||||
|
||||
private void initFabric() {
|
||||
Fabric fabric = new Fabric.Builder(this)
|
||||
.kits(new Crashlytics.Builder()
|
||||
.core(new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build())
|
||||
.build())
|
||||
.debuggable(BuildConfig.DEBUG)
|
||||
.build();
|
||||
Fabric.with(fabric);
|
||||
}
|
||||
|
||||
private void setupPreference() {
|
||||
PreferenceManager.setDefaultValues(this, R.xml.fasthub_settings, false);
|
||||
PreferenceManager.setDefaultValues(this, R.xml.about_settings, false);
|
||||
@ -89,4 +81,14 @@ public class App extends Application {
|
||||
}
|
||||
return dataStore;
|
||||
}
|
||||
|
||||
public ApolloClient getApolloClient() {
|
||||
if (apolloClient == null) {
|
||||
apolloClient = ApolloClient.builder()
|
||||
.serverUrl("https://" + (PrefGetter.isEnterprise() ? PrefGetter.getEnterpriseUrl() : "api.github.com") + "/graphql")
|
||||
.okHttpClient(RestProvider.provideOkHttpClient())
|
||||
.build();
|
||||
}
|
||||
return apolloClient;
|
||||
}
|
||||
}
|
||||
@ -30,7 +30,7 @@ public class AccessTokenModel implements Parcelable {
|
||||
dest.writeString(this.tokenType);
|
||||
}
|
||||
|
||||
protected AccessTokenModel(Parcel in) {
|
||||
private AccessTokenModel(Parcel in) {
|
||||
this.id = in.readLong();
|
||||
this.token = in.readString();
|
||||
this.hashedToken = in.readString();
|
||||
|
||||
@ -22,7 +22,7 @@ import lombok.Setter;
|
||||
dest.writeString(this.label);
|
||||
}
|
||||
|
||||
protected AppLanguageModel(Parcel in) {
|
||||
private AppLanguageModel(Parcel in) {
|
||||
this.value = in.readString();
|
||||
this.label = in.readString();
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ public class AuthModel implements Parcelable {
|
||||
dest.writeString(this.otpCode);
|
||||
}
|
||||
|
||||
protected AuthModel(Parcel in) {
|
||||
private AuthModel(Parcel in) {
|
||||
this.clientId = in.readString();
|
||||
this.clientSecret = in.readString();
|
||||
this.redirectUri = in.readString();
|
||||
|
||||
@ -37,7 +37,7 @@ public class BranchesModel implements Parcelable {
|
||||
dest.writeByte(this.isTag ? (byte) 1 : (byte) 0);
|
||||
}
|
||||
|
||||
protected BranchesModel(Parcel in) {
|
||||
private BranchesModel(Parcel in) {
|
||||
this.name = in.readString();
|
||||
this.commit = in.readParcelable(Commit.class.getClassLoader());
|
||||
this.protectedBranch = in.readByte() != 0;
|
||||
|
||||
@ -13,11 +13,11 @@ import lombok.Setter;
|
||||
*/
|
||||
|
||||
@Getter @Setter public class CommentRequestModel implements Parcelable {
|
||||
private String body;
|
||||
@SerializedName("in_reply_to") private Long inReplyTo;
|
||||
private String path;
|
||||
private Integer position;
|
||||
private Integer line;
|
||||
public String body;
|
||||
@SerializedName("in_reply_to") public Long inReplyTo;
|
||||
public String path;
|
||||
public Integer position;
|
||||
public Integer line;
|
||||
|
||||
public CommentRequestModel() {}
|
||||
|
||||
@ -44,7 +44,7 @@ import lombok.Setter;
|
||||
dest.writeValue(this.line);
|
||||
}
|
||||
|
||||
protected CommentRequestModel(Parcel in) {
|
||||
private CommentRequestModel(Parcel in) {
|
||||
this.body = in.readString();
|
||||
this.inReplyTo = (Long) in.readValue(Long.class.getClassLoader());
|
||||
this.path = in.readString();
|
||||
|
||||
@ -26,7 +26,7 @@ import lombok.Setter;
|
||||
|
||||
public CommitCountModel() {}
|
||||
|
||||
protected CommitCountModel(Parcel in) {
|
||||
private CommitCountModel(Parcel in) {
|
||||
this.all = new ArrayList<Integer>();
|
||||
in.readList(this.all, Integer.class.getClassLoader());
|
||||
this.owner = new ArrayList<Integer>();
|
||||
|
||||
@ -23,7 +23,7 @@ import lombok.Setter;
|
||||
public List<CommitLinesModel> linesModel;
|
||||
public CommitFileModel commitFileModel;
|
||||
|
||||
public CommitFileChanges() {}
|
||||
private CommitFileChanges() {}
|
||||
|
||||
public static Observable<CommitFileChanges> constructToObservable(@Nullable List<CommitFileModel> files) {
|
||||
if (files == null || files.isEmpty()) return Observable.empty();
|
||||
@ -56,7 +56,7 @@ import lombok.Setter;
|
||||
dest.writeParcelable(this.commitFileModel, flags);
|
||||
}
|
||||
|
||||
protected CommitFileChanges(Parcel in) {
|
||||
private CommitFileChanges(Parcel in) {
|
||||
this.linesModel = in.createTypedArrayList(CommitLinesModel.CREATOR);
|
||||
this.commitFileModel = in.readParcelable(CommitFileModel.class.getClassLoader());
|
||||
}
|
||||
|
||||
@ -100,7 +100,7 @@ import static com.fastaccess.ui.widgets.DiffLineSpan.HUNK_TITLE;
|
||||
dest.writeInt(this.position);
|
||||
}
|
||||
|
||||
protected CommitLinesModel(Parcel in) {
|
||||
private CommitLinesModel(Parcel in) {
|
||||
this.text = in.readString();
|
||||
this.color = in.readInt();
|
||||
this.leftLineNo = in.readInt();
|
||||
|
||||
@ -19,23 +19,23 @@ import lombok.Setter;
|
||||
public class CreateGistModel implements Parcelable {
|
||||
private HashMap<String, FilesListModel> files;
|
||||
private String description;
|
||||
@SerializedName("public") private boolean publicGist;
|
||||
@SerializedName("public") private Boolean publicGist;
|
||||
|
||||
@Override public int describeContents() { return 0; }
|
||||
|
||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeSerializable(this.files);
|
||||
dest.writeString(this.description);
|
||||
dest.writeByte(this.publicGist ? (byte) 1 : (byte) 0);
|
||||
dest.writeValue(this.publicGist);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"WeakerAccess", "unchecked"}) protected CreateGistModel(Parcel in) {
|
||||
@SuppressWarnings("unchecked") private CreateGistModel(Parcel in) {
|
||||
this.files = (HashMap<String, FilesListModel>) in.readSerializable();
|
||||
this.description = in.readString();
|
||||
this.publicGist = in.readByte() != 0;
|
||||
this.publicGist = (Boolean) in.readValue(Boolean.class.getClassLoader());
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<CreateGistModel> CREATOR = new Parcelable.Creator<CreateGistModel>() {
|
||||
public static final Creator<CreateGistModel> CREATOR = new Creator<CreateGistModel>() {
|
||||
@Override public CreateGistModel createFromParcel(Parcel source) {return new CreateGistModel(source);}
|
||||
|
||||
@Override public CreateGistModel[] newArray(int size) {return new CreateGistModel[size];}
|
||||
|
||||
@ -14,11 +14,11 @@ import lombok.Setter;
|
||||
|
||||
@Getter @Setter public class EditReviewCommentModel implements Parcelable {
|
||||
|
||||
private int groupPosition;
|
||||
private int commentPosition;
|
||||
private String comment;
|
||||
private ReviewCommentModel commentModel;
|
||||
@SerializedName("in_reply_to") private long inReplyTo;
|
||||
public int groupPosition;
|
||||
public int commentPosition;
|
||||
public String comment;
|
||||
public ReviewCommentModel commentModel;
|
||||
@SerializedName("in_reply_to") public long inReplyTo;
|
||||
|
||||
|
||||
public EditReviewCommentModel() {}
|
||||
@ -33,7 +33,7 @@ import lombok.Setter;
|
||||
dest.writeLong(this.inReplyTo);
|
||||
}
|
||||
|
||||
protected EditReviewCommentModel(Parcel in) {
|
||||
private EditReviewCommentModel(Parcel in) {
|
||||
this.groupPosition = in.readInt();
|
||||
this.commentPosition = in.readInt();
|
||||
this.comment = in.readString();
|
||||
|
||||
@ -6,22 +6,24 @@ import android.os.Parcelable;
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Created by Kosh on 12 Nov 2016, 11:09 AM
|
||||
*/
|
||||
|
||||
@Getter @Setter @NoArgsConstructor
|
||||
@Getter @Setter
|
||||
public class FilesListModel implements Parcelable, Serializable {
|
||||
private String filename;
|
||||
private String type;
|
||||
private String rawUrl;
|
||||
private long size;
|
||||
private String content;
|
||||
private boolean needFetching;
|
||||
private String language;
|
||||
public String filename;
|
||||
public String type;
|
||||
public String rawUrl;
|
||||
public Long size;
|
||||
public String content;
|
||||
public Boolean needFetching;
|
||||
public String language;
|
||||
|
||||
public FilesListModel() {
|
||||
}
|
||||
|
||||
@Override public int describeContents() { return 0; }
|
||||
|
||||
@ -29,9 +31,9 @@ public class FilesListModel implements Parcelable, Serializable {
|
||||
dest.writeString(this.filename);
|
||||
dest.writeString(this.type);
|
||||
dest.writeString(this.rawUrl);
|
||||
dest.writeLong(this.size);
|
||||
dest.writeValue(this.size);
|
||||
dest.writeString(this.content);
|
||||
dest.writeByte(this.needFetching ? (byte) 1 : (byte) 0);
|
||||
dest.writeValue(this.needFetching);
|
||||
dest.writeString(this.language);
|
||||
}
|
||||
|
||||
@ -39,9 +41,9 @@ public class FilesListModel implements Parcelable, Serializable {
|
||||
this.filename = in.readString();
|
||||
this.type = in.readString();
|
||||
this.rawUrl = in.readString();
|
||||
this.size = in.readLong();
|
||||
this.size = (Long) in.readValue(Long.class.getClassLoader());
|
||||
this.content = in.readString();
|
||||
this.needFetching = in.readByte() != 0;
|
||||
this.needFetching = (Boolean) in.readValue(Boolean.class.getClassLoader());
|
||||
this.language = in.readString();
|
||||
}
|
||||
|
||||
|
||||
@ -146,7 +146,7 @@ public class FilterOptionsModel implements Parcelable {
|
||||
dest.writeByte(this.isOrg ? (byte) 1 : (byte) 0);
|
||||
}
|
||||
|
||||
protected FilterOptionsModel(Parcel in) {
|
||||
private FilterOptionsModel(Parcel in) {
|
||||
this.type = in.readString();
|
||||
this.sort = in.readString();
|
||||
this.sortDirection = in.readString();
|
||||
|
||||
@ -152,8 +152,7 @@ import lombok.Setter;
|
||||
}
|
||||
|
||||
@NonNull public static List<FragmentPagerAdapterModel> buildForGist(@NonNull Context context, @NonNull Gist gistsModel) {
|
||||
|
||||
return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.files), GistFilesListFragment.newInstance(gistsModel.getFiles())),
|
||||
return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.files), GistFilesListFragment.newInstance(gistsModel.getFilesAsList(), false)),
|
||||
new FragmentPagerAdapterModel(context.getString(R.string.comments), GistCommentsFragment.newInstance(gistsModel.getGistId())))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ import static com.annimon.stream.Collectors.toList;
|
||||
private Notification notification;
|
||||
private Date date;
|
||||
|
||||
public GroupedNotificationModel(Repo repo) {
|
||||
private GroupedNotificationModel(Repo repo) {
|
||||
this.type = HEADER;
|
||||
this.repo = repo;
|
||||
}
|
||||
|
||||
@ -6,14 +6,11 @@ import android.os.Parcelable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Created by Kosh on 07 May 2017, 5:08 PM
|
||||
*/
|
||||
|
||||
@Getter @Setter public class GroupedReviewModel implements Parcelable {
|
||||
public class GroupedReviewModel implements Parcelable {
|
||||
|
||||
private int position; //to group with!
|
||||
private String diffText;
|
||||
@ -22,9 +19,56 @@ import lombok.Setter;
|
||||
private long id;
|
||||
private List<ReviewCommentModel> comments;
|
||||
|
||||
|
||||
public GroupedReviewModel() {}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setPosition(int position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public String getDiffText() {
|
||||
return diffText;
|
||||
}
|
||||
|
||||
public void setDiffText(String diffText) {
|
||||
this.diffText = diffText;
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(Date date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public List<ReviewCommentModel> getComments() {
|
||||
return comments;
|
||||
}
|
||||
|
||||
public void setComments(List<ReviewCommentModel> comments) {
|
||||
this.comments = comments;
|
||||
}
|
||||
|
||||
@Override public int describeContents() { return 0; }
|
||||
|
||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||
@ -36,7 +80,7 @@ import lombok.Setter;
|
||||
dest.writeTypedList(this.comments);
|
||||
}
|
||||
|
||||
protected GroupedReviewModel(Parcel in) {
|
||||
private GroupedReviewModel(Parcel in) {
|
||||
this.position = in.readInt();
|
||||
this.diffText = in.readString();
|
||||
long tmpDate = in.readLong();
|
||||
|
||||
@ -25,7 +25,7 @@ import lombok.Setter;
|
||||
|
||||
public ImgurReponseModel() {}
|
||||
|
||||
protected ImgurReponseModel(Parcel in) {
|
||||
private ImgurReponseModel(Parcel in) {
|
||||
this.success = in.readByte() != 0;
|
||||
this.status = in.readInt();
|
||||
this.data = in.readParcelable(ImgurImage.class.getClassLoader());
|
||||
@ -52,7 +52,7 @@ import lombok.Setter;
|
||||
dest.writeString(this.link);
|
||||
}
|
||||
|
||||
protected ImgurImage(Parcel in) {
|
||||
private ImgurImage(Parcel in) {
|
||||
this.title = in.readString();
|
||||
this.description = in.readString();
|
||||
this.link = in.readString();
|
||||
|
||||
@ -55,7 +55,7 @@ public class IssueEventAdapterModel implements Parcelable {
|
||||
dest.writeParcelable(this.issueModel, flags);
|
||||
}
|
||||
|
||||
protected IssueEventAdapterModel(Parcel in) {
|
||||
private IssueEventAdapterModel(Parcel in) {
|
||||
this.type = in.readInt();
|
||||
this.issueEvent = in.readParcelable(IssueEvent.class.getClassLoader());
|
||||
this.issueModel = in.readParcelable(Issue.class.getClassLoader());
|
||||
|
||||
@ -71,7 +71,7 @@ public class IssueRequestModel implements Parcelable {
|
||||
dest.writeStringList(this.labels);
|
||||
}
|
||||
|
||||
protected IssueRequestModel(Parcel in) {
|
||||
private IssueRequestModel(Parcel in) {
|
||||
int tmpState = in.readInt();
|
||||
this.state = tmpState == -1 ? null : IssueState.values()[tmpState];
|
||||
this.title = in.readString();
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
package com.fastaccess.data.dao;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Created by Kosh on 15 Nov 2016, 7:04 PM
|
||||
*/
|
||||
|
||||
|
||||
@Getter @Setter @NoArgsConstructor
|
||||
public class IssuesPageable<M> implements Parcelable {
|
||||
|
||||
public int first;
|
||||
public int next;
|
||||
public int prev;
|
||||
public int last;
|
||||
public int totalCount;
|
||||
public boolean incompleteResults;
|
||||
public List<M> items;
|
||||
|
||||
@Override public int describeContents() { return 0; }
|
||||
|
||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(this.first);
|
||||
dest.writeInt(this.next);
|
||||
dest.writeInt(this.prev);
|
||||
dest.writeInt(this.last);
|
||||
dest.writeInt(this.totalCount);
|
||||
dest.writeByte(this.incompleteResults ? (byte) 1 : (byte) 0);
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess") protected IssuesPageable(Parcel in) {
|
||||
this.first = in.readInt();
|
||||
this.next = in.readInt();
|
||||
this.prev = in.readInt();
|
||||
this.last = in.readInt();
|
||||
this.totalCount = in.readInt();
|
||||
this.incompleteResults = in.readByte() != 0;
|
||||
}
|
||||
|
||||
public static final Creator<IssuesPageable> CREATOR = new Creator<IssuesPageable>() {
|
||||
@Override public IssuesPageable createFromParcel(Parcel source) {return new IssuesPageable(source);}
|
||||
|
||||
@Override public IssuesPageable[] newArray(int size) {return new IssuesPageable[size];}
|
||||
};
|
||||
}
|
||||
@ -24,7 +24,7 @@ import lombok.ToString;
|
||||
|
||||
public LanguageColorModel() {}
|
||||
|
||||
protected LanguageColorModel(Parcel in) {
|
||||
private LanguageColorModel(Parcel in) {
|
||||
this.color = in.readString();
|
||||
this.url = in.readString();
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ import lombok.Setter;
|
||||
|
||||
@Override public void writeToParcel(Parcel dest, int flags) {dest.writeString(this.content);}
|
||||
|
||||
protected PostReactionModel(Parcel in) {this.content = in.readString();}
|
||||
private 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);}
|
||||
|
||||
@ -55,7 +55,7 @@ public class PullRequestAdapterModel implements Parcelable {
|
||||
dest.writeParcelable(this.pullRequest, flags);
|
||||
}
|
||||
|
||||
protected PullRequestAdapterModel(Parcel in) {
|
||||
private PullRequestAdapterModel(Parcel in) {
|
||||
this.type = in.readInt();
|
||||
this.issueEvent = in.readParcelable(IssueEvent.class.getClassLoader());
|
||||
this.pullRequest = in.readParcelable(PullRequest.class.getClassLoader());
|
||||
|
||||
@ -41,7 +41,7 @@ import lombok.Setter;
|
||||
dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1);
|
||||
}
|
||||
|
||||
protected PullRequestStatusModel(Parcel in) {
|
||||
private PullRequestStatusModel(Parcel in) {
|
||||
int tmpState = in.readInt();
|
||||
this.state = tmpState == -1 ? null : StatusStateType.values()[tmpState];
|
||||
this.sha = in.readString();
|
||||
|
||||
@ -2,12 +2,18 @@ package com.fastaccess.data.dao;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.fastaccess.data.dao.model.User;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
import pr.PullRequestTimelineQuery;
|
||||
|
||||
/**
|
||||
* Created by Kosh on 28 Mar 2017, 9:15 PM
|
||||
@ -15,18 +21,19 @@ 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;
|
||||
@SerializedName("-1") private int minusOne;
|
||||
private int laugh;
|
||||
private int hooray;
|
||||
private int confused;
|
||||
private int heart;
|
||||
private String content;
|
||||
private User user;
|
||||
private boolean isCallingApi;
|
||||
public long id;
|
||||
public String url;
|
||||
public int total_count;
|
||||
@SerializedName("+1") public int plusOne;
|
||||
@SerializedName("-1") public int minusOne;
|
||||
public int laugh;
|
||||
public int hooray;
|
||||
public int confused;
|
||||
public int heart;
|
||||
public String content;
|
||||
public User user;
|
||||
public boolean viewerHasReacted;
|
||||
public boolean isCallingApi;
|
||||
|
||||
public ReactionsModel() {}
|
||||
|
||||
@ -81,4 +88,46 @@ import lombok.Setter;
|
||||
|
||||
@Override public ReactionsModel[] newArray(int size) {return new ReactionsModel[size];}
|
||||
};
|
||||
|
||||
@NonNull public static List<ReactionsModel> getReactionGroup(@Nullable List<PullRequestTimelineQuery.ReactionGroup> reactions) {
|
||||
List<ReactionsModel> models = new ArrayList<>();
|
||||
if (reactions != null && !reactions.isEmpty()) {
|
||||
for (PullRequestTimelineQuery.ReactionGroup reaction : reactions) {
|
||||
ReactionsModel model = new ReactionsModel();
|
||||
model.setContent(reaction.content().name());
|
||||
model.setViewerHasReacted(reaction.viewerHasReacted());
|
||||
model.setTotal_count(reaction.users().totalCount());
|
||||
models.add(model);
|
||||
}
|
||||
}
|
||||
return models;
|
||||
}
|
||||
|
||||
@NonNull public static List<ReactionsModel> getReaction(@Nullable List<PullRequestTimelineQuery.ReactionGroup1> reactions) {
|
||||
List<ReactionsModel> models = new ArrayList<>();
|
||||
if (reactions != null && !reactions.isEmpty()) {
|
||||
for (PullRequestTimelineQuery.ReactionGroup1 reaction : reactions) {
|
||||
ReactionsModel model = new ReactionsModel();
|
||||
model.setContent(reaction.content().name());
|
||||
model.setViewerHasReacted(reaction.viewerHasReacted());
|
||||
model.setTotal_count(reaction.users().totalCount());
|
||||
models.add(model);
|
||||
}
|
||||
}
|
||||
return models;
|
||||
}
|
||||
|
||||
@NonNull public static List<ReactionsModel> getReaction2(@Nullable List<PullRequestTimelineQuery.ReactionGroup2> reactions) {
|
||||
List<ReactionsModel> models = new ArrayList<>();
|
||||
if (reactions != null && !reactions.isEmpty()) {
|
||||
for (PullRequestTimelineQuery.ReactionGroup2 reaction : reactions) {
|
||||
ReactionsModel model = new ReactionsModel();
|
||||
model.setContent(reaction.content().name());
|
||||
model.setViewerHasReacted(reaction.viewerHasReacted());
|
||||
model.setTotal_count(reaction.users().totalCount());
|
||||
models.add(model);
|
||||
}
|
||||
}
|
||||
return models;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,14 +7,11 @@ import com.fastaccess.data.dao.model.User;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Created by Kosh on 04 May 2017, 7:10 PM
|
||||
*/
|
||||
|
||||
@Getter @Setter public class ReviewCommentModel implements Parcelable {
|
||||
public class ReviewCommentModel implements Parcelable {
|
||||
|
||||
private long id;
|
||||
private String url;
|
||||
@ -36,6 +33,147 @@ import lombok.Setter;
|
||||
|
||||
public ReviewCommentModel() {}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public long getPullRequestReviewId() {
|
||||
return pullRequestReviewId;
|
||||
}
|
||||
|
||||
public void setPullRequestReviewId(long pullRequestReviewId) {
|
||||
this.pullRequestReviewId = pullRequestReviewId;
|
||||
}
|
||||
|
||||
public String getDiffHunk() {
|
||||
return diffHunk;
|
||||
}
|
||||
|
||||
public void setDiffHunk(String diffHunk) {
|
||||
this.diffHunk = diffHunk;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setPosition(int position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public int getOriginalPosition() {
|
||||
return originalPosition;
|
||||
}
|
||||
|
||||
public void setOriginalPosition(int originalPosition) {
|
||||
this.originalPosition = originalPosition;
|
||||
}
|
||||
|
||||
public String getCommitId() {
|
||||
return commitId;
|
||||
}
|
||||
|
||||
public void setCommitId(String commitId) {
|
||||
this.commitId = commitId;
|
||||
}
|
||||
|
||||
public String getOriginalCommitId() {
|
||||
return originalCommitId;
|
||||
}
|
||||
|
||||
public void setOriginalCommitId(String originalCommitId) {
|
||||
this.originalCommitId = originalCommitId;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getBodyHtml() {
|
||||
return bodyHtml;
|
||||
}
|
||||
|
||||
public void setBodyHtml(String bodyHtml) {
|
||||
this.bodyHtml = bodyHtml;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public void setBody(String body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public Date getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(Date createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public Date getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public void setUpdatedAt(Date updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
|
||||
public String getHtmlUrl() {
|
||||
return htmlUrl;
|
||||
}
|
||||
|
||||
public void setHtmlUrl(String htmlUrl) {
|
||||
this.htmlUrl = htmlUrl;
|
||||
}
|
||||
|
||||
public String getPullRequestUrl() {
|
||||
return pullRequestUrl;
|
||||
}
|
||||
|
||||
public void setPullRequestUrl(String pullRequestUrl) {
|
||||
this.pullRequestUrl = pullRequestUrl;
|
||||
}
|
||||
|
||||
public ReactionsModel getReactions() {
|
||||
return reactions;
|
||||
}
|
||||
|
||||
public void setReactions(ReactionsModel reactions) {
|
||||
this.reactions = reactions;
|
||||
}
|
||||
|
||||
@Override public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ReviewCommentModel that = (ReviewCommentModel) o;
|
||||
|
||||
return id == that.id;
|
||||
}
|
||||
|
||||
@Override public int hashCode() {
|
||||
return (int) (id ^ (id >>> 32));
|
||||
}
|
||||
|
||||
@Override public int describeContents() { return 0; }
|
||||
|
||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||
@ -85,4 +223,12 @@ import lombok.Setter;
|
||||
|
||||
@Override public ReviewCommentModel[] newArray(int size) {return new ReviewCommentModel[size];}
|
||||
};
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,59 +4,67 @@ import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.fastaccess.data.dao.model.User;
|
||||
import com.fastaccess.data.dao.types.ReviewStateType;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Created by Kosh on 10 Apr 2017, 4:26 PM
|
||||
*/
|
||||
|
||||
@Getter @Setter public class ReviewModel implements Parcelable {
|
||||
public class ReviewModel implements Parcelable {
|
||||
|
||||
private long id;
|
||||
private User user;
|
||||
@SerializedName("body_html") private String body;
|
||||
private ReviewStateType state;
|
||||
private String bodyHtml;
|
||||
private String state;
|
||||
private Date submittedAt;
|
||||
private String commitId;
|
||||
private String diffText;
|
||||
private List<ReviewCommentModel> comments;
|
||||
private ReactionsModel reactions;
|
||||
private String bodyText;
|
||||
|
||||
public ReviewModel() {}
|
||||
|
||||
@Override public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ReviewModel that = (ReviewModel) o;
|
||||
return id == that.id;
|
||||
}
|
||||
|
||||
@Override public int hashCode() {
|
||||
return (int) (id ^ (id >>> 32));
|
||||
}
|
||||
|
||||
@Override public int describeContents() { return 0; }
|
||||
|
||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeLong(this.id);
|
||||
dest.writeParcelable(this.user, flags);
|
||||
dest.writeString(this.body);
|
||||
dest.writeInt(this.state == null ? -1 : this.state.ordinal());
|
||||
dest.writeString(this.bodyHtml);
|
||||
dest.writeString(this.state);
|
||||
dest.writeLong(this.submittedAt != null ? this.submittedAt.getTime() : -1);
|
||||
dest.writeString(this.commitId);
|
||||
dest.writeString(this.diffText);
|
||||
dest.writeTypedList(this.comments);
|
||||
dest.writeParcelable(this.reactions, flags);
|
||||
dest.writeString(this.bodyText);
|
||||
}
|
||||
|
||||
protected ReviewModel(Parcel in) {
|
||||
this.id = in.readLong();
|
||||
this.user = in.readParcelable(User.class.getClassLoader());
|
||||
this.body = in.readString();
|
||||
int tmpState = in.readInt();
|
||||
this.state = tmpState == -1 ? null : ReviewStateType.values()[tmpState];
|
||||
this.bodyHtml = in.readString();
|
||||
this.state = in.readString();
|
||||
long tmpSubmittedAt = in.readLong();
|
||||
this.submittedAt = tmpSubmittedAt == -1 ? null : new Date(tmpSubmittedAt);
|
||||
this.commitId = in.readString();
|
||||
this.diffText = in.readString();
|
||||
this.comments = in.createTypedArrayList(ReviewCommentModel.CREATOR);
|
||||
this.reactions = in.readParcelable(ReactionsModel.class.getClassLoader());
|
||||
this.bodyText = in.readString();
|
||||
}
|
||||
|
||||
public static final Creator<ReviewModel> CREATOR = new Creator<ReviewModel>() {
|
||||
@ -64,4 +72,84 @@ import lombok.Setter;
|
||||
|
||||
@Override public ReviewModel[] newArray(int size) {return new ReviewModel[size];}
|
||||
};
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public String getBodyHtml() {
|
||||
return bodyHtml;
|
||||
}
|
||||
|
||||
public void setBodyHtml(String bodyHtml) {
|
||||
this.bodyHtml = bodyHtml;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(String state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public Date getSubmittedAt() {
|
||||
return submittedAt;
|
||||
}
|
||||
|
||||
public void setSubmittedAt(Date submittedAt) {
|
||||
this.submittedAt = submittedAt;
|
||||
}
|
||||
|
||||
public String getCommitId() {
|
||||
return commitId;
|
||||
}
|
||||
|
||||
public void setCommitId(String commitId) {
|
||||
this.commitId = commitId;
|
||||
}
|
||||
|
||||
public String getDiffText() {
|
||||
return diffText;
|
||||
}
|
||||
|
||||
public void setDiffText(String diffText) {
|
||||
this.diffText = diffText;
|
||||
}
|
||||
|
||||
public List<ReviewCommentModel> getComments() {
|
||||
return comments;
|
||||
}
|
||||
|
||||
public void setComments(List<ReviewCommentModel> comments) {
|
||||
this.comments = comments;
|
||||
}
|
||||
|
||||
public ReactionsModel getReactions() {
|
||||
return reactions;
|
||||
}
|
||||
|
||||
public void setReactions(ReactionsModel reactions) {
|
||||
this.reactions = reactions;
|
||||
}
|
||||
|
||||
public String getBodyText() {
|
||||
return bodyText;
|
||||
}
|
||||
|
||||
public void setBodyText(String bodyText) {
|
||||
this.bodyText = bodyText;
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ import lombok.Setter;
|
||||
dest.writeTypedList(this.comments);
|
||||
}
|
||||
|
||||
protected ReviewRequestModel(Parcel in) {
|
||||
private ReviewRequestModel(Parcel in) {
|
||||
this.commitId = in.readString();
|
||||
this.body = in.readString();
|
||||
this.event = in.readString();
|
||||
|
||||
@ -25,7 +25,7 @@ import lombok.Setter;
|
||||
|
||||
public SlackInvitePostModel() {}
|
||||
|
||||
protected SlackInvitePostModel(Parcel in) {
|
||||
private SlackInvitePostModel(Parcel in) {
|
||||
this.email = in.readString();
|
||||
this.first_name = in.readString();
|
||||
this.last_name = in.readString();
|
||||
|
||||
@ -23,7 +23,7 @@ import lombok.Setter;
|
||||
|
||||
public SlackResponseModel() {}
|
||||
|
||||
protected SlackResponseModel(Parcel in) {
|
||||
private SlackResponseModel(Parcel in) {
|
||||
this.ok = in.readByte() != 0;
|
||||
this.error = in.readString();
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ import lombok.Setter;
|
||||
dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1);
|
||||
}
|
||||
|
||||
protected StatusesModel(Parcel in) {
|
||||
private StatusesModel(Parcel in) {
|
||||
this.url = in.readString();
|
||||
this.id = in.readInt();
|
||||
int tmpState = in.readInt();
|
||||
|
||||
@ -2,249 +2,104 @@ package com.fastaccess.data.dao;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.annimon.stream.Collectors;
|
||||
import com.annimon.stream.Stream;
|
||||
import com.fastaccess.data.dao.model.Comment;
|
||||
import com.fastaccess.data.dao.model.Issue;
|
||||
import com.fastaccess.data.dao.model.IssueEvent;
|
||||
import com.fastaccess.data.dao.model.PullRequest;
|
||||
import com.fastaccess.data.dao.timeline.GenericEvent;
|
||||
import com.fastaccess.data.dao.timeline.PullRequestCommitModel;
|
||||
import com.fastaccess.data.dao.types.IssueEventType;
|
||||
import com.fastaccess.data.dao.types.ReviewStateType;
|
||||
import com.fastaccess.helper.InputHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
|
||||
import static com.annimon.stream.Collectors.toList;
|
||||
|
||||
/**
|
||||
* Created by Kosh on 30 Mar 2017, 9:03 PM
|
||||
*/
|
||||
|
||||
@Getter @Setter @NoArgsConstructor public class TimelineModel implements Parcelable {
|
||||
public static final int HEADER = 0;
|
||||
public static final int STATUS = 1;
|
||||
public static final int REVIEW = 2;
|
||||
public static final int GROUPED_REVIEW = 3;
|
||||
public static final int EVENT = 4;
|
||||
public static final int COMMENT = 5;
|
||||
@Getter @Setter public class TimelineModel implements Parcelable {
|
||||
public static final int HEADER = 1;
|
||||
public static final int EVENT = 2;
|
||||
public static final int COMMENT = 3;
|
||||
public static final int REVIEW = 4;
|
||||
public static final int GROUP = 5;
|
||||
public static final int COMMIT_COMMENTS = 6;
|
||||
public static final int STATUS = 7;
|
||||
|
||||
private int type;
|
||||
private Issue issue;
|
||||
private IssueEventType event;
|
||||
private Comment comment;
|
||||
private IssueEvent event;
|
||||
private PullRequest pullRequest;
|
||||
private GenericEvent genericEvent;
|
||||
private PullRequestStatusModel status;
|
||||
private Issue issue;
|
||||
private PullRequest pullRequest;
|
||||
private ReviewModel review;
|
||||
private GroupedReviewModel groupedReview;
|
||||
private ReviewCommentModel reviewComment;
|
||||
private Date sortedDate;
|
||||
private GroupedReviewModel groupedReviewModel;
|
||||
private PullRequestCommitModel commit;
|
||||
|
||||
private TimelineModel(Issue issue) {
|
||||
this.type = HEADER;
|
||||
public TimelineModel(Issue issue) {
|
||||
this.issue = issue;
|
||||
this.sortedDate = issue.getCreatedAt();
|
||||
}
|
||||
|
||||
private TimelineModel(PullRequest pullRequest) {
|
||||
this.type = HEADER;
|
||||
public TimelineModel(PullRequest pullRequest) {
|
||||
this.pullRequest = pullRequest;
|
||||
this.sortedDate = pullRequest.getCreatedAt();
|
||||
}
|
||||
|
||||
private TimelineModel(Comment comment) {
|
||||
this.type = COMMENT;
|
||||
public TimelineModel(Comment comment) {
|
||||
this.comment = comment;
|
||||
this.sortedDate = comment.getCreatedAt() == null ? new Date() : comment.getCreatedAt();
|
||||
this.event = IssueEventType.commented;
|
||||
}
|
||||
|
||||
private TimelineModel(IssueEvent event) {
|
||||
this.type = EVENT;
|
||||
this.event = event;
|
||||
this.sortedDate = event.getCreatedAt();
|
||||
public TimelineModel(PullRequestStatusModel statusModel) {
|
||||
this.status = statusModel;
|
||||
}
|
||||
|
||||
private TimelineModel(PullRequestStatusModel status) {
|
||||
this.type = STATUS;
|
||||
this.status = status;
|
||||
this.sortedDate = status.getCreatedAt();
|
||||
public TimelineModel() {}
|
||||
|
||||
public int getType() {
|
||||
if (getEvent() != null) {
|
||||
switch (getEvent()) {
|
||||
case commented:
|
||||
return COMMENT;
|
||||
case reviewed:
|
||||
case changes_requested:
|
||||
return REVIEW;
|
||||
case GROUPED:
|
||||
return GROUP;
|
||||
case commit_commented:
|
||||
return COMMIT_COMMENTS;
|
||||
default:
|
||||
return EVENT;
|
||||
}
|
||||
} else {
|
||||
if (issue != null || pullRequest != null) return HEADER;
|
||||
else if (status != null) return STATUS;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private TimelineModel(ReviewModel review) {
|
||||
this.type = REVIEW;
|
||||
this.review = review;
|
||||
this.sortedDate = review.getSubmittedAt();
|
||||
}
|
||||
|
||||
private TimelineModel(GroupedReviewModel groupedReview) {
|
||||
this.type = GROUPED_REVIEW;
|
||||
this.groupedReview = groupedReview;
|
||||
this.sortedDate = groupedReview.getDate();
|
||||
}
|
||||
|
||||
@NonNull public static TimelineModel constructHeader(@NonNull Issue issue) {
|
||||
public static TimelineModel constructHeader(Issue issue) {
|
||||
return new TimelineModel(issue);
|
||||
}
|
||||
|
||||
@NonNull public static TimelineModel constructHeader(@NonNull PullRequest pullRequest) {
|
||||
public static TimelineModel constructHeader(PullRequest pullRequest) {
|
||||
return new TimelineModel(pullRequest);
|
||||
}
|
||||
|
||||
@NonNull public static TimelineModel constructComment(@NonNull Comment comment) {
|
||||
public static TimelineModel constructComment(Comment comment) {
|
||||
return new TimelineModel(comment);
|
||||
}
|
||||
|
||||
@NonNull public static List<TimelineModel> construct(@Nullable List<Comment> commentList) {
|
||||
ArrayList<TimelineModel> list = new ArrayList<>();
|
||||
if (commentList != null && !commentList.isEmpty()) {
|
||||
list.addAll(Stream.of(commentList)
|
||||
.map(TimelineModel::new)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@NonNull public static List<TimelineModel> construct(@Nullable List<Comment> commentList, @Nullable List<IssueEvent> eventList) {
|
||||
ArrayList<TimelineModel> list = new ArrayList<>();
|
||||
if (commentList != null && !commentList.isEmpty()) {
|
||||
list.addAll(Stream.of(commentList)
|
||||
.map(TimelineModel::new)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
if (eventList != null && !eventList.isEmpty()) {
|
||||
list.addAll(constructLabels(eventList));
|
||||
}
|
||||
|
||||
return Stream.of(list).sorted((o1, o2) -> {
|
||||
if (o1.getEvent() != null && o2.getComment() != null) {
|
||||
return o1.getEvent().getCreatedAt().compareTo(o2.getComment().getCreatedAt());
|
||||
} else if (o1.getComment() != null && o2.getEvent() != null) {
|
||||
return o1.getComment().getCreatedAt().compareTo(o2.getEvent().getCreatedAt());
|
||||
} else {
|
||||
return Integer.valueOf(o1.getType()).compareTo(o2.getType());
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@NonNull public static List<TimelineModel> construct(@Nullable List<Comment> commentList, @Nullable List<IssueEvent> eventList,
|
||||
@Nullable PullRequestStatusModel status, @Nullable List<ReviewModel> reviews,
|
||||
@Nullable List<ReviewCommentModel> reviewComments) {
|
||||
ArrayList<TimelineModel> list = new ArrayList<>();
|
||||
if (status != null) {
|
||||
list.add(new TimelineModel(status));
|
||||
}
|
||||
if (reviews != null && !reviews.isEmpty()) {
|
||||
list.addAll(constructReviews(reviews, reviewComments));
|
||||
}
|
||||
if (commentList != null && !commentList.isEmpty()) {
|
||||
list.addAll(Stream.of(commentList)
|
||||
.map(TimelineModel::new)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
if (eventList != null && !eventList.isEmpty()) {
|
||||
list.addAll(constructLabels(eventList));
|
||||
}
|
||||
|
||||
return Stream.of(list).sortBy(model -> {
|
||||
if (model.getSortedDate() != null) {
|
||||
return model.getSortedDate().getTime();
|
||||
} else {
|
||||
return (long) model.getType();
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@NonNull private static List<TimelineModel> constructLabels(@NonNull List<IssueEvent> eventList) {
|
||||
List<TimelineModel> models = new ArrayList<>();
|
||||
Map<String, List<IssueEvent>> issueEventMap = Stream.of(eventList)
|
||||
.filter(value -> value.getEvent() != null && value.getEvent() != IssueEventType.subscribed &&
|
||||
value.getEvent() != IssueEventType.unsubscribed && value.getEvent() != IssueEventType.mentioned)
|
||||
.collect(Collectors.groupingBy(issueEvent -> {
|
||||
if (issueEvent.getAssigner() != null && issueEvent.getAssignee() != null) {
|
||||
return issueEvent.getAssigner().getLogin();
|
||||
}
|
||||
return issueEvent.getActor().getLogin();
|
||||
}));
|
||||
if (issueEventMap != null && !issueEventMap.isEmpty()) {
|
||||
for (Map.Entry<String, List<IssueEvent>> stringListEntry : issueEventMap.entrySet()) {
|
||||
List<LabelModel> labelModels = new ArrayList<>();
|
||||
List<IssueEvent> events = stringListEntry.getValue();
|
||||
IssueEvent toAdd = null;
|
||||
for (IssueEvent event : events) {
|
||||
if (event.getEvent() == IssueEventType.labeled || event.getEvent() == IssueEventType.unlabeled) {
|
||||
if (toAdd == null) {
|
||||
toAdd = event;
|
||||
}
|
||||
long time = toAdd.getCreatedAt().after(event.getCreatedAt()) ? (toAdd.getCreatedAt().getTime() - event
|
||||
.getCreatedAt().getTime()) : (event.getCreatedAt().getTime() - toAdd.getCreatedAt().getTime());
|
||||
if (TimeUnit.MINUTES.toMinutes(time) <= 2 && toAdd.getEvent() == event.getEvent()) {
|
||||
labelModels.add(event.getLabel());
|
||||
} else {
|
||||
models.add(new TimelineModel(event));
|
||||
}
|
||||
} else {
|
||||
models.add(new TimelineModel(event));
|
||||
}
|
||||
}
|
||||
if (toAdd != null) {
|
||||
toAdd.setLabels(labelModels);
|
||||
models.add(new TimelineModel(toAdd));
|
||||
}
|
||||
}
|
||||
}
|
||||
return Stream.of(models)
|
||||
.sortBy(TimelineModel::getSortedDate)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@NonNull private static List<TimelineModel> constructReviews
|
||||
(@NonNull List<ReviewModel> reviews, @Nullable List<ReviewCommentModel> comments) {
|
||||
List<TimelineModel> models = new ArrayList<>();
|
||||
if (comments == null || comments.isEmpty()) {
|
||||
models.addAll(Stream.of(reviews)
|
||||
.map(TimelineModel::new)
|
||||
.collect(Collectors.toList()));
|
||||
} else { // this is how bad github API is.
|
||||
Map<Integer, List<ReviewCommentModel>> mappedComments = Stream.of(comments)
|
||||
.collect(Collectors.groupingBy(ReviewCommentModel::getOriginalPosition, LinkedHashMap::new,
|
||||
Collectors.mapping(o -> o, toList())));
|
||||
for (Map.Entry<Integer, List<ReviewCommentModel>> entry : mappedComments.entrySet()) {
|
||||
List<ReviewCommentModel> reviewCommentModels = entry.getValue();
|
||||
GroupedReviewModel groupedReviewModel = new GroupedReviewModel();
|
||||
if (!reviewCommentModels.isEmpty()) {
|
||||
ReviewCommentModel reviewCommentModel = reviewCommentModels.get(0);
|
||||
groupedReviewModel.setPath(reviewCommentModel.getPath());
|
||||
groupedReviewModel.setDiffText(reviewCommentModel.getDiffHunk());
|
||||
groupedReviewModel.setDate(reviewCommentModel.getCreatedAt());
|
||||
groupedReviewModel.setPosition(reviewCommentModel.getOriginalPosition());
|
||||
groupedReviewModel.setId(reviewCommentModel.getId());
|
||||
}
|
||||
for (ReviewCommentModel reviewCommentModel : reviewCommentModels) {
|
||||
if (reviewCommentModel.getCreatedAt() != null) {
|
||||
groupedReviewModel.setDate(reviewCommentModel.getCreatedAt());
|
||||
break;
|
||||
}
|
||||
}
|
||||
groupedReviewModel.setComments(reviewCommentModels);
|
||||
models.add(new TimelineModel(groupedReviewModel));
|
||||
}
|
||||
models.addAll(Stream.of(reviews)
|
||||
.filter(reviewModel -> !InputHelper.isEmpty(reviewModel.getBody()) || reviewModel.getState() == ReviewStateType.APPROVED)
|
||||
.map(TimelineModel::new)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
return models;
|
||||
@NonNull public static Observable<List<TimelineModel>> construct(@Nullable List<Comment> comments) {
|
||||
if (comments == null || comments.isEmpty()) return Observable.empty();
|
||||
return Observable.fromIterable(comments)
|
||||
.map(TimelineModel::new)
|
||||
.toList()
|
||||
.toObservable();
|
||||
}
|
||||
|
||||
@Override public boolean equals(Object o) {
|
||||
@ -258,33 +113,104 @@ import static com.annimon.stream.Collectors.toList;
|
||||
return comment != null ? (int) comment.getId() : 0;
|
||||
}
|
||||
|
||||
|
||||
public IssueEventType getEvent() {
|
||||
return event;
|
||||
}
|
||||
|
||||
public void setEvent(IssueEventType event) {
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
public Comment getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
public void setComment(Comment comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
public GenericEvent getGenericEvent() {
|
||||
return genericEvent;
|
||||
}
|
||||
|
||||
public void setGenericEvent(GenericEvent genericEvent) {
|
||||
this.genericEvent = genericEvent;
|
||||
}
|
||||
|
||||
public PullRequestStatusModel getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(PullRequestStatusModel status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Issue getIssue() {
|
||||
return issue;
|
||||
}
|
||||
|
||||
public void setIssue(Issue issue) {
|
||||
this.issue = issue;
|
||||
}
|
||||
|
||||
public PullRequest getPullRequest() {
|
||||
return pullRequest;
|
||||
}
|
||||
|
||||
public void setPullRequest(PullRequest pullRequest) {
|
||||
this.pullRequest = pullRequest;
|
||||
}
|
||||
|
||||
public ReviewModel getReview() {
|
||||
return review;
|
||||
}
|
||||
|
||||
public void setReview(ReviewModel review) {
|
||||
this.review = review;
|
||||
}
|
||||
|
||||
public GroupedReviewModel getGroupedReviewModel() {
|
||||
return groupedReviewModel;
|
||||
}
|
||||
|
||||
public void setGroupedReviewModel(GroupedReviewModel groupedReviewModel) {
|
||||
this.groupedReviewModel = groupedReviewModel;
|
||||
}
|
||||
|
||||
public PullRequestCommitModel getCommit() {
|
||||
return commit;
|
||||
}
|
||||
|
||||
public void setCommit(PullRequestCommitModel commit) {
|
||||
this.commit = commit;
|
||||
}
|
||||
|
||||
@Override public int describeContents() { return 0; }
|
||||
|
||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(this.type);
|
||||
dest.writeParcelable(this.issue, flags);
|
||||
dest.writeInt(this.event == null ? -1 : this.event.ordinal());
|
||||
dest.writeParcelable(this.comment, flags);
|
||||
dest.writeParcelable(this.event, flags);
|
||||
dest.writeParcelable(this.pullRequest, flags);
|
||||
dest.writeParcelable(this.genericEvent, flags);
|
||||
dest.writeParcelable(this.status, flags);
|
||||
dest.writeParcelable(this.issue, flags);
|
||||
dest.writeParcelable(this.pullRequest, flags);
|
||||
dest.writeParcelable(this.review, flags);
|
||||
dest.writeParcelable(this.groupedReview, flags);
|
||||
dest.writeParcelable(this.reviewComment, flags);
|
||||
dest.writeLong(this.sortedDate != null ? this.sortedDate.getTime() : -1);
|
||||
dest.writeParcelable(this.groupedReviewModel, flags);
|
||||
dest.writeParcelable(this.commit, flags);
|
||||
}
|
||||
|
||||
protected TimelineModel(Parcel in) {
|
||||
this.type = in.readInt();
|
||||
this.issue = in.readParcelable(Issue.class.getClassLoader());
|
||||
int tmpEvent = in.readInt();
|
||||
this.event = tmpEvent == -1 ? null : IssueEventType.values()[tmpEvent];
|
||||
this.comment = in.readParcelable(Comment.class.getClassLoader());
|
||||
this.event = in.readParcelable(IssueEvent.class.getClassLoader());
|
||||
this.pullRequest = in.readParcelable(PullRequest.class.getClassLoader());
|
||||
this.genericEvent = in.readParcelable(GenericEvent.class.getClassLoader());
|
||||
this.status = in.readParcelable(PullRequestStatusModel.class.getClassLoader());
|
||||
this.issue = in.readParcelable(Issue.class.getClassLoader());
|
||||
this.pullRequest = in.readParcelable(PullRequest.class.getClassLoader());
|
||||
this.review = in.readParcelable(ReviewModel.class.getClassLoader());
|
||||
this.groupedReview = in.readParcelable(GroupedReviewModel.class.getClassLoader());
|
||||
this.reviewComment = in.readParcelable(ReviewCommentModel.class.getClassLoader());
|
||||
long tmpSortedDate = in.readLong();
|
||||
this.sortedDate = tmpSortedDate == -1 ? null : new Date(tmpSortedDate);
|
||||
this.groupedReviewModel = in.readParcelable(GroupedReviewModel.class.getClassLoader());
|
||||
this.commit = in.readParcelable(PullRequestCommitModel.class.getClassLoader());
|
||||
}
|
||||
|
||||
public static final Creator<TimelineModel> CREATOR = new Creator<TimelineModel>() {
|
||||
|
||||
@ -32,7 +32,7 @@ import lombok.Setter;
|
||||
dest.writeString(this.htmlUrl);
|
||||
}
|
||||
|
||||
protected WikiModel(Parcel in) {
|
||||
private WikiModel(Parcel in) {
|
||||
this.pageName = in.readString();
|
||||
this.title = in.readString();
|
||||
this.summary = in.readString();
|
||||
|
||||
@ -4,6 +4,7 @@ import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.annimon.stream.Collectors;
|
||||
import com.annimon.stream.LongStream;
|
||||
import com.annimon.stream.Stream;
|
||||
import com.fastaccess.App;
|
||||
@ -19,6 +20,7 @@ import com.google.gson.annotations.SerializedName;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
@ -134,12 +136,13 @@ import static com.fastaccess.data.dao.model.Gist.OWNER_NAME;
|
||||
return url != null ? url.hashCode() : 0;
|
||||
}
|
||||
|
||||
@NonNull public List<FilesListModel> getFilesAsList() {
|
||||
List<FilesListModel> models = new ArrayList<>();
|
||||
@NonNull public ArrayList<FilesListModel> getFilesAsList() {
|
||||
if (files != null) {
|
||||
models.addAll(files.values());
|
||||
return Stream.of(files)
|
||||
.map(Map.Entry::getValue)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
return models;
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@NonNull public SpannableBuilder getDisplayTitle(boolean isFromProfile) {
|
||||
|
||||
@ -92,6 +92,26 @@ import lombok.NoArgsConstructor;
|
||||
})).subscribe(o -> {/*do nothing*/}, Throwable::printStackTrace);
|
||||
}
|
||||
|
||||
public static Single<Boolean> saveAsSingle(@android.support.annotation.Nullable List<Notification> models) {
|
||||
if (models == null || models.isEmpty()) {
|
||||
return Single.just(true);
|
||||
}
|
||||
return RxHelper.getSingle(Single.fromPublisher(s -> {
|
||||
try {
|
||||
BlockingEntityStore<Persistable> dataStore = App.getInstance().getDataStore().toBlocking();
|
||||
for (Notification entity : models) {
|
||||
dataStore.delete(Notification.class).where(Notification.ID.eq(entity.getId())).get().value();
|
||||
}
|
||||
dataStore.insert(models);
|
||||
s.onNext(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
s.onError(e);
|
||||
}
|
||||
s.onComplete();
|
||||
}));
|
||||
}
|
||||
|
||||
public static Single<List<Notification>> getUnreadNotifications() {
|
||||
return App.getInstance()
|
||||
.getDataStore()
|
||||
@ -116,9 +136,9 @@ import lombok.NoArgsConstructor;
|
||||
public static boolean hasUnreadNotifications() {
|
||||
return App.getInstance()
|
||||
.getDataStore()
|
||||
.toBlocking()
|
||||
.count(Notification.class)
|
||||
.where(Notification.UNREAD.equal(true))
|
||||
.limit(1)
|
||||
.get()
|
||||
.value() > 0;
|
||||
}
|
||||
|
||||
@ -121,13 +121,12 @@ import static com.fastaccess.data.dao.model.Repo.UPDATED_AT;
|
||||
String starredUser;
|
||||
String reposOwner;
|
||||
|
||||
public Single<Repo> save(Repo entity) {
|
||||
return RxHelper.getSingle(App.getInstance().getDataStore()
|
||||
.delete(Repo.class)
|
||||
.where(Repo.ID.eq(entity.getId()))
|
||||
.get()
|
||||
.single()
|
||||
.flatMap(observer -> App.getInstance().getDataStore().insert(entity)));
|
||||
public Disposable save(Repo entity) {
|
||||
return Single.create(e -> {
|
||||
BlockingEntityStore<Persistable> dataSource = App.getInstance().getDataStore().toBlocking();
|
||||
dataSource.delete(Repo.class).where(Repo.ID.eq(entity.getId())).get().value();
|
||||
dataSource.insert(entity);
|
||||
}).subscribe(o -> {/**/}, Throwable::printStackTrace);
|
||||
}
|
||||
|
||||
public static Maybe<Repo> getRepo(@NonNull String name, @NonNull String login) {
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
package com.fastaccess.data.dao.timeline;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter @Setter public class AuthorModel implements Parcelable {
|
||||
private String name;
|
||||
private String email;
|
||||
private Date date;
|
||||
|
||||
public AuthorModel() {}
|
||||
|
||||
@Override public int describeContents() { return 0; }
|
||||
|
||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(this.name);
|
||||
dest.writeString(this.email);
|
||||
dest.writeLong(this.date != null ? this.date.getTime() : -1);
|
||||
}
|
||||
|
||||
private AuthorModel(Parcel in) {
|
||||
this.name = in.readString();
|
||||
this.email = in.readString();
|
||||
long tmpDate = in.readLong();
|
||||
this.date = tmpDate == -1 ? null : new Date(tmpDate);
|
||||
}
|
||||
|
||||
public static final Creator<AuthorModel> CREATOR = new Creator<AuthorModel>() {
|
||||
@Override public AuthorModel createFromParcel(Parcel source) {return new AuthorModel(source);}
|
||||
|
||||
@Override public AuthorModel[] newArray(int size) {return new AuthorModel[size];}
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,126 @@
|
||||
package com.fastaccess.data.dao.timeline;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.fastaccess.data.dao.ReactionsModel;
|
||||
import com.fastaccess.data.dao.model.Comment;
|
||||
import com.fastaccess.data.dao.model.User;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Created by Kosh on 16 Mar 2017, 7:24 PM
|
||||
*/
|
||||
@Getter @Setter public class CommentEvent implements Parcelable {
|
||||
private long id;
|
||||
private User user;
|
||||
private String url;
|
||||
private String body;
|
||||
private String bodyHtml;
|
||||
private String htmlUrl;
|
||||
private Date createdAt;
|
||||
private Date updatedAt;
|
||||
private int position;
|
||||
private int line;
|
||||
private String path;
|
||||
private String commitId;
|
||||
private String repoId;
|
||||
private String login;
|
||||
private String gistId;
|
||||
private String issueId;
|
||||
private String pullRequestId;
|
||||
private ReactionsModel reactions;
|
||||
|
||||
@Override public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Comment that = (Comment) o;
|
||||
return id == that.getId();
|
||||
|
||||
}
|
||||
|
||||
@Override public int hashCode() {
|
||||
return (int) (id ^ (id >>> 32));
|
||||
}
|
||||
|
||||
public CommentEvent() {}
|
||||
|
||||
@Override public String toString() {
|
||||
return "CommentEvent{" +
|
||||
"id=" + id +
|
||||
", user=" + user +
|
||||
", url='" + url + '\'' +
|
||||
", body='" + body + '\'' +
|
||||
", bodyHtml='" + bodyHtml + '\'' +
|
||||
", htmlUrl='" + htmlUrl + '\'' +
|
||||
", createdAt=" + createdAt +
|
||||
", updatedAt=" + updatedAt +
|
||||
", position=" + position +
|
||||
", line=" + line +
|
||||
", path='" + path + '\'' +
|
||||
", commitId='" + commitId + '\'' +
|
||||
", repoId='" + repoId + '\'' +
|
||||
", login='" + login + '\'' +
|
||||
", gistId='" + gistId + '\'' +
|
||||
", issueId='" + issueId + '\'' +
|
||||
", pullRequestId='" + pullRequestId + '\'' +
|
||||
", reactions=" + reactions +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override public int describeContents() { return 0; }
|
||||
|
||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeLong(this.id);
|
||||
dest.writeParcelable(this.user, flags);
|
||||
dest.writeString(this.url);
|
||||
dest.writeString(this.body);
|
||||
dest.writeString(this.bodyHtml);
|
||||
dest.writeString(this.htmlUrl);
|
||||
dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1);
|
||||
dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1);
|
||||
dest.writeInt(this.position);
|
||||
dest.writeInt(this.line);
|
||||
dest.writeString(this.path);
|
||||
dest.writeString(this.commitId);
|
||||
dest.writeString(this.repoId);
|
||||
dest.writeString(this.login);
|
||||
dest.writeString(this.gistId);
|
||||
dest.writeString(this.issueId);
|
||||
dest.writeString(this.pullRequestId);
|
||||
dest.writeParcelable(this.reactions, flags);
|
||||
}
|
||||
|
||||
private CommentEvent(Parcel in) {
|
||||
this.id = in.readLong();
|
||||
this.user = in.readParcelable(User.class.getClassLoader());
|
||||
this.url = in.readString();
|
||||
this.body = in.readString();
|
||||
this.bodyHtml = in.readString();
|
||||
this.htmlUrl = in.readString();
|
||||
long tmpCreatedAt = in.readLong();
|
||||
this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt);
|
||||
long tmpUpdatedAt = in.readLong();
|
||||
this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt);
|
||||
this.position = in.readInt();
|
||||
this.line = in.readInt();
|
||||
this.path = in.readString();
|
||||
this.commitId = in.readString();
|
||||
this.repoId = in.readString();
|
||||
this.login = in.readString();
|
||||
this.gistId = in.readString();
|
||||
this.issueId = in.readString();
|
||||
this.pullRequestId = in.readString();
|
||||
this.reactions = in.readParcelable(ReactionsModel.class.getClassLoader());
|
||||
}
|
||||
|
||||
public static final Creator<CommentEvent> CREATOR = new Creator<CommentEvent>() {
|
||||
@Override public CommentEvent createFromParcel(Parcel source) {return new CommentEvent(source);}
|
||||
|
||||
@Override public CommentEvent[] newArray(int size) {return new CommentEvent[size];}
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,119 @@
|
||||
package com.fastaccess.data.dao.timeline;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.fastaccess.data.dao.LabelModel;
|
||||
import com.fastaccess.data.dao.MilestoneModel;
|
||||
import com.fastaccess.data.dao.RenameModel;
|
||||
import com.fastaccess.data.dao.TeamsModel;
|
||||
import com.fastaccess.data.dao.model.Issue;
|
||||
import com.fastaccess.data.dao.model.PullRequest;
|
||||
import com.fastaccess.data.dao.model.User;
|
||||
import com.fastaccess.data.dao.types.IssueEventType;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Created by kosh on 25/07/2017.
|
||||
*/
|
||||
|
||||
@NoArgsConstructor @Getter @Setter public class GenericEvent implements Parcelable {
|
||||
|
||||
private long id;
|
||||
private String url;
|
||||
private String commitId;
|
||||
private String commitUrl;
|
||||
private String message;
|
||||
private String sha;
|
||||
private String htmlUrl;
|
||||
private Date createdAt;
|
||||
private User actor;
|
||||
private User requestedReviewer;
|
||||
private User reviewRequester;
|
||||
private User assigner;
|
||||
private User assignee;
|
||||
private User author;
|
||||
private User committer;
|
||||
private LabelModel label;
|
||||
private TeamsModel requestedTeam;
|
||||
private MilestoneModel milestone;
|
||||
private RenameModel rename;
|
||||
private SourceModel source;
|
||||
private Issue issue;
|
||||
private PullRequest pullRequest;
|
||||
private ParentsModel tree;
|
||||
private List<ParentsModel> parents;
|
||||
private IssueEventType event;
|
||||
|
||||
@Override public int describeContents() { return 0; }
|
||||
|
||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeLong(this.id);
|
||||
dest.writeString(this.url);
|
||||
dest.writeString(this.commitId);
|
||||
dest.writeString(this.commitUrl);
|
||||
dest.writeString(this.message);
|
||||
dest.writeString(this.sha);
|
||||
dest.writeString(this.htmlUrl);
|
||||
dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1);
|
||||
dest.writeParcelable(this.actor, flags);
|
||||
dest.writeParcelable(this.requestedReviewer, flags);
|
||||
dest.writeParcelable(this.reviewRequester, flags);
|
||||
dest.writeParcelable(this.assigner, flags);
|
||||
dest.writeParcelable(this.assignee, flags);
|
||||
dest.writeParcelable(this.author, flags);
|
||||
dest.writeParcelable(this.committer, flags);
|
||||
dest.writeParcelable(this.label, flags);
|
||||
dest.writeParcelable(this.requestedTeam, flags);
|
||||
dest.writeParcelable(this.milestone, flags);
|
||||
dest.writeParcelable(this.rename, flags);
|
||||
dest.writeParcelable(this.source, flags);
|
||||
dest.writeParcelable(this.issue, flags);
|
||||
dest.writeParcelable(this.pullRequest, flags);
|
||||
dest.writeParcelable(this.tree, flags);
|
||||
dest.writeTypedList(this.parents);
|
||||
dest.writeInt(this.event == null ? -1 : this.event.ordinal());
|
||||
}
|
||||
|
||||
private GenericEvent(Parcel in) {
|
||||
this.id = in.readLong();
|
||||
this.url = in.readString();
|
||||
this.commitId = in.readString();
|
||||
this.commitUrl = in.readString();
|
||||
this.message = in.readString();
|
||||
this.sha = in.readString();
|
||||
this.htmlUrl = in.readString();
|
||||
long tmpCreatedAt = in.readLong();
|
||||
this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt);
|
||||
this.actor = in.readParcelable(User.class.getClassLoader());
|
||||
this.requestedReviewer = in.readParcelable(User.class.getClassLoader());
|
||||
this.reviewRequester = in.readParcelable(User.class.getClassLoader());
|
||||
this.assigner = in.readParcelable(User.class.getClassLoader());
|
||||
this.assignee = in.readParcelable(User.class.getClassLoader());
|
||||
this.author = in.readParcelable(User.class.getClassLoader());
|
||||
this.committer = in.readParcelable(User.class.getClassLoader());
|
||||
this.label = in.readParcelable(LabelModel.class.getClassLoader());
|
||||
this.requestedTeam = in.readParcelable(TeamsModel.class.getClassLoader());
|
||||
this.milestone = in.readParcelable(MilestoneModel.class.getClassLoader());
|
||||
this.rename = in.readParcelable(RenameModel.class.getClassLoader());
|
||||
this.source = in.readParcelable(SourceModel.class.getClassLoader());
|
||||
this.issue = in.readParcelable(Issue.class.getClassLoader());
|
||||
this.pullRequest = in.readParcelable(PullRequest.class.getClassLoader());
|
||||
this.tree = in.readParcelable(ParentsModel.class.getClassLoader());
|
||||
this.parents = in.createTypedArrayList(ParentsModel.CREATOR);
|
||||
int tmpEvent = in.readInt();
|
||||
this.event = tmpEvent == -1 ? null : IssueEventType.values()[tmpEvent];
|
||||
}
|
||||
|
||||
public static final Creator<GenericEvent> CREATOR = new Creator<GenericEvent>() {
|
||||
@Override public GenericEvent createFromParcel(Parcel source) {return new GenericEvent(source);}
|
||||
|
||||
@Override public GenericEvent[] newArray(int size) {return new GenericEvent[size];}
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package com.fastaccess.data.dao.timeline;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter @Setter public class ParentsModel implements Parcelable {
|
||||
private String sha;
|
||||
private String url;
|
||||
private String htmlUrl;
|
||||
|
||||
@Override public int describeContents() { return 0; }
|
||||
|
||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(this.sha);
|
||||
dest.writeString(this.url);
|
||||
dest.writeString(this.htmlUrl);
|
||||
}
|
||||
|
||||
public ParentsModel() {}
|
||||
|
||||
private ParentsModel(Parcel in) {
|
||||
this.sha = in.readString();
|
||||
this.url = in.readString();
|
||||
this.htmlUrl = in.readString();
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<ParentsModel> CREATOR = new Parcelable.Creator<ParentsModel>() {
|
||||
@Override public ParentsModel createFromParcel(Parcel source) {return new ParentsModel(source);}
|
||||
|
||||
@Override public ParentsModel[] newArray(int size) {return new ParentsModel[size];}
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,98 @@
|
||||
package com.fastaccess.data.dao.timeline;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.fastaccess.data.dao.model.Comment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by kosh on 15/08/2017.
|
||||
*/
|
||||
|
||||
public class PullRequestCommitModel implements Parcelable {
|
||||
private String login;
|
||||
private String path;
|
||||
private int position;
|
||||
private String commitId;
|
||||
private List<Comment> comments;
|
||||
private int line;
|
||||
|
||||
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
public void setLine(int line) {
|
||||
this.line = line;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setPosition(int position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public String getCommitId() {
|
||||
return commitId;
|
||||
}
|
||||
|
||||
public void setCommitId(String commitId) {
|
||||
this.commitId = commitId;
|
||||
}
|
||||
|
||||
public List<Comment> getComments() {
|
||||
return comments;
|
||||
}
|
||||
|
||||
public void setComments(List<Comment> comments) {
|
||||
this.comments = comments;
|
||||
}
|
||||
|
||||
public PullRequestCommitModel() {}
|
||||
|
||||
public String getLogin() {
|
||||
return login;
|
||||
}
|
||||
|
||||
public void setLogin(String login) {
|
||||
this.login = login;
|
||||
}
|
||||
|
||||
@Override public int describeContents() { return 0; }
|
||||
|
||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(this.login);
|
||||
dest.writeString(this.path);
|
||||
dest.writeInt(this.position);
|
||||
dest.writeString(this.commitId);
|
||||
dest.writeTypedList(this.comments);
|
||||
dest.writeInt(this.line);
|
||||
}
|
||||
|
||||
protected PullRequestCommitModel(Parcel in) {
|
||||
this.login = in.readString();
|
||||
this.path = in.readString();
|
||||
this.position = in.readInt();
|
||||
this.commitId = in.readString();
|
||||
this.comments = in.createTypedArrayList(Comment.CREATOR);
|
||||
this.line = in.readInt();
|
||||
}
|
||||
|
||||
public static final Creator<PullRequestCommitModel> CREATOR = new Creator<PullRequestCommitModel>() {
|
||||
@Override public PullRequestCommitModel createFromParcel(Parcel source) {return new PullRequestCommitModel(source);}
|
||||
|
||||
@Override public PullRequestCommitModel[] newArray(int size) {return new PullRequestCommitModel[size];}
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,169 @@
|
||||
package com.fastaccess.data.dao.timeline;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.fastaccess.data.dao.ReactionsModel;
|
||||
import com.fastaccess.helper.Logger;
|
||||
import com.fastaccess.helper.ParseDateFormat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import pr.PullRequestTimelineQuery;
|
||||
import pr.type.PullRequestReviewState;
|
||||
|
||||
/**
|
||||
* Created by kosh on 20/08/2017.
|
||||
*/
|
||||
|
||||
public class PullRequestReviewModel {
|
||||
private PullRequestTimelineQuery.AsReviewDismissedEvent reviewDismissedEvent;
|
||||
private PullRequestTimelineQuery.AsReviewRequestedEvent reviewRequestedEvent;
|
||||
private PullRequestTimelineQuery.AsReviewRequestRemovedEvent reviewRequestRemovedEvent;
|
||||
private PullRequestTimelineQuery.Node2 node;
|
||||
private List<ReactionsModel> reaction;
|
||||
private List<PullRequestReviewModel> comments;
|
||||
private String id;
|
||||
private String url;
|
||||
private PullRequestTimelineQuery.Author2 author;
|
||||
private String bodyHTML;
|
||||
private String createdAt;
|
||||
private PullRequestReviewState state;
|
||||
|
||||
@Nullable public static PullRequestReviewModel build(@NonNull PullRequestTimelineQuery.Node node) {
|
||||
PullRequestReviewModel model = new PullRequestReviewModel();
|
||||
if (node.asReviewRequestRemovedEvent() != null) {
|
||||
model.reviewRequestRemovedEvent = node.asReviewRequestRemovedEvent();
|
||||
} else if (node.asReviewDismissedEvent() != null) {
|
||||
model.reviewDismissedEvent = node.asReviewDismissedEvent();
|
||||
} else if (node.asReviewRequestedEvent() != null) {
|
||||
model.reviewRequestedEvent = node.asReviewRequestedEvent();
|
||||
} else {
|
||||
PullRequestTimelineQuery.AsPullRequestReview pullRequestReview = node.asPullRequestReview();
|
||||
if (pullRequestReview != null) {
|
||||
model.state = pullRequestReview.state();
|
||||
model.url = pullRequestReview.url().toString();
|
||||
model.author = pullRequestReview.author();
|
||||
model.bodyHTML = pullRequestReview.bodyHTML().toString();
|
||||
model.createdAt = ParseDateFormat.getTimeAgo(pullRequestReview.createdAt().toString()).toString();
|
||||
model.id = pullRequestReview.id();
|
||||
model.url = pullRequestReview.url().toString();
|
||||
List<PullRequestTimelineQuery.Edge2> edges = pullRequestReview.comments().edges();
|
||||
if (edges != null && !edges.isEmpty()) {
|
||||
List<PullRequestReviewModel> comments = new ArrayList<>();
|
||||
for (PullRequestTimelineQuery.Edge2 edge : edges) {
|
||||
PullRequestTimelineQuery.Node2 node2 = edge.node();
|
||||
if (node2 != null) {
|
||||
PullRequestReviewModel comment = new PullRequestReviewModel();
|
||||
comment.node = node2;
|
||||
comment.reaction = ReactionsModel.getReaction(node2.reactionGroups());
|
||||
comments.add(comment);
|
||||
}
|
||||
}
|
||||
Logger.e(comments.size());
|
||||
model.comments = comments;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
public PullRequestTimelineQuery.AsReviewDismissedEvent getReviewDismissedEvent() {
|
||||
return reviewDismissedEvent;
|
||||
}
|
||||
|
||||
public void setReviewDismissedEvent(PullRequestTimelineQuery.AsReviewDismissedEvent reviewDismissedEvent) {
|
||||
this.reviewDismissedEvent = reviewDismissedEvent;
|
||||
}
|
||||
|
||||
public PullRequestTimelineQuery.AsReviewRequestedEvent getReviewRequestedEvent() {
|
||||
return reviewRequestedEvent;
|
||||
}
|
||||
|
||||
public void setReviewRequestedEvent(PullRequestTimelineQuery.AsReviewRequestedEvent reviewRequestedEvent) {
|
||||
this.reviewRequestedEvent = reviewRequestedEvent;
|
||||
}
|
||||
|
||||
public PullRequestTimelineQuery.AsReviewRequestRemovedEvent getReviewRequestRemovedEvent() {
|
||||
return reviewRequestRemovedEvent;
|
||||
}
|
||||
|
||||
public void setReviewRequestRemovedEvent(PullRequestTimelineQuery.AsReviewRequestRemovedEvent reviewRequestRemovedEvent) {
|
||||
this.reviewRequestRemovedEvent = reviewRequestRemovedEvent;
|
||||
}
|
||||
|
||||
public PullRequestTimelineQuery.Node2 getNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
public void setNode(PullRequestTimelineQuery.Node2 node) {
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
public List<ReactionsModel> getReaction() {
|
||||
return reaction;
|
||||
}
|
||||
|
||||
public void setReaction(List<ReactionsModel> reaction) {
|
||||
this.reaction = reaction;
|
||||
}
|
||||
|
||||
public List<PullRequestReviewModel> getComments() {
|
||||
return comments;
|
||||
}
|
||||
|
||||
public void setComments(List<PullRequestReviewModel> comments) {
|
||||
this.comments = comments;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public PullRequestTimelineQuery.Author2 getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(PullRequestTimelineQuery.Author2 author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public String getBodyHTML() {
|
||||
return bodyHTML;
|
||||
}
|
||||
|
||||
public void setBodyHTML(String bodyHTML) {
|
||||
this.bodyHTML = bodyHTML;
|
||||
}
|
||||
|
||||
public String getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(String createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public PullRequestReviewState getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(PullRequestReviewState state) {
|
||||
this.state = state;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
package com.fastaccess.data.dao.timeline;
|
||||
|
||||
import com.fastaccess.data.dao.ReactionsModel;
|
||||
import com.fastaccess.data.dao.model.PullRequest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import pr.PullRequestTimelineQuery;
|
||||
|
||||
/**
|
||||
* Created by kosh on 02/08/2017.
|
||||
*/
|
||||
|
||||
@Getter @Setter public class PullRequestTimelineModel {
|
||||
|
||||
public static final int HEADER = 1;
|
||||
public static final int EVENT = 2;
|
||||
public static final int COMMENT = 3;
|
||||
public static final int STATUS = 4;
|
||||
public static final int REVIEW = 5;
|
||||
public static final int COMMIT_COMMENTS = 6;
|
||||
public PullRequestTimelineQuery.Node node;
|
||||
public PullRequest pullRequest;
|
||||
public PullRequestTimelineQuery.Status status;
|
||||
public List<ReactionsModel> reactions;
|
||||
public boolean isMergeable;
|
||||
public PullRequestCommitModel commitThread;
|
||||
public PullRequestReviewModel reviewModel;
|
||||
|
||||
public PullRequestTimelineModel(PullRequest pullRequest) {
|
||||
this.pullRequest = pullRequest;
|
||||
}
|
||||
|
||||
public PullRequestTimelineModel(PullRequestTimelineQuery.Node node) {
|
||||
this.node = node;
|
||||
if (this.node.asCommitCommentThread() != null) {
|
||||
|
||||
} else {
|
||||
if (node.asPullRequestReview() != null || node.asReviewDismissedEvent() != null
|
||||
|| node.asReviewRequestedEvent() != null || node.asReviewRequestRemovedEvent() != null) {
|
||||
reviewModel = PullRequestReviewModel.build(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PullRequestTimelineModel(PullRequestTimelineQuery.Status status, boolean isMergeable) {
|
||||
this.status = status;
|
||||
this.isMergeable = isMergeable;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
if (pullRequest != null) return HEADER;
|
||||
if (node != null) {
|
||||
if (node.asAssignedEvent() != null || node.asClosedEvent() != null
|
||||
|| node.asDemilestonedEvent() != null || node.asHeadRefDeletedEvent() != null
|
||||
|| node.asLabeledEvent() != null || node.asLockedEvent() != null
|
||||
|| node.asMergedEvent() != null || node.asMilestonedEvent() != null
|
||||
|| node.asReferencedEvent() != null || node.asRenamedTitleEvent() != null
|
||||
|| node.asReopenedEvent() != null || node.asUnassignedEvent() != null
|
||||
|| node.asUnlabeledEvent() != null || node.asUnlockedEvent() != null
|
||||
|| node.asCommit() != null || node.asHeadRefRestoredEvent() != null) {
|
||||
return EVENT;
|
||||
} else if (node.asIssueComment() != null) {
|
||||
if (reactions == null) {
|
||||
//noinspection ConstantConditions
|
||||
setReactions(ReactionsModel.getReaction2(node.asIssueComment().reactionGroups()));
|
||||
}
|
||||
return COMMENT;
|
||||
} else if (reviewModel != null) {
|
||||
return REVIEW;
|
||||
} else if (commitThread != null) {
|
||||
return COMMIT_COMMENTS;
|
||||
}
|
||||
} else if (status != null) {
|
||||
return STATUS;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return String.valueOf(getType());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package com.fastaccess.data.dao.timeline;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.fastaccess.data.dao.model.Commit;
|
||||
import com.fastaccess.data.dao.model.Issue;
|
||||
import com.fastaccess.data.dao.model.PullRequest;
|
||||
import com.fastaccess.data.dao.model.Repo;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Created by kosh on 26/07/2017.
|
||||
*/
|
||||
|
||||
@Getter @Setter public class SourceModel implements Parcelable {
|
||||
|
||||
private String type;
|
||||
private Issue issue;
|
||||
private PullRequest pullRequest;
|
||||
private Commit commit;
|
||||
private Repo repository;
|
||||
|
||||
public SourceModel() {}
|
||||
|
||||
@Override public int describeContents() { return 0; }
|
||||
|
||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(this.type);
|
||||
dest.writeParcelable(this.issue, flags);
|
||||
dest.writeParcelable(this.pullRequest, flags);
|
||||
dest.writeParcelable(this.commit, flags);
|
||||
dest.writeParcelable(this.repository, flags);
|
||||
}
|
||||
|
||||
private SourceModel(Parcel in) {
|
||||
this.type = in.readString();
|
||||
this.issue = in.readParcelable(Issue.class.getClassLoader());
|
||||
this.pullRequest = in.readParcelable(PullRequest.class.getClassLoader());
|
||||
this.commit = in.readParcelable(Commit.class.getClassLoader());
|
||||
this.repository = in.readParcelable(Repo.class.getClassLoader());
|
||||
}
|
||||
|
||||
public static final Creator<SourceModel> CREATOR = new Creator<SourceModel>() {
|
||||
@Override public SourceModel createFromParcel(Parcel source) {return new SourceModel(source);}
|
||||
|
||||
@Override public SourceModel[] newArray(int size) {return new SourceModel[size];}
|
||||
};
|
||||
}
|
||||
@ -1,5 +1,9 @@
|
||||
package com.fastaccess.data.dao.types;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
import com.fastaccess.R;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
@ -7,7 +11,7 @@ public enum IssueEventType {
|
||||
assigned(R.drawable.ic_profile),
|
||||
closed(R.drawable.ic_issue_closed),
|
||||
commented(R.drawable.ic_comment),
|
||||
committed(R.drawable.ic_announcement),
|
||||
committed(R.drawable.ic_push),
|
||||
demilestoned(R.drawable.ic_milestone),
|
||||
head_ref_deleted(R.drawable.ic_trash),
|
||||
head_ref_restored(R.drawable.ic_redo),
|
||||
@ -27,7 +31,13 @@ public enum IssueEventType {
|
||||
review_requested(R.drawable.ic_eye),
|
||||
review_dismissed(R.drawable.ic_eye_off),
|
||||
review_request_removed(R.drawable.ic_eye_off),
|
||||
@SerializedName("cross-referenced")crossReferenced(R.drawable.ic_format_quote);
|
||||
@SerializedName("cross-referenced")cross_referenced(R.drawable.ic_format_quote),
|
||||
@SerializedName("line-commented")line_commented(R.drawable.ic_comment),
|
||||
@SerializedName("commit-commented")commit_commented(R.drawable.ic_comment),
|
||||
reviewed(R.drawable.ic_eye),
|
||||
changes_requested(R.drawable.ic_eye),
|
||||
added_to_project(R.drawable.ic_add),
|
||||
GROUPED(R.drawable.ic_eye);
|
||||
|
||||
int iconResId;
|
||||
|
||||
@ -36,4 +46,12 @@ public enum IssueEventType {
|
||||
public int getIconResId() {
|
||||
return iconResId == 0 ? R.drawable.ic_label : iconResId;
|
||||
}
|
||||
|
||||
@Nullable public static IssueEventType getType(@NonNull String type) {
|
||||
return Stream.of(values())
|
||||
.filter(value -> value.name().toLowerCase().equalsIgnoreCase(type.toLowerCase()
|
||||
.replaceAll("-", "_")))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@ package com.fastaccess.data.dao.types;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
import com.fastaccess.R;
|
||||
|
||||
/**
|
||||
@ -35,10 +36,9 @@ public enum ReactionTypes {
|
||||
}
|
||||
|
||||
@Nullable public static ReactionTypes get(@IdRes int vId) {
|
||||
for (ReactionTypes type : ReactionTypes.values()) {
|
||||
if (type.vId == vId) return type;
|
||||
}
|
||||
|
||||
return null;
|
||||
return Stream.of(values())
|
||||
.filter(value -> value.getvId() == vId)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
package com.fastaccess.data.dao.types;
|
||||
|
||||
import android.support.annotation.DrawableRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.StringRes;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
import com.fastaccess.R;
|
||||
|
||||
/**
|
||||
@ -11,7 +14,7 @@ import com.fastaccess.R;
|
||||
|
||||
public enum ReviewStateType {
|
||||
COMMENTED(R.string.reviewed, R.drawable.ic_eye),
|
||||
CHANGES_REQUESTED(R.string.reviewed, R.drawable.ic_eye),
|
||||
CHANGES_REQUESTED(R.string.request_changes, R.drawable.ic_clear),
|
||||
REQUEST_CHANGES(R.string.reviewed, R.drawable.ic_eye),
|
||||
DISMISSED(R.string.dismissed_review, R.drawable.ic_clear),
|
||||
APPROVED(R.string.approved_these_changes, R.drawable.ic_done),
|
||||
@ -32,4 +35,11 @@ public enum ReviewStateType {
|
||||
@DrawableRes public int getDrawableRes() {
|
||||
return drawableRes > 0 ? drawableRes : R.drawable.ic_eye;
|
||||
}
|
||||
|
||||
@Nullable public static ReviewStateType getType(@NonNull String state) {
|
||||
return Stream.of(values())
|
||||
.filter(value -> value.name().toLowerCase().equalsIgnoreCase(state.toLowerCase()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
package com.fastaccess.data.dao.types;
|
||||
|
||||
import android.support.annotation.DrawableRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
import com.fastaccess.R;
|
||||
|
||||
/**
|
||||
@ -23,4 +26,11 @@ public enum StatusStateType {
|
||||
@DrawableRes public int getDrawableRes() {
|
||||
return drawableRes;
|
||||
}
|
||||
|
||||
@NonNull public static StatusStateType getState(@Nullable String status) {
|
||||
return Stream.of(values())
|
||||
.filter(value -> value.name().toLowerCase().equalsIgnoreCase(status))
|
||||
.findFirst()
|
||||
.orElse(pending);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import android.os.Parcelable
|
||||
/**
|
||||
* Created by Kosh on 13 Jun 2017, 8:06 PM
|
||||
*/
|
||||
data class WikiContentModel(val content: String? = null, val footer: String? = null,
|
||||
data class WikiContentModel(val content: String? = null, private val footer: String? = null,
|
||||
val sidebar: ArrayList<WikiSideBarModel>) : Parcelable {
|
||||
companion object {
|
||||
@JvmField val CREATOR: Parcelable.Creator<WikiContentModel> = object : Parcelable.Creator<WikiContentModel> {
|
||||
|
||||
@ -32,7 +32,7 @@ public interface GistService {
|
||||
|
||||
@POST("gists") Observable<Gist> createGist(@Body CreateGistModel gistBody);
|
||||
|
||||
@POST("gists/{id}") Observable<Gist> editGist(@Body CreateGistModel gistBody, @NonNull @Path("id") String id);
|
||||
@PATCH("gists/{id}") Observable<Gist> editGist(@Body CreateGistModel gistBody, @Path("id") String id);
|
||||
|
||||
@DELETE("gists/{id}") Observable<Response<Boolean>> deleteGist(@Path("id") String id);
|
||||
|
||||
|
||||
@ -7,14 +7,17 @@ import com.fastaccess.data.dao.AssigneesRequestModel;
|
||||
import com.fastaccess.data.dao.CommentRequestModel;
|
||||
import com.fastaccess.data.dao.CreateIssueModel;
|
||||
import com.fastaccess.data.dao.IssueRequestModel;
|
||||
import com.fastaccess.data.dao.IssuesPageable;
|
||||
import com.fastaccess.data.dao.LabelModel;
|
||||
import com.fastaccess.data.dao.Pageable;
|
||||
import com.fastaccess.data.dao.model.Comment;
|
||||
import com.fastaccess.data.dao.model.Issue;
|
||||
import com.fastaccess.data.dao.model.IssueEvent;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import retrofit2.Response;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.DELETE;
|
||||
@ -25,7 +28,6 @@ import retrofit2.http.POST;
|
||||
import retrofit2.http.PUT;
|
||||
import retrofit2.http.Path;
|
||||
import retrofit2.http.Query;
|
||||
import io.reactivex.Observable;
|
||||
|
||||
public interface IssueService {
|
||||
|
||||
@ -49,6 +51,12 @@ public interface IssueService {
|
||||
Observable<Pageable<IssueEvent>> getTimeline(@Path("owner") String owner, @Path("repo") String repo,
|
||||
@Path("issue_number") int issue_number);
|
||||
|
||||
@GET("repos/{owner}/{repo}/issues/{issue_number}/timeline")
|
||||
@Headers("Accept: application/vnd.github.mockingbird-preview,application/vnd.github.VERSION.full+json," +
|
||||
" application/vnd.github.squirrel-girl-preview")
|
||||
Observable<IssuesPageable<JsonObject>> getTimeline(@Path("owner") String owner, @Path("repo") String repo,
|
||||
@Path("issue_number") int issue_number, @Query("page") int page);
|
||||
|
||||
@POST("repos/{owner}/{repo}/issues")
|
||||
Observable<Issue> createIssue(@Path("owner") String owner, @Path("repo") String repo,
|
||||
@Body IssueRequestModel issue);
|
||||
|
||||
@ -39,10 +39,13 @@ public interface OrganizationService {
|
||||
|
||||
@GET("teams/{id}/repos") Observable<Pageable<Repo>> getTeamRepos(@Path("id") long id, @Query("page") int page);
|
||||
|
||||
@GET("orgs/{username}/events")
|
||||
Observable<Pageable<Event>> getReceivedEvents(@NonNull @Path("username") String userName, @Query("page") int page);
|
||||
@GET("users/{username}/events/orgs/{org}")
|
||||
Observable<Pageable<Event>> getReceivedEvents(@NonNull @Path("username") String userName,
|
||||
@NonNull @Path("org") String org, @Query("page") int page);
|
||||
|
||||
@GET("orgs/{org}/repos")
|
||||
Observable<Pageable<Repo>> getOrgRepos(@NonNull @Path("org") String org, @QueryMap(encoded = true) Map<String, String> filterParams, @Query("page") int page);
|
||||
Observable<Pageable<Repo>> getOrgRepos(@NonNull @Path("org") String org,
|
||||
@QueryMap(encoded = true) Map<String, String> filterParams,
|
||||
@Query("page") int page);
|
||||
|
||||
}
|
||||
|
||||
@ -138,6 +138,9 @@ public interface RepoService {
|
||||
@NonNull @GET("repos/{owner}/{repo}/labels?per_page=100")
|
||||
Observable<Pageable<LabelModel>> getLabels(@NonNull @Path("owner") String owner, @NonNull @Path("repo") String repo);
|
||||
|
||||
@NonNull @GET("repos/{owner}/{repo}/labels?per_page=100")
|
||||
Observable<Pageable<LabelModel>> getLabels(@NonNull @Path("owner") String owner, @NonNull @Path("repo") String repo, @Query("page") int page);
|
||||
|
||||
@NonNull @POST("repos/{owner}/{repo}/labels")
|
||||
Observable<LabelModel> addLabel(@NonNull @Path("owner") String owner, @NonNull @Path("repo") String repo, @Body LabelModel body);
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ public interface ReviewService {
|
||||
Observable<Pageable<ReviewCommentModel>> getReviewComments(@Path("owner") String owner, @Path("repo") String repo,
|
||||
@Path("number") long number, @Path("id") long reviewId);
|
||||
|
||||
@GET("repos/{owner}/{repo}/pulls/{number}/comments")
|
||||
@GET("repos/{owner}/{repo}/pulls/{number}/comments?per_page=100")
|
||||
@Headers("Accept: application/vnd.github.black-cat-preview+json, application/vnd.github.VERSION.html, "
|
||||
+ "application/vnd.github.squirrel-girl-preview")
|
||||
@NonNull
|
||||
@ -68,5 +68,5 @@ public interface ReviewService {
|
||||
@POST("repos/{owner}/{repo}/pulls/{number}/reviews")
|
||||
@Headers("Accept: application/vnd.github.black-cat-preview")
|
||||
Observable<Response<ReviewModel>> submitPrReview(@Path("owner") String owner, @Path("repo") String repo,
|
||||
@Path("number") long number, @NonNull @Body ReviewRequestModel body);
|
||||
@Path("number") long number, @NonNull @Body ReviewRequestModel body);
|
||||
}
|
||||
|
||||
@ -4,6 +4,8 @@ import android.app.NotificationManager;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
@ -73,14 +75,16 @@ public class AppHelper {
|
||||
.append("**Android Version: ").append(String.valueOf(Build.VERSION.RELEASE)).append(" (SDK: ")
|
||||
.append(String.valueOf(Build.VERSION.SDK_INT)).append(")**").append(" \n")
|
||||
.append("**Device Information:**").append(" \n")
|
||||
.append("- **" + (!model.equalsIgnoreCase(brand) ? "Manufacturer" : "Manufacturer&Brand") + ":** ").append(Build.MANUFACTURER)
|
||||
.append("- **")
|
||||
.append(!model.equalsIgnoreCase(brand) ? "Manufacturer" : "Manufacturer&Brand")
|
||||
.append(":** ")
|
||||
.append(Build.MANUFACTURER)
|
||||
.append(" \n");
|
||||
if (!(model.equalsIgnoreCase(brand) || "google".equals(Build.BRAND))) {
|
||||
builder.append("- **Brand:** ").append(brand).append(" \n");
|
||||
}
|
||||
builder.append("- **Model:** ")
|
||||
.append(model)
|
||||
.append(" \n").append("---").append("\n");
|
||||
builder.append("- **Model:** ").append(model).append(" \n")
|
||||
.append("---").append("\n\n");
|
||||
if (!Locale.getDefault().getLanguage().equals(new Locale("en").getLanguage())) {
|
||||
builder.append("<--")
|
||||
.append(App.getInstance().getString(R.string.english_please))
|
||||
@ -157,7 +161,13 @@ public class AppHelper {
|
||||
}
|
||||
|
||||
public static boolean isGoogleAvailable(@NonNull Context context) {
|
||||
int status = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context);
|
||||
return status != ConnectionResult.SERVICE_DISABLED && status == ConnectionResult.SUCCESS;
|
||||
ApplicationInfo applicationInfo = null;
|
||||
try {
|
||||
applicationInfo = context.getPackageManager().getApplicationInfo("com.google.android.gms", 0);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return applicationInfo != null && applicationInfo.enabled &&
|
||||
GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
@ -5,9 +5,15 @@ import android.support.annotation.StringDef;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import static com.fastaccess.helper.BundleConstant.ExtraTYpe.EDIT_GIST_COMMENT_EXTRA;
|
||||
import static com.fastaccess.helper.BundleConstant.ExtraTYpe.FOR_RESULT_EXTRA;
|
||||
import static com.fastaccess.helper.BundleConstant.ExtraTYpe.NEW_GIST_COMMENT_EXTRA;
|
||||
import static com.fastaccess.helper.BundleConstant.ExtraType.EDIT_COMMIT_COMMENT_EXTRA;
|
||||
import static com.fastaccess.helper.BundleConstant.ExtraType.EDIT_GIST_COMMENT_EXTRA;
|
||||
import static com.fastaccess.helper.BundleConstant.ExtraType.EDIT_ISSUE_COMMENT_EXTRA;
|
||||
import static com.fastaccess.helper.BundleConstant.ExtraType.EDIT_REVIEW_COMMENT_EXTRA;
|
||||
import static com.fastaccess.helper.BundleConstant.ExtraType.FOR_RESULT_EXTRA;
|
||||
import static com.fastaccess.helper.BundleConstant.ExtraType.NEW_COMMIT_COMMENT_EXTRA;
|
||||
import static com.fastaccess.helper.BundleConstant.ExtraType.NEW_GIST_COMMENT_EXTRA;
|
||||
import static com.fastaccess.helper.BundleConstant.ExtraType.NEW_ISSUE_COMMENT_EXTRA;
|
||||
import static com.fastaccess.helper.BundleConstant.ExtraType.NEW_REVIEW_COMMENT_EXTRA;
|
||||
|
||||
/**
|
||||
* Created by Kosh on 12 Nov 2016, 3:55 PM
|
||||
@ -35,12 +41,18 @@ public class BundleConstant {
|
||||
|
||||
|
||||
@StringDef({
|
||||
NEW_GIST_COMMENT_EXTRA,
|
||||
FOR_RESULT_EXTRA,
|
||||
EDIT_GIST_COMMENT_EXTRA,
|
||||
FOR_RESULT_EXTRA
|
||||
NEW_GIST_COMMENT_EXTRA,
|
||||
EDIT_ISSUE_COMMENT_EXTRA,
|
||||
NEW_ISSUE_COMMENT_EXTRA,
|
||||
EDIT_COMMIT_COMMENT_EXTRA,
|
||||
NEW_COMMIT_COMMENT_EXTRA,
|
||||
NEW_REVIEW_COMMENT_EXTRA,
|
||||
EDIT_REVIEW_COMMENT_EXTRA
|
||||
})
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE) public @interface ExtraTYpe {
|
||||
@Retention(RetentionPolicy.SOURCE) public @interface ExtraType {
|
||||
String FOR_RESULT_EXTRA = "for_result_extra";
|
||||
String EDIT_GIST_COMMENT_EXTRA = "edit_comment_extra";
|
||||
String NEW_GIST_COMMENT_EXTRA = "new_gist_comment_extra";
|
||||
|
||||
@ -185,7 +185,7 @@ public class Bundler {
|
||||
/**
|
||||
* Get the underlying start.
|
||||
*/
|
||||
public Bundle get() {
|
||||
private Bundle get() {
|
||||
return bundle;
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ import android.util.Log;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CustomTabsHelper {
|
||||
class CustomTabsHelper {
|
||||
private static final String TAG = "CustomTabsHelper";
|
||||
private static final String STABLE_PACKAGE = "com.android.chrome";
|
||||
private static final String BETA_PACKAGE = "com.chrome.beta";
|
||||
|
||||
@ -31,6 +31,18 @@ public class ParseDateFormat {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@NonNull public static CharSequence getTimeAgo(@Nullable String toParse) {
|
||||
try {
|
||||
Date parsedDate = getInstance().dateFormat.parse(toParse);
|
||||
long now = System.currentTimeMillis();
|
||||
return DateUtils.getRelativeTimeSpanString(parsedDate.getTime(), now, DateUtils.SECOND_IN_MILLIS);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
@NonNull public static CharSequence getTimeAgo(@Nullable Date parsedDate) {
|
||||
if (parsedDate != null) {
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
@ -3,6 +3,7 @@ package com.fastaccess.provider.emoji;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* This class represents an emoji.<br>
|
||||
@ -12,203 +13,205 @@ import java.util.List;
|
||||
* @author Vincent DURMONT [vdurmont@gmail.com]
|
||||
*/
|
||||
public class Emoji {
|
||||
private final String description;
|
||||
private final boolean supportsFitzpatrick;
|
||||
private final List<String> aliases;
|
||||
private final List<String> tags;
|
||||
private final String unicode;
|
||||
private final String htmlDec;
|
||||
private final String htmlHex;
|
||||
private final String description;
|
||||
private final boolean supportsFitzpatrick;
|
||||
private final List<String> aliases;
|
||||
private final List<String> tags;
|
||||
private String unicode;
|
||||
private String htmlDec;
|
||||
private String htmlHex;
|
||||
|
||||
/**
|
||||
* Constructor for the Emoji.
|
||||
*
|
||||
* @param description The description of the emoji
|
||||
* @param supportsFitzpatrick Whether the emoji supports Fitzpatrick modifiers
|
||||
* @param aliases the aliases for this emoji
|
||||
* @param tags the tags associated with this emoji
|
||||
* @param bytes the bytes that represent the emoji
|
||||
*/
|
||||
protected Emoji(
|
||||
String description,
|
||||
boolean supportsFitzpatrick,
|
||||
List<String> aliases,
|
||||
List<String> tags,
|
||||
byte... bytes
|
||||
) {
|
||||
this.description = description;
|
||||
this.supportsFitzpatrick = supportsFitzpatrick;
|
||||
this.aliases = Collections.unmodifiableList(aliases);
|
||||
this.tags = Collections.unmodifiableList(tags);
|
||||
/**
|
||||
* Constructor for the Emoji.
|
||||
*
|
||||
* @param description
|
||||
* The description of the emoji
|
||||
* @param supportsFitzpatrick
|
||||
* Whether the emoji supports Fitzpatrick modifiers
|
||||
* @param aliases
|
||||
* the aliases for this emoji
|
||||
* @param tags
|
||||
* the tags associated with this emoji
|
||||
* @param bytes
|
||||
* the bytes that represent the emoji
|
||||
*/
|
||||
protected Emoji(
|
||||
String description,
|
||||
boolean supportsFitzpatrick,
|
||||
List<String> aliases,
|
||||
List<String> tags,
|
||||
byte... bytes
|
||||
) {
|
||||
this.description = description;
|
||||
this.supportsFitzpatrick = supportsFitzpatrick;
|
||||
this.aliases = Collections.unmodifiableList(aliases);
|
||||
this.tags = Collections.unmodifiableList(tags);
|
||||
|
||||
int count = 0;
|
||||
try {
|
||||
this.unicode = new String(bytes, "UTF-8");
|
||||
int stringLength = getUnicode().length();
|
||||
String[] pointCodes = new String[stringLength];
|
||||
String[] pointCodesHex = new String[stringLength];
|
||||
|
||||
for (int offset = 0; offset < stringLength; ) {
|
||||
final int codePoint = getUnicode().codePointAt(offset);
|
||||
|
||||
pointCodes[count] = String.format("&#%d;", codePoint);
|
||||
pointCodesHex[count++] = String.format("&#x%x;", codePoint);
|
||||
|
||||
offset += Character.charCount(codePoint);
|
||||
}
|
||||
this.htmlDec = stringJoin(pointCodes, count);
|
||||
this.htmlHex = stringJoin(pointCodesHex, count);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
int count = 0;
|
||||
try {
|
||||
this.unicode = new String(bytes, "UTF-8");
|
||||
int stringLength = getUnicode().length();
|
||||
String[] pointCodes = new String[stringLength];
|
||||
String[] pointCodesHex = new String[stringLength];
|
||||
for (int offset = 0; offset < stringLength; ) {
|
||||
final int codePoint = getUnicode().codePointAt(offset);
|
||||
pointCodes[count] = String.format(Locale.getDefault(), "&#%d;", codePoint);
|
||||
pointCodesHex[count++] = String.format("&#x%x;", codePoint);
|
||||
offset += Character.charCount(codePoint);
|
||||
}
|
||||
this.htmlDec = stringJoin(pointCodes, count);
|
||||
this.htmlHex = stringJoin(pointCodesHex, count);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to replace String.join, since it was only introduced in java8
|
||||
* @param array the array to be concatenated
|
||||
* @return concatenated String
|
||||
*/
|
||||
private String stringJoin(String[] array, int count){
|
||||
String joined = "";
|
||||
for(int i = 0; i < count; i++)
|
||||
joined += array[i];
|
||||
return joined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description of the emoji
|
||||
*
|
||||
* @return the description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns wether the emoji supports the Fitzpatrick modifiers or not
|
||||
*
|
||||
* @return true if the emoji supports the Fitzpatrick modifiers
|
||||
*/
|
||||
public boolean supportsFitzpatrick() {
|
||||
return this.supportsFitzpatrick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the aliases of the emoji
|
||||
*
|
||||
* @return the aliases (unmodifiable)
|
||||
*/
|
||||
public List<String> getAliases() {
|
||||
return this.aliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tags of the emoji
|
||||
*
|
||||
* @return the tags (unmodifiable)
|
||||
*/
|
||||
public List<String> getTags() {
|
||||
return this.tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unicode representation of the emoji
|
||||
*
|
||||
* @return the unicode representation
|
||||
*/
|
||||
public String getUnicode() {
|
||||
return this.unicode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unicode representation of the emoji associated with the
|
||||
* provided Fitzpatrick modifier.<br>
|
||||
* If the modifier is null, then the result is similar to
|
||||
* {@link Emoji#getUnicode()}
|
||||
*
|
||||
* @param fitzpatrick the fitzpatrick modifier or null
|
||||
*
|
||||
* @return the unicode representation
|
||||
* @throws UnsupportedOperationException if the emoji doesn't support the
|
||||
* Fitzpatrick modifiers
|
||||
*/
|
||||
public String getUnicode(Fitzpatrick fitzpatrick) {
|
||||
if (!this.supportsFitzpatrick()) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Cannot get the unicode with a fitzpatrick modifier, " +
|
||||
"the emoji doesn't support fitzpatrick."
|
||||
);
|
||||
} else if (fitzpatrick == null) {
|
||||
return this.getUnicode();
|
||||
/**
|
||||
* Method to replace String.join, since it was only introduced in java8
|
||||
*
|
||||
* @param array
|
||||
* the array to be concatenated
|
||||
* @return concatenated String
|
||||
*/
|
||||
private String stringJoin(String[] array, int count) {
|
||||
String joined = "";
|
||||
for (int i = 0; i < count; i++)
|
||||
joined += array[i];
|
||||
return joined;
|
||||
}
|
||||
return this.getUnicode() + fitzpatrick.unicode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML decimal representation of the emoji
|
||||
*
|
||||
* @return the HTML decimal representation
|
||||
*/
|
||||
public String getHtmlDecimal() {
|
||||
return this.htmlDec;
|
||||
}
|
||||
/**
|
||||
* Returns the description of the emoji
|
||||
*
|
||||
* @return the description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated identical to {@link #getHtmlHexadecimal()} for
|
||||
* backwards-compatibility. Use that instead.
|
||||
*
|
||||
* @return the HTML hexadecimal representation
|
||||
*/
|
||||
public String getHtmlHexidecimal() {
|
||||
return this.getHtmlHexadecimal();
|
||||
}
|
||||
/**
|
||||
* Returns wether the emoji supports the Fitzpatrick modifiers or not
|
||||
*
|
||||
* @return true if the emoji supports the Fitzpatrick modifiers
|
||||
*/
|
||||
public boolean supportsFitzpatrick() {
|
||||
return this.supportsFitzpatrick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML hexadecimal representation of the emoji
|
||||
*
|
||||
* @return the HTML hexadecimal representation
|
||||
*/
|
||||
public String getHtmlHexadecimal() {
|
||||
return this.htmlHex;
|
||||
}
|
||||
/**
|
||||
* Returns the aliases of the emoji
|
||||
*
|
||||
* @return the aliases (unmodifiable)
|
||||
*/
|
||||
public List<String> getAliases() {
|
||||
return this.aliases;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return !(other == null || !(other instanceof Emoji)) &&
|
||||
((Emoji) other).getUnicode().equals(getUnicode());
|
||||
}
|
||||
/**
|
||||
* Returns the tags of the emoji
|
||||
*
|
||||
* @return the tags (unmodifiable)
|
||||
*/
|
||||
public List<String> getTags() {
|
||||
return this.tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return unicode.hashCode();
|
||||
}
|
||||
/**
|
||||
* Returns the unicode representation of the emoji
|
||||
*
|
||||
* @return the unicode representation
|
||||
*/
|
||||
public String getUnicode() {
|
||||
return this.unicode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String representation of the Emoji object.<br>
|
||||
* <br>
|
||||
* Example:<br>
|
||||
* <code>Emoji {
|
||||
* description='smiling face with open mouth and smiling eyes',
|
||||
* supportsFitzpatrick=false,
|
||||
* aliases=[smile],
|
||||
* tags=[happy, joy, pleased],
|
||||
* unicode='😄',
|
||||
* htmlDec='&#128516;',
|
||||
* htmlHex='&#x1f604;'
|
||||
* }</code>
|
||||
*
|
||||
* @return the string representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Emoji{" +
|
||||
"description='" + description + '\'' +
|
||||
", supportsFitzpatrick=" + supportsFitzpatrick +
|
||||
", aliases=" + aliases +
|
||||
", tags=" + tags +
|
||||
", unicode='" + unicode + '\'' +
|
||||
", htmlDec='" + htmlDec + '\'' +
|
||||
", htmlHex='" + htmlHex + '\'' +
|
||||
'}';
|
||||
}
|
||||
/**
|
||||
* Returns the unicode representation of the emoji associated with the
|
||||
* provided Fitzpatrick modifier.<br>
|
||||
* If the modifier is null, then the result is similar to
|
||||
* {@link Emoji#getUnicode()}
|
||||
*
|
||||
* @param fitzpatrick
|
||||
* the fitzpatrick modifier or null
|
||||
* @return the unicode representation
|
||||
* @throws UnsupportedOperationException
|
||||
* if the emoji doesn't support the Fitzpatrick modifiers
|
||||
*/
|
||||
public String getUnicode(Fitzpatrick fitzpatrick) {
|
||||
if (!this.supportsFitzpatrick()) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Cannot get the unicode with a fitzpatrick modifier, " +
|
||||
"the emoji doesn't support fitzpatrick."
|
||||
);
|
||||
} else if (fitzpatrick == null) {
|
||||
return this.getUnicode();
|
||||
}
|
||||
return this.getUnicode() + fitzpatrick.unicode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML decimal representation of the emoji
|
||||
*
|
||||
* @return the HTML decimal representation
|
||||
*/
|
||||
public String getHtmlDecimal() {
|
||||
return this.htmlDec;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the HTML hexadecimal representation
|
||||
* @deprecated identical to {@link #getHtmlHexadecimal()} for backwards-compatibility. Use that instead.
|
||||
*/
|
||||
public String getHtmlHexidecimal() {
|
||||
return this.getHtmlHexadecimal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML hexadecimal representation of the emoji
|
||||
*
|
||||
* @return the HTML hexadecimal representation
|
||||
*/
|
||||
public String getHtmlHexadecimal() {
|
||||
return this.htmlHex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return !(other == null || !(other instanceof Emoji)) &&
|
||||
((Emoji) other).getUnicode().equals(getUnicode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return unicode.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String representation of the Emoji object.<br>
|
||||
* <br>
|
||||
* Example:<br>
|
||||
* <code>Emoji {
|
||||
* description='smiling face with open mouth and smiling eyes',
|
||||
* supportsFitzpatrick=false,
|
||||
* aliases=[smile],
|
||||
* tags=[happy, joy, pleased],
|
||||
* unicode='😄',
|
||||
* htmlDec='&#128516;',
|
||||
* htmlHex='&#x1f604;'
|
||||
* }</code>
|
||||
*
|
||||
* @return the string representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Emoji{" +
|
||||
"description='" + description + '\'' +
|
||||
", supportsFitzpatrick=" + supportsFitzpatrick +
|
||||
", aliases=" + aliases +
|
||||
", tags=" + tags +
|
||||
", unicode='" + unicode + '\'' +
|
||||
", htmlDec='" + htmlDec + '\'' +
|
||||
", htmlHex='" + htmlHex + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,10 +16,10 @@ import java.util.List;
|
||||
*
|
||||
* @author Vincent DURMONT [vdurmont@gmail.com]
|
||||
*/
|
||||
public class EmojiLoader {
|
||||
class EmojiLoader {
|
||||
private EmojiLoader() {}
|
||||
|
||||
public static List<Emoji> loadEmojis(InputStream stream) throws IOException {
|
||||
static List<Emoji> loadEmojis(InputStream stream) throws IOException {
|
||||
try {
|
||||
JSONArray emojisJSON = new JSONArray(inputStreamToString(stream));
|
||||
List<Emoji> emojis = new ArrayList<Emoji>(emojisJSON.length());
|
||||
@ -48,7 +48,7 @@ public class EmojiLoader {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected static Emoji buildEmojiFromJSON(JSONObject json) throws Exception {
|
||||
private static Emoji buildEmojiFromJSON(JSONObject json) throws Exception {
|
||||
if (!json.has("emoji")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -87,7 +87,7 @@ public class EmojiManager {
|
||||
return EMOJI_TRIE.getEmoji(unicode);
|
||||
}
|
||||
|
||||
public static Collection<Emoji> getAll() {
|
||||
public static List<Emoji> getAll() {
|
||||
return ALL_EMOJIS;
|
||||
}
|
||||
|
||||
|
||||
@ -52,32 +52,30 @@ public class EmojiParser {
|
||||
*
|
||||
* @return the string with the emojis replaced by their alias.
|
||||
*/
|
||||
public static String parseToAliases(
|
||||
String input,
|
||||
final FitzpatrickAction fitzpatrickAction
|
||||
private static String parseToAliases(
|
||||
String input,
|
||||
final FitzpatrickAction fitzpatrickAction
|
||||
) {
|
||||
EmojiTransformer emojiTransformer = new EmojiTransformer() {
|
||||
public String transform(UnicodeCandidate unicodeCandidate) {
|
||||
switch (fitzpatrickAction) {
|
||||
default:
|
||||
case PARSE:
|
||||
if (unicodeCandidate.hasFitzpatrick()) {
|
||||
return ":" +
|
||||
unicodeCandidate.getEmoji().getAliases().get(0) +
|
||||
"|" +
|
||||
unicodeCandidate.getFitzpatrickType() +
|
||||
":";
|
||||
}
|
||||
case REMOVE:
|
||||
EmojiTransformer emojiTransformer = unicodeCandidate -> {
|
||||
switch (fitzpatrickAction) {
|
||||
default:
|
||||
case PARSE:
|
||||
if (unicodeCandidate.hasFitzpatrick()) {
|
||||
return ":" +
|
||||
unicodeCandidate.getEmoji().getAliases().get(0) +
|
||||
":";
|
||||
case IGNORE:
|
||||
return ":" +
|
||||
unicodeCandidate.getEmoji().getAliases().get(0) +
|
||||
":" +
|
||||
unicodeCandidate.getFitzpatrickUnicode();
|
||||
}
|
||||
unicodeCandidate.getEmoji().getAliases().get(0) +
|
||||
"|" +
|
||||
unicodeCandidate.getFitzpatrickType() +
|
||||
":";
|
||||
}
|
||||
case REMOVE:
|
||||
return ":" +
|
||||
unicodeCandidate.getEmoji().getAliases().get(0) +
|
||||
":";
|
||||
case IGNORE:
|
||||
return ":" +
|
||||
unicodeCandidate.getEmoji().getAliases().get(0) +
|
||||
":" +
|
||||
unicodeCandidate.getFitzpatrickUnicode();
|
||||
}
|
||||
};
|
||||
|
||||
@ -132,7 +130,7 @@ public class EmojiParser {
|
||||
return result;
|
||||
}
|
||||
|
||||
protected static List<AliasCandidate> getAliasCandidates(String input) {
|
||||
private static List<AliasCandidate> getAliasCandidates(String input) {
|
||||
List<AliasCandidate> candidates = new ArrayList<AliasCandidate>();
|
||||
|
||||
Matcher matcher = ALIAS_CANDIDATE_PATTERN.matcher(input);
|
||||
@ -186,21 +184,19 @@ public class EmojiParser {
|
||||
* @return the string with the emojis replaced by their html decimal
|
||||
* representation.
|
||||
*/
|
||||
public static String parseToHtmlDecimal(
|
||||
String input,
|
||||
final FitzpatrickAction fitzpatrickAction
|
||||
private static String parseToHtmlDecimal(
|
||||
String input,
|
||||
final FitzpatrickAction fitzpatrickAction
|
||||
) {
|
||||
EmojiTransformer emojiTransformer = new EmojiTransformer() {
|
||||
public String transform(UnicodeCandidate unicodeCandidate) {
|
||||
switch (fitzpatrickAction) {
|
||||
default:
|
||||
case PARSE:
|
||||
case REMOVE:
|
||||
return unicodeCandidate.getEmoji().getHtmlDecimal();
|
||||
case IGNORE:
|
||||
return unicodeCandidate.getEmoji().getHtmlDecimal() +
|
||||
unicodeCandidate.getFitzpatrickUnicode();
|
||||
}
|
||||
EmojiTransformer emojiTransformer = unicodeCandidate -> {
|
||||
switch (fitzpatrickAction) {
|
||||
default:
|
||||
case PARSE:
|
||||
case REMOVE:
|
||||
return unicodeCandidate.getEmoji().getHtmlDecimal();
|
||||
case IGNORE:
|
||||
return unicodeCandidate.getEmoji().getHtmlDecimal() +
|
||||
unicodeCandidate.getFitzpatrickUnicode();
|
||||
}
|
||||
};
|
||||
|
||||
@ -241,21 +237,19 @@ public class EmojiParser {
|
||||
* @return the string with the emojis replaced by their html hex
|
||||
* representation.
|
||||
*/
|
||||
public static String parseToHtmlHexadecimal(
|
||||
String input,
|
||||
final FitzpatrickAction fitzpatrickAction
|
||||
private static String parseToHtmlHexadecimal(
|
||||
String input,
|
||||
final FitzpatrickAction fitzpatrickAction
|
||||
) {
|
||||
EmojiTransformer emojiTransformer = new EmojiTransformer() {
|
||||
public String transform(UnicodeCandidate unicodeCandidate) {
|
||||
switch (fitzpatrickAction) {
|
||||
default:
|
||||
case PARSE:
|
||||
case REMOVE:
|
||||
return unicodeCandidate.getEmoji().getHtmlHexadecimal();
|
||||
case IGNORE:
|
||||
return unicodeCandidate.getEmoji().getHtmlHexadecimal() +
|
||||
unicodeCandidate.getFitzpatrickUnicode();
|
||||
}
|
||||
EmojiTransformer emojiTransformer = unicodeCandidate -> {
|
||||
switch (fitzpatrickAction) {
|
||||
default:
|
||||
case PARSE:
|
||||
case REMOVE:
|
||||
return unicodeCandidate.getEmoji().getHtmlHexadecimal();
|
||||
case IGNORE:
|
||||
return unicodeCandidate.getEmoji().getHtmlHexadecimal() +
|
||||
unicodeCandidate.getFitzpatrickUnicode();
|
||||
}
|
||||
};
|
||||
|
||||
@ -270,11 +264,7 @@ public class EmojiParser {
|
||||
* @return the string without any emoji
|
||||
*/
|
||||
public static String removeAllEmojis(String str) {
|
||||
EmojiTransformer emojiTransformer = new EmojiTransformer() {
|
||||
public String transform(UnicodeCandidate unicodeCandidate) {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
EmojiTransformer emojiTransformer = unicodeCandidate -> "";
|
||||
|
||||
return parseFromUnicode(str, emojiTransformer);
|
||||
}
|
||||
@ -292,14 +282,12 @@ public class EmojiParser {
|
||||
String str,
|
||||
final Collection<Emoji> emojisToRemove
|
||||
) {
|
||||
EmojiTransformer emojiTransformer = new EmojiTransformer() {
|
||||
public String transform(UnicodeCandidate unicodeCandidate) {
|
||||
if (!emojisToRemove.contains(unicodeCandidate.getEmoji())) {
|
||||
return unicodeCandidate.getEmoji().getUnicode() +
|
||||
unicodeCandidate.getFitzpatrickUnicode();
|
||||
}
|
||||
return "";
|
||||
EmojiTransformer emojiTransformer = unicodeCandidate -> {
|
||||
if (!emojisToRemove.contains(unicodeCandidate.getEmoji())) {
|
||||
return unicodeCandidate.getEmoji().getUnicode() +
|
||||
unicodeCandidate.getFitzpatrickUnicode();
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
return parseFromUnicode(str, emojiTransformer);
|
||||
@ -317,14 +305,12 @@ public class EmojiParser {
|
||||
String str,
|
||||
final Collection<Emoji> emojisToKeep
|
||||
) {
|
||||
EmojiTransformer emojiTransformer = new EmojiTransformer() {
|
||||
public String transform(UnicodeCandidate unicodeCandidate) {
|
||||
if (emojisToKeep.contains(unicodeCandidate.getEmoji())) {
|
||||
return unicodeCandidate.getEmoji().getUnicode() +
|
||||
unicodeCandidate.getFitzpatrickUnicode();
|
||||
}
|
||||
return "";
|
||||
EmojiTransformer emojiTransformer = unicodeCandidate -> {
|
||||
if (emojisToKeep.contains(unicodeCandidate.getEmoji())) {
|
||||
return unicodeCandidate.getEmoji().getUnicode() +
|
||||
unicodeCandidate.getFitzpatrickUnicode();
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
return parseFromUnicode(str, emojiTransformer);
|
||||
@ -340,9 +326,9 @@ public class EmojiParser {
|
||||
*
|
||||
* @return input string with all emojis transformed
|
||||
*/
|
||||
public static String parseFromUnicode(
|
||||
String input,
|
||||
EmojiTransformer transformer
|
||||
private static String parseFromUnicode(
|
||||
String input,
|
||||
EmojiTransformer transformer
|
||||
) {
|
||||
int prev = 0;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@ -378,7 +364,7 @@ public class EmojiParser {
|
||||
* @param input String to find all unicode emojis in
|
||||
* @return List of UnicodeCandidates for each unicode emote in text
|
||||
*/
|
||||
protected static List<UnicodeCandidate> getUnicodeCandidates(String input) {
|
||||
private static List<UnicodeCandidate> getUnicodeCandidates(String input) {
|
||||
char[] inputCharArray = input.toCharArray();
|
||||
List<UnicodeCandidate> candidates = new ArrayList<UnicodeCandidate>();
|
||||
for (int i = 0; i < input.length(); i++) {
|
||||
@ -417,7 +403,7 @@ public class EmojiParser {
|
||||
* @return the end index of the unicode emoji starting at startPos. -1 if not
|
||||
* found
|
||||
*/
|
||||
protected static int getEmojiEndPos(char[] text, int startPos) {
|
||||
private static int getEmojiEndPos(char[] text, int startPos) {
|
||||
int best = -1;
|
||||
for (int j = startPos + 1; j <= text.length; j++) {
|
||||
EmojiTrie.Matches status = EmojiManager.isEmoji(Arrays.copyOfRange(
|
||||
@ -482,7 +468,7 @@ public class EmojiParser {
|
||||
}
|
||||
|
||||
|
||||
protected static class AliasCandidate {
|
||||
static class AliasCandidate {
|
||||
public final String fullString;
|
||||
public final String alias;
|
||||
public final Fitzpatrick fitzpatrick;
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
package com.fastaccess.provider.fabric;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Created by kosh on 14/08/2017.
|
||||
*/
|
||||
|
||||
public class FabricProvider {
|
||||
|
||||
public static void initFabric(@NonNull Context context) {}//DO NOTHING IN DEBUG
|
||||
|
||||
public static void logPurchase(@NonNull String productKey) {}//DO NOTHING IN DEBUG
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package com.fastaccess.provider.markdown
|
||||
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Created by kosh on 11/08/2017.
|
||||
*/
|
||||
class CachedComments private constructor() {
|
||||
|
||||
val map = WeakHashMap<String, CharSequence>()
|
||||
|
||||
fun put(repo: String?, login: String?, number: Any?, comment: CharSequence) {
|
||||
map.put("$repo/$login/$number", comment)
|
||||
}
|
||||
|
||||
fun get(repo: String?, login: String?, number: Any?): CharSequence? {
|
||||
return map["$repo/$login/$number"]
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
map.clear()
|
||||
}
|
||||
|
||||
private object Holder {
|
||||
val INSTANCE = CachedComments()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val instance: CachedComments by lazy { Holder.INSTANCE }
|
||||
}
|
||||
}
|
||||
@ -3,18 +3,31 @@ package com.fastaccess.provider.markdown;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.Html;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.webkit.MimeTypeMap;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.annimon.stream.IntStream;
|
||||
import com.fastaccess.helper.InputHelper;
|
||||
import com.fastaccess.helper.Logger;
|
||||
import com.fastaccess.provider.markdown.extension.emoji.EmojiExtension;
|
||||
import com.fastaccess.provider.markdown.extension.mention.MentionExtension;
|
||||
import com.fastaccess.provider.timeline.HtmlHelper;
|
||||
|
||||
import org.commonmark.Extension;
|
||||
import org.commonmark.ext.autolink.AutolinkExtension;
|
||||
import org.commonmark.ext.front.matter.YamlFrontMatterExtension;
|
||||
import org.commonmark.ext.gfm.strikethrough.StrikethroughExtension;
|
||||
import org.commonmark.ext.gfm.tables.TablesExtension;
|
||||
import org.commonmark.ext.ins.InsExtension;
|
||||
import org.commonmark.node.Node;
|
||||
import org.commonmark.parser.Parser;
|
||||
import org.commonmark.renderer.html.HtmlRenderer;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Kosh on 24 Nov 2016, 7:43 PM
|
||||
*/
|
||||
@ -35,12 +48,42 @@ public class MarkDownProvider {
|
||||
|
||||
public static void setMdText(@NonNull TextView textView, String markdown) {
|
||||
if (!InputHelper.isEmpty(markdown)) {
|
||||
Parser parser = Parser.builder().build();
|
||||
Node node = parser.parse(markdown);
|
||||
HtmlHelper.htmlIntoTextView(textView, HtmlRenderer.builder().build().render(node));
|
||||
int width = textView.getMeasuredWidth();
|
||||
if (width > 0) {
|
||||
render(textView, markdown, width);
|
||||
} else {
|
||||
textView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override public void onGlobalLayout() {
|
||||
textView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
render(textView, markdown, textView.getMeasuredWidth());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static void render(@NonNull TextView textView, String markdown, int width) {
|
||||
List<Extension> extensions = Arrays.asList(
|
||||
StrikethroughExtension.create(),
|
||||
AutolinkExtension.create(),
|
||||
TablesExtension.create(),
|
||||
InsExtension.create(),
|
||||
EmojiExtension.create(),
|
||||
MentionExtension.create(),
|
||||
YamlFrontMatterExtension.create());
|
||||
Parser parser = Parser.builder()
|
||||
.extensions(extensions)
|
||||
.build();
|
||||
Node node = parser.parse(markdown);
|
||||
String rendered = HtmlRenderer
|
||||
.builder()
|
||||
.extensions(extensions)
|
||||
.build()
|
||||
.render(node);
|
||||
Logger.e(rendered);
|
||||
HtmlHelper.htmlIntoTextView(textView, rendered, (width - (textView.getPaddingStart() + textView.getPaddingEnd())));
|
||||
}
|
||||
|
||||
public static void stripMdText(@NonNull TextView textView, String markdown) {
|
||||
if (!InputHelper.isEmpty(markdown)) {
|
||||
Parser parser = Parser.builder().build();
|
||||
@ -49,7 +92,7 @@ public class MarkDownProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private static String stripHtml(String html) {
|
||||
public static String stripHtml(String html) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
|
||||
return Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY).toString();
|
||||
} else {
|
||||
@ -125,7 +168,7 @@ public class MarkDownProvider {
|
||||
int selectionStart = editText.getSelectionStart();
|
||||
int selectionEnd = editText.getSelectionEnd();
|
||||
String substring = source.substring(selectionStart, selectionEnd);
|
||||
String result = "__" + substring + "__ ";
|
||||
String result = "**" + substring + "** ";
|
||||
editText.getText().replace(selectionStart, selectionEnd, result);
|
||||
editText.setSelection(result.length() + selectionStart - 3);
|
||||
|
||||
@ -151,6 +194,17 @@ public class MarkDownProvider {
|
||||
}
|
||||
}
|
||||
|
||||
public static void addInlinleCode(@NonNull EditText editText) {
|
||||
String source = editText.getText().toString();
|
||||
int selectionStart = editText.getSelectionStart();
|
||||
int selectionEnd = editText.getSelectionEnd();
|
||||
String substring = source.substring(selectionStart, selectionEnd);
|
||||
String result = "`" + substring + "` ";
|
||||
editText.getText().replace(selectionStart, selectionEnd, result);
|
||||
editText.setSelection(result.length() + selectionStart - 2);
|
||||
|
||||
}
|
||||
|
||||
public static void addStrikeThrough(@NonNull EditText editText) {
|
||||
String source = editText.getText().toString();
|
||||
int selectionStart = editText.getSelectionStart();
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
package com.fastaccess.provider.markdown.extension.emoji;
|
||||
|
||||
import org.commonmark.node.CustomNode;
|
||||
import org.commonmark.node.Delimited;
|
||||
|
||||
/**
|
||||
* Created by kosh on 20/08/2017.
|
||||
*/
|
||||
|
||||
public class Emoji extends CustomNode implements Delimited {
|
||||
|
||||
private static final String DELIMITER = ":";
|
||||
|
||||
@Override public String getOpeningDelimiter() {
|
||||
return DELIMITER;
|
||||
}
|
||||
|
||||
@Override public String getClosingDelimiter() {
|
||||
return DELIMITER;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.fastaccess.provider.markdown.extension.emoji;
|
||||
|
||||
import com.fastaccess.provider.markdown.extension.emoji.internal.EmojiDelimiterProcessor;
|
||||
import com.fastaccess.provider.markdown.extension.emoji.internal.EmojiNodeRenderer;
|
||||
|
||||
import org.commonmark.Extension;
|
||||
import org.commonmark.parser.Parser;
|
||||
import org.commonmark.renderer.html.HtmlRenderer;
|
||||
|
||||
/**
|
||||
* Created by kosh on 20/08/2017.
|
||||
*/
|
||||
|
||||
public class EmojiExtension implements Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension {
|
||||
private EmojiExtension() {}
|
||||
|
||||
public static Extension create() {
|
||||
return new EmojiExtension();
|
||||
}
|
||||
|
||||
@Override public void extend(Parser.Builder parserBuilder) {
|
||||
parserBuilder.customDelimiterProcessor(new EmojiDelimiterProcessor());
|
||||
}
|
||||
|
||||
@Override public void extend(HtmlRenderer.Builder rendererBuilder) {
|
||||
rendererBuilder.nodeRendererFactory(EmojiNodeRenderer::new);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package com.fastaccess.provider.markdown.extension.emoji.internal;
|
||||
|
||||
import com.fastaccess.provider.markdown.extension.emoji.Emoji;
|
||||
|
||||
import org.commonmark.node.Node;
|
||||
import org.commonmark.node.Text;
|
||||
import org.commonmark.parser.delimiter.DelimiterProcessor;
|
||||
import org.commonmark.parser.delimiter.DelimiterRun;
|
||||
|
||||
public class EmojiDelimiterProcessor implements DelimiterProcessor {
|
||||
|
||||
@Override public char getOpeningCharacter() {
|
||||
return ':';
|
||||
}
|
||||
|
||||
@Override public char getClosingCharacter() {
|
||||
return ':';
|
||||
}
|
||||
|
||||
@Override public int getMinLength() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override public int getDelimiterUse(DelimiterRun opener, DelimiterRun closer) {
|
||||
if (opener.length() >= 1 && closer.length() >= 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void process(Text opener, Text closer, int delimiterCount) {
|
||||
Node emoji = new Emoji();
|
||||
Node tmp = opener.getNext();
|
||||
while (tmp != null && tmp != closer) {
|
||||
Node next = tmp.getNext();
|
||||
emoji.appendChild(tmp);
|
||||
tmp = next;
|
||||
}
|
||||
opener.insertAfter(emoji);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package com.fastaccess.provider.markdown.extension.emoji.internal;
|
||||
|
||||
import org.commonmark.node.Node;
|
||||
import org.commonmark.renderer.NodeRenderer;
|
||||
import org.commonmark.renderer.html.HtmlNodeRendererContext;
|
||||
import org.commonmark.renderer.html.HtmlWriter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class EmojiNodeRenderer implements NodeRenderer {
|
||||
|
||||
private final HtmlNodeRendererContext context;
|
||||
private final HtmlWriter html;
|
||||
|
||||
public EmojiNodeRenderer(HtmlNodeRendererContext context) {
|
||||
this.context = context;
|
||||
this.html = context.getWriter();
|
||||
}
|
||||
|
||||
@Override public Set<Class<? extends Node>> getNodeTypes() {
|
||||
return Collections.singleton(com.fastaccess.provider.markdown.extension.emoji.Emoji.class);
|
||||
}
|
||||
|
||||
@Override public void render(Node node) {
|
||||
Map<String, String> attributes = context.extendAttributes(node, "emoji", Collections.emptyMap());
|
||||
html.tag("emoji", attributes);
|
||||
renderChildren(node);
|
||||
html.tag("/emoji");
|
||||
}
|
||||
|
||||
private void renderChildren(Node parent) {
|
||||
Node node = parent.getFirstChild();
|
||||
while (node != null) {
|
||||
Node next = node.getNext();
|
||||
context.render(node);
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.fastaccess.provider.markdown.extension.mention;
|
||||
|
||||
import org.commonmark.node.CustomNode;
|
||||
import org.commonmark.node.Delimited;
|
||||
|
||||
/**
|
||||
* Created by kosh on 20/08/2017.
|
||||
*/
|
||||
|
||||
public class Mention extends CustomNode implements Delimited {
|
||||
|
||||
private static final String DELIMITER = "@";
|
||||
|
||||
@Override public String getOpeningDelimiter() {
|
||||
return DELIMITER;
|
||||
}
|
||||
|
||||
@Override public String getClosingDelimiter() {
|
||||
return " ";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.fastaccess.provider.markdown.extension.mention;
|
||||
|
||||
import com.fastaccess.provider.markdown.extension.mention.internal.MentionDelimiterProcessor;
|
||||
import com.fastaccess.provider.markdown.extension.mention.internal.MentionNodeRenderer;
|
||||
|
||||
import org.commonmark.Extension;
|
||||
import org.commonmark.parser.Parser;
|
||||
import org.commonmark.renderer.html.HtmlRenderer;
|
||||
|
||||
/**
|
||||
* Created by kosh on 20/08/2017.
|
||||
*/
|
||||
|
||||
public class MentionExtension implements Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension {
|
||||
private MentionExtension() {}
|
||||
|
||||
public static Extension create() {
|
||||
return new MentionExtension();
|
||||
}
|
||||
|
||||
@Override public void extend(Parser.Builder parserBuilder) {
|
||||
parserBuilder.customDelimiterProcessor(new MentionDelimiterProcessor());
|
||||
}
|
||||
|
||||
@Override public void extend(HtmlRenderer.Builder rendererBuilder) {
|
||||
rendererBuilder.nodeRendererFactory(MentionNodeRenderer::new);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package com.fastaccess.provider.markdown.extension.mention.internal;
|
||||
|
||||
import com.fastaccess.provider.markdown.extension.mention.Mention;
|
||||
|
||||
import org.commonmark.node.Node;
|
||||
import org.commonmark.node.Text;
|
||||
import org.commonmark.parser.delimiter.DelimiterProcessor;
|
||||
import org.commonmark.parser.delimiter.DelimiterRun;
|
||||
|
||||
public class MentionDelimiterProcessor implements DelimiterProcessor {
|
||||
|
||||
@Override public char getOpeningCharacter() {
|
||||
return '@';
|
||||
}
|
||||
|
||||
@Override public char getClosingCharacter() {
|
||||
return ' ';
|
||||
}
|
||||
|
||||
@Override public int getMinLength() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override public int getDelimiterUse(DelimiterRun opener, DelimiterRun closer) {
|
||||
if (opener.length() >= 1 && closer.length() >= 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void process(Text opener, Text closer, int delimiterCount) {
|
||||
Node mention = new Mention();
|
||||
Node tmp = opener.getNext();
|
||||
while (tmp != null && tmp != closer) {
|
||||
Node next = tmp.getNext();
|
||||
mention.appendChild(tmp);
|
||||
tmp = next;
|
||||
}
|
||||
opener.insertAfter(mention);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.fastaccess.provider.markdown.extension.mention.internal;
|
||||
|
||||
import com.fastaccess.provider.markdown.extension.mention.Mention;
|
||||
|
||||
import org.commonmark.node.Node;
|
||||
import org.commonmark.renderer.NodeRenderer;
|
||||
import org.commonmark.renderer.html.HtmlNodeRendererContext;
|
||||
import org.commonmark.renderer.html.HtmlWriter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class MentionNodeRenderer implements NodeRenderer {
|
||||
|
||||
private final HtmlNodeRendererContext context;
|
||||
private final HtmlWriter html;
|
||||
|
||||
public MentionNodeRenderer(HtmlNodeRendererContext context) {
|
||||
this.context = context;
|
||||
this.html = context.getWriter();
|
||||
}
|
||||
|
||||
@Override public Set<Class<? extends Node>> getNodeTypes() {
|
||||
return Collections.singleton(Mention.class);
|
||||
}
|
||||
|
||||
@Override public void render(Node node) {
|
||||
Map<String, String> attributes = context.extendAttributes(node, "mention", Collections.emptyMap());
|
||||
html.tag("mention", attributes);
|
||||
renderChildren(node);
|
||||
html.tag("/mention");
|
||||
}
|
||||
|
||||
private void renderChildren(Node parent) {
|
||||
Node node = parent.getFirstChild();
|
||||
while (node != null) {
|
||||
Node next = node.getNext();
|
||||
context.render(node);
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -58,10 +58,11 @@ public class RestProvider {
|
||||
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
|
||||
.excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
|
||||
.setDateFormat("yyyy-MM-dd HH:mm:ss")
|
||||
.disableHtmlEscaping()
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
|
||||
private static OkHttpClient provideOkHttpClient() {
|
||||
public static OkHttpClient provideOkHttpClient() {
|
||||
if (okHttpClient == null) {
|
||||
OkHttpClient.Builder client = new OkHttpClient.Builder();
|
||||
if (BuildConfig.DEBUG) {
|
||||
|
||||
@ -7,14 +7,24 @@ import com.fastaccess.helper.InputHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
public class PaginationInterceptor implements Interceptor {
|
||||
|
||||
@Override public Response intercept(@NonNull Chain chain) throws IOException {
|
||||
Response response = chain.proceed(chain.request());
|
||||
Request request = chain.request();
|
||||
Response response = chain.proceed(request);
|
||||
Headers headers = chain.request().headers();
|
||||
if (headers != null) {
|
||||
if ((headers.values("Accept").contains("application/vnd.github.html") ||
|
||||
headers.values("Accept").contains("application/vnd.github.VERSION.raw"))) {
|
||||
return response;//return them as they are.
|
||||
}
|
||||
}
|
||||
if (response.isSuccessful()) {
|
||||
if (response.peekBody(1).string().equals("[")) {
|
||||
String json = "{";
|
||||
|
||||
@ -29,10 +29,11 @@ public class OnLoadMore<P> extends InfiniteScroll {
|
||||
return parameter;
|
||||
}
|
||||
|
||||
@Override public void onLoadMore(int page, int totalItemsCount) {
|
||||
@Override public boolean onLoadMore(int page, int totalItemsCount) {
|
||||
if (presenter != null) {
|
||||
presenter.setPreviousTotal(totalItemsCount);
|
||||
presenter.onCallApi(page + 1, parameter);
|
||||
return presenter.onCallApi(page + 1, parameter);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -31,6 +31,7 @@ import com.fastaccess.ui.modules.repos.issues.create.CreateIssueActivity;
|
||||
import com.fastaccess.ui.modules.repos.issues.issue.details.IssuePagerActivity;
|
||||
import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.PullRequestPagerActivity;
|
||||
import com.fastaccess.ui.modules.repos.wiki.WikiActivity;
|
||||
import com.fastaccess.ui.modules.search.SearchActivity;
|
||||
import com.fastaccess.ui.modules.trending.TrendingActivity;
|
||||
import com.fastaccess.ui.modules.user.UserPagerActivity;
|
||||
|
||||
@ -338,6 +339,9 @@ public class SchemeParser {
|
||||
} else if (segments != null && !segments.isEmpty() && segments.size() > 1 && segments.get(0).equalsIgnoreCase("orgs")) {
|
||||
if ("invitation".equalsIgnoreCase(uri.getLastPathSegment())) {
|
||||
return null;
|
||||
} else if ("search".equalsIgnoreCase(uri.getLastPathSegment())) {
|
||||
String query = uri.getQueryParameter("q");
|
||||
return SearchActivity.getIntent(context, query);
|
||||
} else {
|
||||
return UserPagerActivity.createIntent(context, segments.get(1), true);
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.media.AudioManager;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
@ -91,6 +92,7 @@ public class NotificationSchedulerJobTask extends JobService {
|
||||
public static void scheduleJob(@NonNull Context context, int duration, boolean cancel) {
|
||||
if (AppHelper.isGoogleAvailable(context)) {
|
||||
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
|
||||
dispatcher.cancel(SINGLE_JOB_ID);
|
||||
if (cancel) dispatcher.cancel(JOB_ID);
|
||||
if (duration == -1) {
|
||||
dispatcher.cancel(JOB_ID);
|
||||
@ -254,7 +256,7 @@ public class NotificationSchedulerJobTask extends JobService {
|
||||
new Intent(getApplicationContext(), NotificationActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
return getNotification(thread.getSubject().getTitle(), thread.getRepository().getFullName())
|
||||
.setDefaults(PrefGetter.isNotificationSoundEnabled() ? NotificationCompat.DEFAULT_ALL : 0)
|
||||
.setSound(PrefGetter.getNotificationSound())
|
||||
.setSound(PrefGetter.getNotificationSound(), AudioManager.STREAM_NOTIFICATION)
|
||||
.setContentIntent(toNotificationActivity ? pendingIntent : getPendingIntent(thread.getId(), thread.getSubject().getUrl()))
|
||||
.addAction(R.drawable.ic_github, getString(R.string.open), getPendingIntent(thread.getId(), thread
|
||||
.getSubject().getUrl()))
|
||||
|
||||
@ -57,7 +57,7 @@ object ThemeEngine {
|
||||
setTaskDescription(activity)
|
||||
}
|
||||
|
||||
@StyleRes fun getTheme(themeMode: Int, themeColor: Int): Int {
|
||||
@StyleRes private fun getTheme(themeMode: Int, themeColor: Int): Int {
|
||||
Logger.e(themeMode, themeColor)
|
||||
// I wish if I could simplify this :'( too many cases for the love of god.
|
||||
when (themeMode) {
|
||||
@ -156,7 +156,7 @@ object ThemeEngine {
|
||||
return R.style.ThemeLight
|
||||
}
|
||||
|
||||
@StyleRes fun getDialogTheme(themeMode: Int, themeColor: Int): Int {
|
||||
@StyleRes private fun getDialogTheme(themeMode: Int, themeColor: Int): Int {
|
||||
when (themeMode) {
|
||||
PrefGetter.LIGHT -> when (themeColor) {
|
||||
PrefGetter.RED -> return R.style.DialogThemeLight_Red
|
||||
|
||||
@ -62,7 +62,7 @@ public class CommentsHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getEmojiByUnicode(int unicode) {
|
||||
private static String getEmojiByUnicode(int unicode) {
|
||||
return new String(Character.toChars(unicode));
|
||||
}
|
||||
|
||||
|
||||
@ -1,21 +1,20 @@
|
||||
package com.fastaccess.provider.timeline;
|
||||
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.ColorInt;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.WindowManager;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.fastaccess.App;
|
||||
import com.fastaccess.R;
|
||||
import com.fastaccess.helper.PrefGetter;
|
||||
import com.fastaccess.helper.ViewHelper;
|
||||
@ -23,6 +22,7 @@ import com.fastaccess.provider.scheme.SchemeParser;
|
||||
import com.fastaccess.provider.timeline.handler.BetterLinkMovementExtended;
|
||||
import com.fastaccess.provider.timeline.handler.DrawableHandler;
|
||||
import com.fastaccess.provider.timeline.handler.EmojiHandler;
|
||||
import com.fastaccess.provider.timeline.handler.HrHandler;
|
||||
import com.fastaccess.provider.timeline.handler.ItalicHandler;
|
||||
import com.fastaccess.provider.timeline.handler.LinkHandler;
|
||||
import com.fastaccess.provider.timeline.handler.ListsHandler;
|
||||
@ -45,9 +45,18 @@ import net.nightwhistler.htmlspanner.handlers.BoldHandler;
|
||||
|
||||
public class HtmlHelper {
|
||||
|
||||
public static void htmlIntoTextView(@NonNull TextView textView, @NonNull String html) {
|
||||
public static void htmlIntoTextView(@NonNull TextView textView, @NonNull String html, int width) {
|
||||
registerClickEvent(textView);
|
||||
textView.setText(initHtml(textView).fromHtml(format(html).toString()));
|
||||
if (textView.getMeasuredWidth() > 0) {
|
||||
textView.setText(initHtml(textView, getActualWidth(textView)).fromHtml(format(html).toString()));
|
||||
} else {
|
||||
textView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override public void onGlobalLayout() {
|
||||
textView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
textView.setText(initHtml(textView, getActualWidth(textView)).fromHtml(format(html).toString()));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerClickEvent(@NonNull TextView textView) {
|
||||
@ -82,7 +91,11 @@ public class HtmlHelper {
|
||||
});
|
||||
}
|
||||
|
||||
private static HtmlSpanner initHtml(@NonNull TextView textView) {
|
||||
private static int getActualWidth(TextView textView) {
|
||||
return textView.getMeasuredWidth() - (convertDpToPx(textView.getContext(), 16));
|
||||
}
|
||||
|
||||
private static HtmlSpanner initHtml(@NonNull TextView textView, int width) {
|
||||
@PrefGetter.ThemeType int theme = PrefGetter.getThemeType();
|
||||
@ColorInt int windowBackground = getWindowBackground(theme);
|
||||
Drawable checked = ContextCompat.getDrawable(textView.getContext(), R.drawable.ic_checkbox_small);
|
||||
@ -108,13 +121,12 @@ public class HtmlHelper {
|
||||
mySpanner.registerHandler("sub", new SubScriptHandler());
|
||||
mySpanner.registerHandler("sup", new SuperScriptHandler());
|
||||
mySpanner.registerHandler("a", new LinkHandler());
|
||||
mySpanner.registerHandler("hr", new HrHandler(windowBackground, width, false));
|
||||
mySpanner.registerHandler("emoji", new EmojiHandler());
|
||||
mySpanner.registerHandler("mention", new LinkHandler());
|
||||
TableHandler tableHandler = new TableHandler();
|
||||
tableHandler.setTextColor(ViewHelper.generateTextColor(windowBackground));
|
||||
WindowManager windowManager = (WindowManager) App.getInstance().getSystemService(Context.WINDOW_SERVICE);
|
||||
Point point = new Point();
|
||||
windowManager.getDefaultDisplay().getRealSize(point);
|
||||
tableHandler.setTableWidth((int) (point.x / 1.2));
|
||||
tableHandler.setTextSize(18.0F);
|
||||
tableHandler.setTableWidth(width);
|
||||
mySpanner.registerHandler("table", tableHandler);
|
||||
return mySpanner;
|
||||
}
|
||||
@ -144,10 +156,6 @@ public class HtmlHelper {
|
||||
|
||||
private static final String SIGNATURE_END = "</div>";
|
||||
|
||||
private static final String EMAIL_START = "<div class=\"email-fragment\">";
|
||||
|
||||
private static final String EMAIL_END = "</div>";
|
||||
|
||||
private static final String HIDDEN_REPLY_START = "<div class=\"email-hidden-reply\" style=\" display:none\">";
|
||||
|
||||
private static final String HIDDEN_REPLY_END = "</div>";
|
||||
@ -206,4 +214,9 @@ public class HtmlHelper {
|
||||
length = input.length();
|
||||
}
|
||||
}
|
||||
|
||||
private static int convertDpToPx(Context context, float dp) {
|
||||
return (int) (dp * context.getResources().getDisplayMetrics().density + 0.5f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,135 @@
|
||||
package com.fastaccess.provider.timeline
|
||||
|
||||
import com.fastaccess.data.dao.*
|
||||
import com.fastaccess.data.dao.model.Comment
|
||||
import com.fastaccess.data.dao.timeline.GenericEvent
|
||||
import com.fastaccess.data.dao.timeline.PullRequestCommitModel
|
||||
import com.fastaccess.data.dao.types.IssueEventType
|
||||
import com.fastaccess.helper.InputHelper
|
||||
import com.fastaccess.helper.Logger
|
||||
import com.fastaccess.provider.rest.RestProvider
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonObject
|
||||
import io.reactivex.Observable
|
||||
|
||||
/**
|
||||
* Created by kosh on 26/07/2017.
|
||||
*/
|
||||
|
||||
object TimelineConverter {
|
||||
|
||||
fun convert(jsonObjects: List<JsonObject>?): Observable<TimelineModel> {
|
||||
if (jsonObjects == null) return Observable.empty<TimelineModel>()
|
||||
val gson = RestProvider.gson
|
||||
return Observable.fromIterable(jsonObjects)
|
||||
.map { jsonObject ->
|
||||
val event = jsonObject.get("event").asString
|
||||
val timeline = TimelineModel()
|
||||
if (!InputHelper.isEmpty(event)) {
|
||||
val type = IssueEventType.getType(event)
|
||||
timeline.event = type
|
||||
if (type != null) {
|
||||
if (type == IssueEventType.commented) {
|
||||
timeline.comment = getComment(jsonObject, gson)
|
||||
} else {
|
||||
timeline.genericEvent = getGenericEvent(jsonObject, gson)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
timeline.genericEvent = getGenericEvent(jsonObject, gson)
|
||||
}
|
||||
timeline
|
||||
}
|
||||
.filter { filterEvents(it.event) }
|
||||
}
|
||||
|
||||
fun convert(jsonObjects: List<JsonObject>?, comments: Pageable<ReviewCommentModel>?): List<TimelineModel> {
|
||||
val list = arrayListOf<TimelineModel>()
|
||||
if (jsonObjects == null) return list
|
||||
val gson = RestProvider.gson
|
||||
Logger.e(comments?.items?.size)
|
||||
jsonObjects.onEach { jsonObject ->
|
||||
val event = jsonObject.get("event").asString
|
||||
val timeline = TimelineModel()
|
||||
if (!InputHelper.isEmpty(event)) {
|
||||
val type = IssueEventType.getType(event)
|
||||
timeline.event = type
|
||||
if (type != null) {
|
||||
if (type == IssueEventType.commented) {
|
||||
timeline.comment = getComment(jsonObject, gson)
|
||||
list.add(timeline)
|
||||
} else if (type == IssueEventType.commit_commented) {
|
||||
val commit = getCommit(jsonObject, gson)
|
||||
if (commit != null) {
|
||||
val comment = commit.comments?.firstOrNull()
|
||||
comment?.let {
|
||||
commit.path = it.path
|
||||
commit.position = it.position
|
||||
commit.line = it.line
|
||||
commit.login = it.user?.login
|
||||
}
|
||||
timeline.commit = commit
|
||||
list.add(timeline)
|
||||
}
|
||||
} else if (type == IssueEventType.reviewed || type == IssueEventType
|
||||
.changes_requested) {
|
||||
val review = getReview(jsonObject, gson)
|
||||
if (review != null) {
|
||||
timeline.review = review
|
||||
list.add(timeline)
|
||||
val reviewsList = arrayListOf<TimelineModel>()
|
||||
comments?.items?.filter { it.pullRequestReviewId == review.id }
|
||||
?.onEach {
|
||||
val grouped = GroupedReviewModel()
|
||||
grouped.diffText = it.diffHunk
|
||||
grouped.path = it.path
|
||||
grouped.position = it.position
|
||||
grouped.comments = arrayListOf(it)
|
||||
grouped.id = it.id
|
||||
val groupTimeline = TimelineModel()
|
||||
groupTimeline.event = IssueEventType.GROUPED
|
||||
groupTimeline.groupedReviewModel = grouped
|
||||
reviewsList.add(groupTimeline)
|
||||
}
|
||||
comments?.items?.filter { it.pullRequestReviewId != review.id }?.onEach {
|
||||
reviewsList.onEach { reviews ->
|
||||
if (it.path == reviews.groupedReviewModel.path && it.position == reviews.groupedReviewModel.position) {
|
||||
reviews.groupedReviewModel.comments.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
list.addAll(reviewsList)
|
||||
}
|
||||
} else {
|
||||
timeline.genericEvent = getGenericEvent(jsonObject, gson)
|
||||
list.add(timeline)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
timeline.genericEvent = getGenericEvent(jsonObject, gson)
|
||||
list.add(timeline)
|
||||
}
|
||||
}
|
||||
return list.filter({filterEvents(it.event)})
|
||||
}
|
||||
|
||||
private fun getCommit(jsonObject: JsonObject, gson: Gson): PullRequestCommitModel? {
|
||||
return gson.fromJson(jsonObject, PullRequestCommitModel::class.java)
|
||||
}
|
||||
|
||||
private fun getGenericEvent(jsonObject: JsonObject, gson: Gson): GenericEvent {
|
||||
return gson.fromJson(jsonObject, GenericEvent::class.java)
|
||||
}
|
||||
|
||||
private fun getComment(jsonObject: JsonObject, gson: Gson): Comment {
|
||||
return gson.fromJson(jsonObject, Comment::class.java)
|
||||
}
|
||||
|
||||
private fun filterEvents(type: IssueEventType?): Boolean {
|
||||
return type != null && type != IssueEventType.subscribed && type != IssueEventType.unsubscribed && type != IssueEventType.mentioned
|
||||
}
|
||||
|
||||
private fun getReview(jsonObject: JsonObject, gson: Gson): ReviewModel? {
|
||||
return gson.fromJson(jsonObject, ReviewModel::class.java)
|
||||
}
|
||||
}
|
||||
@ -8,14 +8,14 @@ import android.text.style.BackgroundColorSpan;
|
||||
|
||||
import com.fastaccess.R;
|
||||
import com.fastaccess.data.dao.LabelModel;
|
||||
import com.fastaccess.data.dao.model.IssueEvent;
|
||||
import com.fastaccess.data.dao.model.User;
|
||||
import com.fastaccess.data.dao.timeline.GenericEvent;
|
||||
import com.fastaccess.data.dao.timeline.SourceModel;
|
||||
import com.fastaccess.data.dao.types.IssueEventType;
|
||||
import com.fastaccess.helper.InputHelper;
|
||||
import com.fastaccess.helper.ParseDateFormat;
|
||||
import com.fastaccess.helper.PrefGetter;
|
||||
import com.fastaccess.helper.ViewHelper;
|
||||
import com.fastaccess.ui.widgets.LabelSpan;
|
||||
import com.fastaccess.ui.widgets.SpannableBuilder;
|
||||
import com.zzhoujay.markdown.style.CodeSpan;
|
||||
|
||||
@ -27,39 +27,45 @@ import java.util.Date;
|
||||
|
||||
public class TimelineProvider {
|
||||
|
||||
@NonNull public static SpannableBuilder getStyledEvents(@NonNull IssueEvent issueEventModel, @NonNull Context context, boolean isMerged) {
|
||||
@NonNull public static SpannableBuilder getStyledEvents(@NonNull GenericEvent issueEventModel,
|
||||
@NonNull Context context, boolean isMerged) {
|
||||
IssueEventType event = issueEventModel.getEvent();
|
||||
SpannableBuilder spannableBuilder = SpannableBuilder.builder();
|
||||
Date date = issueEventModel.getCreatedAt() != null
|
||||
? issueEventModel.getCreatedAt()
|
||||
: issueEventModel.getAuthor() != null
|
||||
? issueEventModel.getAuthor().getDate() : null;
|
||||
if (event != null) {
|
||||
String to = context.getString(R.string.to);
|
||||
String from = context.getString(R.string.from);
|
||||
String thisString = context.getString(R.string.this_value);
|
||||
String in = context.getString(R.string.in_value);
|
||||
if (event == IssueEventType.labeled || event == IssueEventType.unlabeled) {
|
||||
if (issueEventModel.getAssignee() != null && issueEventModel.getAssigner() != null) {
|
||||
spannableBuilder.bold(issueEventModel.getAssigner().getLogin());
|
||||
} else if (issueEventModel.getActor() != null) {
|
||||
spannableBuilder.bold(issueEventModel.getActor().getLogin());
|
||||
}
|
||||
spannableBuilder.bold(issueEventModel.getActor().getLogin());
|
||||
spannableBuilder.append(" ").append(event.name().replaceAll("_", " "));
|
||||
LabelModel labelModel = issueEventModel.getLabel();
|
||||
int color = Color.parseColor("#" + labelModel.getColor());
|
||||
spannableBuilder.append(" ").append(" " + labelModel.getName() + " ", new CodeSpan(color, ViewHelper.generateTextColor(color), 5));
|
||||
spannableBuilder.append(" ").append(getDate(issueEventModel.getCreatedAt()));
|
||||
} else if (event == IssueEventType.committed) {
|
||||
spannableBuilder.append(issueEventModel.getMessage().replaceAll("\n", " "))
|
||||
.append(" ")
|
||||
.url(substring(issueEventModel.getSha()));
|
||||
} else {
|
||||
User user = null;
|
||||
if (issueEventModel.getAssignee() != null && issueEventModel.getAssigner() != null) {
|
||||
user = issueEventModel.getAssigner();
|
||||
} else if (issueEventModel.getActor() != null) {
|
||||
user = issueEventModel.getActor();
|
||||
} else if (issueEventModel.getAuthor() != null) {
|
||||
user = issueEventModel.getAuthor();
|
||||
}
|
||||
if (user != null) {
|
||||
spannableBuilder.bold(user.getLogin());
|
||||
}
|
||||
|
||||
if ((event == IssueEventType.review_requested || (event == IssueEventType.review_dismissed ||
|
||||
event == IssueEventType.review_request_removed)) && user != null) {
|
||||
appendReviews(issueEventModel, event, spannableBuilder, from, user);
|
||||
appendReviews(issueEventModel, event, spannableBuilder, from, issueEventModel.getReviewRequester());
|
||||
} else if (event == IssueEventType.closed || event == IssueEventType.reopened) {
|
||||
if (isMerged) {
|
||||
spannableBuilder.append(" ").append(IssueEventType.merged.name());
|
||||
@ -76,7 +82,6 @@ public class TimelineProvider {
|
||||
.append(in)
|
||||
.append(" ")
|
||||
.url(substring(issueEventModel.getCommitId()));
|
||||
|
||||
}
|
||||
} else if (event == IssueEventType.assigned || event == IssueEventType.unassigned) {
|
||||
spannableBuilder
|
||||
@ -99,15 +104,17 @@ public class TimelineProvider {
|
||||
} else if (event == IssueEventType.head_ref_deleted || event == IssueEventType.head_ref_restored) {
|
||||
spannableBuilder.append(" ").append(event.name().replaceAll("_", " "),
|
||||
new BackgroundColorSpan(HtmlHelper.getWindowBackground(PrefGetter.getThemeType())));
|
||||
} else if (event == IssueEventType.milestoned || event == IssueEventType.demilestoned) {
|
||||
spannableBuilder.append(" ")
|
||||
.append(event == IssueEventType.milestoned ? "added this to the" : "removed this from the")
|
||||
.append(" ")
|
||||
.bold(issueEventModel.getMilestone().getTitle())
|
||||
.append(" ")
|
||||
.append("milestone");
|
||||
} else {
|
||||
spannableBuilder.append(" ").append(event.name().replaceAll("_", " "));
|
||||
}
|
||||
if (event == IssueEventType.milestoned || event == IssueEventType.demilestoned) {
|
||||
spannableBuilder.append(" ")
|
||||
.append(event == IssueEventType.milestoned ? to : from)
|
||||
.append(" ")
|
||||
.bold(issueEventModel.getMilestone().getTitle());
|
||||
} else if (event == IssueEventType.renamed) {
|
||||
if (event == IssueEventType.renamed) {
|
||||
spannableBuilder
|
||||
.append(" ")
|
||||
.append(from)
|
||||
@ -123,18 +130,40 @@ public class TimelineProvider {
|
||||
.append("commit")
|
||||
.append(" ")
|
||||
.url(substring(issueEventModel.getCommitId()));
|
||||
} else if (event == IssueEventType.cross_referenced) {
|
||||
SourceModel sourceModel = issueEventModel.getSource();
|
||||
if (sourceModel != null) {
|
||||
SpannableBuilder title = SpannableBuilder.builder();
|
||||
if (sourceModel.getIssue() != null) {
|
||||
title.url("#" + sourceModel.getIssue().getNumber());
|
||||
} else if (sourceModel.getPullRequest() != null) {
|
||||
title.url("#" + sourceModel.getPullRequest().getNumber());
|
||||
} else if (sourceModel.getCommit() != null) {
|
||||
title.url(substring(sourceModel.getCommit().getSha()));
|
||||
} else if (sourceModel.getRepository() != null) {
|
||||
title.url(sourceModel.getRepository().getName());
|
||||
}
|
||||
if (!InputHelper.isEmpty(title)) {
|
||||
spannableBuilder.append(" ")
|
||||
.append(thisString)
|
||||
.append(" in ")
|
||||
.append(sourceModel.getType())
|
||||
.append(" ")
|
||||
.append(title);
|
||||
}
|
||||
}
|
||||
}
|
||||
spannableBuilder.append(" ").append(getDate(issueEventModel.getCreatedAt()));
|
||||
spannableBuilder.append(" ").append(getDate(date));
|
||||
}
|
||||
}
|
||||
return spannableBuilder;
|
||||
}
|
||||
|
||||
private static void appendReviews(@NonNull IssueEvent issueEventModel, @NonNull IssueEventType event,
|
||||
@NonNull SpannableBuilder spannableBuilder, @NonNull String from, @NonNull User user) {
|
||||
private static void appendReviews(@NonNull GenericEvent issueEventModel, @NonNull IssueEventType event,
|
||||
@NonNull SpannableBuilder spannableBuilder, @NonNull String from,
|
||||
@NonNull User user) {
|
||||
spannableBuilder.append(" ");
|
||||
User reviewer = issueEventModel.getRequestedReviewer() != null
|
||||
? issueEventModel.getRequestedReviewer() : issueEventModel.getIssue() != null ? issueEventModel.getIssue().getUser() : null;
|
||||
User reviewer = issueEventModel.getRequestedReviewer();
|
||||
if (reviewer != null && user.getLogin().equalsIgnoreCase(reviewer.getLogin())) {
|
||||
spannableBuilder
|
||||
.append(event == IssueEventType.review_requested
|
||||
@ -158,11 +187,6 @@ public class TimelineProvider {
|
||||
}
|
||||
}
|
||||
|
||||
public static void appendLabels(@NonNull LabelModel labelModel, @NonNull SpannableBuilder spannableBuilder) {
|
||||
int color = Color.parseColor("#" + labelModel.getColor());
|
||||
spannableBuilder.append(" ").append(" " + labelModel.getName() + " ", new LabelSpan(color));
|
||||
}
|
||||
|
||||
@NonNull private static CharSequence getDate(@Nullable Date date) {
|
||||
return ParseDateFormat.getTimeAgo(date);
|
||||
}
|
||||
|
||||
@ -5,10 +5,10 @@ import android.text.style.ImageSpan;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.fastaccess.helper.InputHelper;
|
||||
import com.fastaccess.helper.Logger;
|
||||
import com.fastaccess.provider.timeline.handler.drawable.DrawableGetter;
|
||||
|
||||
import net.nightwhistler.htmlspanner.TagNodeHandler;
|
||||
import net.nightwhistler.htmlspanner.spans.CenterSpan;
|
||||
|
||||
import org.htmlcleaner.TagNode;
|
||||
|
||||
@ -30,15 +30,14 @@ import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
|
||||
|
||||
@Override public void handleTagNode(TagNode node, SpannableStringBuilder builder, int start, int end) {
|
||||
String src = node.getAttributeByName("src");
|
||||
boolean isGif = "gif".equalsIgnoreCase(node.getAttributeByName("alt"));
|
||||
Logger.e(isGif);
|
||||
if (!InputHelper.isEmpty(src)) {
|
||||
builder.append("");
|
||||
if (isNull()) return;
|
||||
CenterSpan centerSpan = new CenterSpan();
|
||||
DrawableGetter imageGetter = new DrawableGetter(textView);
|
||||
builder.setSpan(centerSpan, start, builder.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
builder.setSpan(new ImageSpan(imageGetter.getDrawable(src)), start, builder.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
appendNewLine(builder);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ package com.fastaccess.provider.timeline.handler;
|
||||
|
||||
import android.text.SpannableStringBuilder;
|
||||
|
||||
import com.fastaccess.helper.InputHelper;
|
||||
import com.fastaccess.helper.Logger;
|
||||
import com.fastaccess.provider.emoji.Emoji;
|
||||
import com.fastaccess.provider.emoji.EmojiManager;
|
||||
|
||||
@ -18,11 +18,17 @@ public class EmojiHandler extends TagNodeHandler {
|
||||
|
||||
@Override public void handleTagNode(TagNode node, SpannableStringBuilder builder, int start, int end) {
|
||||
String emoji = node.getAttributeByName("alias");
|
||||
if (!InputHelper.isEmpty(emoji)) {
|
||||
if (emoji != null) {
|
||||
Emoji unicode = EmojiManager.getForAlias(emoji);
|
||||
if (unicode != null && unicode.getUnicode() != null) {
|
||||
builder.replace(start, end, unicode.getUnicode());
|
||||
}
|
||||
} else if (node.getText() != null) {
|
||||
Logger.e(node.getText());
|
||||
Emoji unicode = EmojiManager.getForAlias(node.getText().toString());
|
||||
if (unicode != null && unicode.getUnicode() != null) {
|
||||
builder.replace(start, end, unicode.getUnicode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
package com.fastaccess.provider.timeline.handler;
|
||||
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
|
||||
import net.nightwhistler.htmlspanner.TagNodeHandler;
|
||||
import net.nightwhistler.htmlspanner.spans.CenterSpan;
|
||||
|
||||
import org.htmlcleaner.TagNode;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
/**
|
||||
* Created by kosh on 30/07/2017.
|
||||
*/
|
||||
|
||||
@AllArgsConstructor public class HrHandler extends TagNodeHandler {
|
||||
|
||||
private final int color;
|
||||
private final int width;
|
||||
private final boolean isHeader;
|
||||
|
||||
@Override public void handleTagNode(TagNode tagNode, SpannableStringBuilder spannableStringBuilder, int i, int i1) {
|
||||
spannableStringBuilder.append("\n");
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder("$");
|
||||
HrSpan hrSpan = new HrSpan(color, width);
|
||||
builder.setSpan(hrSpan, 0, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
builder.setSpan(new CenterSpan(), 0, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
builder.append("\n");
|
||||
spannableStringBuilder.append(builder);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.fastaccess.provider.timeline.handler;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.style.LineHeightSpan;
|
||||
import android.text.style.ReplacementSpan;
|
||||
|
||||
public class HrSpan extends ReplacementSpan implements LineHeightSpan {
|
||||
|
||||
private final int width;
|
||||
private final int color;
|
||||
|
||||
HrSpan(int color, int width) {
|
||||
this.color = color;
|
||||
this.width = width;
|
||||
Drawable drawable = new ColorDrawable(color);
|
||||
}
|
||||
|
||||
@Override public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
|
||||
return (int) paint.measureText(text, start, end);
|
||||
}
|
||||
|
||||
@Override public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top,
|
||||
int y, int bottom, @NonNull Paint paint) {
|
||||
final int currentColor = paint.getColor();
|
||||
paint.setColor(color);
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
int height = 10;
|
||||
canvas.drawRect(new Rect(0, bottom - height, (int) x + width, bottom), paint);
|
||||
paint.setColor(currentColor);
|
||||
}
|
||||
|
||||
@Override public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int v, Paint.FontMetricsInt fm) {
|
||||
fm.top /= 3;
|
||||
fm.ascent /= 3;
|
||||
fm.bottom /= 3;
|
||||
fm.descent /= 3;
|
||||
}
|
||||
}
|
||||
@ -18,6 +18,10 @@ public class LinkHandler extends TagNodeHandler {
|
||||
|
||||
@Override public void handleTagNode(TagNode node, SpannableStringBuilder spannableStringBuilder, int start, int end) {
|
||||
String href = node.getAttributeByName("href");
|
||||
spannableStringBuilder.setSpan(new LinkSpan(href, linkColor), start, end, 33);
|
||||
if (href != null) {
|
||||
spannableStringBuilder.setSpan(new LinkSpan(href, linkColor), start, end, 33);
|
||||
} else if (node.getText() != null) {
|
||||
spannableStringBuilder.setSpan(new LinkSpan("https://github.com/" + node.getText().toString(), linkColor), start, end, 33);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ import lombok.NoArgsConstructor;
|
||||
return node.getParent() == null ? null : node.getParent().getName();
|
||||
}
|
||||
|
||||
@Override public void beforeChildren(TagNode node, SpannableStringBuilder builder) {
|
||||
@Override public void beforeChildren(TagNode node, SpannableStringBuilder builder) {
|
||||
TodoItems todoItem = null;
|
||||
if (node.getChildTags() != null && node.getChildTags().length > 0) {
|
||||
for (TagNode tagNode : node.getChildTags()) {
|
||||
|
||||
@ -19,6 +19,7 @@ import android.text.style.AlignmentSpan;
|
||||
import android.text.style.ImageSpan;
|
||||
|
||||
import net.nightwhistler.htmlspanner.TagNodeHandler;
|
||||
import net.nightwhistler.htmlspanner.spans.CenterSpan;
|
||||
|
||||
import org.htmlcleaner.TagNode;
|
||||
|
||||
@ -35,12 +36,12 @@ import java.util.List;
|
||||
*/
|
||||
public class TableHandler extends TagNodeHandler {
|
||||
|
||||
private int tableWidth = 400;
|
||||
private int tableWidth = 500;
|
||||
private Typeface typeFace = Typeface.DEFAULT;
|
||||
private float textSize = 16f;
|
||||
private float textSize = 30f;
|
||||
private int textColor = Color.BLACK;
|
||||
|
||||
private static final int PADDING = 5;
|
||||
private static final int PADDING = 20;
|
||||
|
||||
/**
|
||||
* Sets how wide the table should be.
|
||||
@ -144,7 +145,6 @@ public class TableHandler extends TagNodeHandler {
|
||||
int rowHeight = 0;
|
||||
|
||||
for (Spanned cell : row) {
|
||||
|
||||
StaticLayout layout = new StaticLayout(cell, textPaint, columnWidth
|
||||
- 2 * PADDING, Alignment.ALIGN_NORMAL, 1f, 0f, true);
|
||||
|
||||
@ -165,19 +165,14 @@ public class TableHandler extends TagNodeHandler {
|
||||
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
|
||||
drawable.getIntrinsicHeight());
|
||||
builder.setSpan(new ImageSpan(drawable), start + i, builder.length(), 33);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
We add an empty last row to work around a rendering issue where
|
||||
the last row would appear detached.
|
||||
*/
|
||||
builder.append("\uFFFC");
|
||||
Drawable drawable = new TableRowDrawable(new ArrayList<Spanned>(), table.isDrawBorder());
|
||||
Drawable drawable = new TableRowDrawable(new ArrayList<>(), table.isDrawBorder());
|
||||
drawable.setBounds(0, 0, tableWidth, 1);
|
||||
builder.setSpan(new ImageSpan(drawable), builder.length() - 1, builder.length(),
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
builder.setSpan((AlignmentSpan) () -> Alignment.ALIGN_CENTER, start, builder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
builder.setSpan(new CenterSpan(), start, builder.length(), 33);
|
||||
builder.append("\n");
|
||||
}
|
||||
|
||||
|
||||
@ -3,14 +3,12 @@ package com.fastaccess.provider.timeline.handler.drawable;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.text.Html;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bumptech.glide.GenericRequestBuilder;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.fastaccess.R;
|
||||
import com.fastaccess.helper.Logger;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashSet;
|
||||
@ -22,7 +20,7 @@ import java.util.Set;
|
||||
|
||||
public class DrawableGetter implements Html.ImageGetter, Drawable.Callback {
|
||||
private WeakReference<TextView> container;
|
||||
private final Set<GifBitmapTarget> cachedTargets;
|
||||
private final Set<GlideDrawableTarget> cachedTargets;
|
||||
|
||||
public DrawableGetter(TextView tv) {
|
||||
tv.setTag(R.id.drawable_callback, this);
|
||||
@ -30,27 +28,14 @@ public class DrawableGetter implements Html.ImageGetter, Drawable.Callback {
|
||||
this.cachedTargets = new HashSet<>();
|
||||
}
|
||||
|
||||
public void clear(@NonNull DrawableGetter drawableGetter) {
|
||||
if (drawableGetter.cachedTargets != null) {
|
||||
for (GifBitmapTarget target : drawableGetter.cachedTargets) {
|
||||
Logger.e("is clearing");
|
||||
Glide.clear(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public Drawable getDrawable(@NonNull String url) {
|
||||
final UrlDrawable urlDrawable = new UrlDrawable();
|
||||
if (container != null && container.get() != null) {
|
||||
Context context = container.get().getContext();
|
||||
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.ic_image);
|
||||
urlDrawable.setDrawable(drawable);
|
||||
container.get().setText(container.get().getText());
|
||||
container.get().invalidate();
|
||||
final GenericRequestBuilder load = Glide.with(context)
|
||||
.load(url)
|
||||
.dontAnimate();
|
||||
final GifBitmapTarget target = new GifBitmapTarget(urlDrawable, container);
|
||||
final GlideDrawableTarget target = new GlideDrawableTarget(urlDrawable, container);
|
||||
load.into(target);
|
||||
cachedTargets.add(target);
|
||||
}
|
||||
@ -66,4 +51,12 @@ public class DrawableGetter implements Html.ImageGetter, Drawable.Callback {
|
||||
@Override public void scheduleDrawable(@NonNull Drawable drawable, @NonNull Runnable runnable, long l) {}
|
||||
|
||||
@Override public void unscheduleDrawable(@NonNull Drawable drawable, @NonNull Runnable runnable) {}
|
||||
|
||||
public void clear(@NonNull DrawableGetter drawableGetter) {
|
||||
if (drawableGetter.cachedTargets != null) {
|
||||
for (GlideDrawableTarget target : drawableGetter.cachedTargets) {
|
||||
Glide.clear(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,11 +11,11 @@ import com.fastaccess.R;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
class GifBitmapTarget extends SimpleTarget<GlideDrawable> {
|
||||
class GlideDrawableTarget extends SimpleTarget<GlideDrawable> {
|
||||
private final UrlDrawable urlDrawable;
|
||||
private final WeakReference<TextView> container;
|
||||
|
||||
GifBitmapTarget(UrlDrawable urlDrawable, WeakReference<TextView> container) {
|
||||
GlideDrawableTarget(UrlDrawable urlDrawable, WeakReference<TextView> container) {
|
||||
this.urlDrawable = urlDrawable;
|
||||
this.container = container;
|
||||
}
|
||||
@ -34,7 +34,7 @@ class GifBitmapTarget extends SimpleTarget<GlideDrawable> {
|
||||
width = (float) resource.getIntrinsicWidth() * multiplier;
|
||||
height = (float) resource.getIntrinsicHeight() * multiplier;
|
||||
}
|
||||
Rect rect = new Rect(0, 0, Math.round(width), Math.round(height));
|
||||
Rect rect = new Rect(0, 0, (int) Math.round(width / 1.3), (int) Math.round(height / 1.3));
|
||||
resource.setBounds(rect);
|
||||
urlDrawable.setBounds(rect);
|
||||
urlDrawable.setDrawable(resource);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user