Merge pull request #7 from k0shk0sh/master

merging commits
This commit is contained in:
Felix Naumann 2017-06-07 17:19:22 +02:00 committed by GitHub
commit 3fad2de2b7
181 changed files with 4317 additions and 4039 deletions

View File

@ -34,6 +34,7 @@ grab **FastHub** from [Here](https://github.com/thermatk/FastHub-Libre) maintain
- Notifications overview and "Mark all as read"
- Search users/orgs, repos, issues/prs & code.
- Pinned Repos
- Trending
- **Repositories**
- Search Repos
- Browse and search Repos
@ -81,6 +82,7 @@ Ads are no longer available until further notice
# Specs / Open-source libraries:
- Minimum **SDK 21**, _but AppCompat is used all the way ;-)_
- **Kotlin** all new modules starting from 2.5.3 will be written in **#Kotlin**.
- **MVP**-architecture: [**ThirtyInch**](https://github.com/grandcentrix/ThirtyInch) because its ThirtyInch.
- [**RxJava2**](https://github.com/ReactiveX/RxJava) & [**RxAndroid**](https://github.com/ReactiveX/RxAndroid) for Retrofit & background threads
- [**Retrofit**](https://github.com/square/retrofit) for constructing the REST API
@ -95,7 +97,7 @@ Ads are no longer available until further notice
- [**Toasty**](https://github.com/GrenderG/Toasty) for displaying error/success messages
- [**ShapedImageView**](https://github.com/gavinliu/ShapedImageView) for round avatars
- [**MaterialTapTargetPrompt**](https://github.com/sjwall/MaterialTapTargetPrompt) for displaying tips throughout the app
- **Firebase** crash reporting
- **Fabric** analytics & crash reporting.
- **Android Support Libraries**, the almighty ;-)
# Contribution

View File

@ -28,8 +28,8 @@ android {
applicationId "com.fastaccess.github"
minSdkVersion 21
targetSdkVersion 26
versionCode 253
versionName "2.5.3"
versionCode 301
versionName "3.0.1"
signingConfig signingConfigs.signing
buildConfigString "GITHUB_CLIENT_ID", (buildProperties.secrets['github_client_id'] | buildProperties.notThere['github_client_id']).string
buildConfigString "GITHUB_SECRET", (buildProperties.secrets['github_secret'] | buildProperties.notThere['github_secret']).string
@ -49,7 +49,7 @@ android {
buildTypes {
release {
minifyEnabled true
shrinkResources true
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
@ -92,6 +92,10 @@ android {
compileOptions.incremental = false
}
kapt {
generateStubs = true
}
repositories {
maven { url "https://clojars.org/repo/" }
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
@ -101,8 +105,6 @@ repositories {
mavenCentral()
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile "com.android.support:appcompat-v7:${supportVersion}"
@ -145,8 +147,6 @@ dependencies {
}
compile "com.github.miguelbcr:RxBillingService:0.0.3"
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
compile "com.github.florent37:retrojsoup:${retrojsoupVersion}"
compile "com.github.florent37:rxjsoup:${retrojsoupVersion}"
compile 'org.jsoup:jsoup:1.10.2'
compile "com.evernote:android-state:${state_version}"
provided "org.projectlombok:lombok:${lombokVersion}"
@ -156,7 +156,6 @@ dependencies {
kapt "com.jakewharton:butterknife-compiler:${butterKnifeVersion}"
kapt 'com.github.matthiasrobbers:shortbread-compiler:1.0.1'
kapt "org.projectlombok:lombok:${lombokVersion}"
kapt "com.github.florent37:retrojsoup-compiler:${retrojsoupVersion}"
// testCompile "net.grandcentrix.thirtyinch:thirtyinch-test:$thirtyinchVersion"
testCompile "junit:junit:${junitVersion}"
testCompile "org.mockito:mockito-core:${mockitoVersion}"

View File

@ -32,8 +32,7 @@
}
-keep class com.google.gson.** { *; }
-keep class com.google.inject.** { *; }
-keep class org.apache.http.** { *; }
-keep class org.apache.james.mime4j.** { *; }
-keep class org.apache.** { *; }
-keep class javax.inject.** { *; }
-keep class retrofit.** { *; }
-keep class com.squareup.okhttp.** { *; }
@ -45,7 +44,7 @@
-dontwarn rx.**
-dontwarn com.squareup.okhttp.**
-dontwarn okio.**
-dontwarn org.apache.http.**
-dontwarn org.apache.**
-dontwarn android.net.http.AndroidHttpClient
-dontwarn retrofit.**
-dontwarn retrofit2.adapter.rxjava.CompletableHelper$**
@ -72,7 +71,8 @@
-keepclasseswithmembernames class * {
@icepick.* <fields>;
}
-keep class com.fastaccess.data.dao.** { *; }
-keep class com.fastaccess.data.** { *; }
-keep class com.fastaccess.provider.rest.** { *; }
-keepclassmembers class com.prettifier.pretty.callback.MarkDownInterceptorInterface {
public *;
}
@ -80,6 +80,7 @@
-dontwarn java.util.**
-dontwarn java.time.**
-dontwarn javax.annotation.**
-dontwarn org.jetbrains.annotations.**
-dontwarn javax.cache.**
-dontwarn javax.naming.**
-dontwarn javax.transaction.**
@ -101,11 +102,23 @@
<fields>;
}
-keep class net.nightwhistler.** {*;}
-keep class org.htmlcleaner.** {*;}
-keep class net.nightwhistler.** { *; }
-keep class org.htmlcleaner.** { *; }
-dontwarn org.jaxen.**
-dontwarn org.jdom.**
-dontwarn com.google.android.gms.**
-dontwarn android.animation.**
-dontwarn java.io.**
-dontwarn android.content.**
-dontwarn android.content.**
-dontwarn org.jdom.**
-dontwarn kotlin.reflect.jvm.internal.impl.descriptors.CallableDescriptor
-dontwarn kotlin.reflect.jvm.internal.impl.descriptors.ClassDescriptor
-dontwarn kotlin.reflect.jvm.internal.impl.descriptors.ClassifierDescriptorWithTypeParameters
-dontwarn kotlin.reflect.jvm.internal.impl.descriptors.annotations.AnnotationDescriptor
-dontwarn kotlin.reflect.jvm.internal.impl.descriptors.impl.PropertyDescriptorImpl
-dontwarn kotlin.reflect.jvm.internal.impl.load.java.JavaClassFinder
-dontwarn kotlin.reflect.jvm.internal.impl.resolve.OverridingUtil
-dontwarn kotlin.reflect.jvm.internal.impl.types.DescriptorSubstitutor
-dontwarn kotlin.reflect.jvm.internal.impl.types.DescriptorSubstitutor
-dontwarn kotlin.reflect.jvm.internal.impl.types.TypeConstructor
-keeppackagenames org.jsoup.nodes

View File

@ -220,7 +220,7 @@
<service
android:name=".provider.tasks.notification.NotificationSchedulerJobTask"
android:exported="false">
android:exported="true">
<intent-filter>
<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE"/>
</intent-filter>

View File

@ -1,144 +0,0 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.vending.billing;
import android.os.Bundle;
/**
* InAppBillingService is the service that provides in-app billing version 3 and beyond.
* This service provides the following features:
* 1. Provides a new API to get details of in-app items published for the app including
* price, type, title and description.
* 2. The purchase flow is synchronous and purchase information is available immediately
* after it completes.
* 3. Purchase information of in-app purchases is maintained within the Google Play system
* till the purchase is consumed.
* 4. An API to consume a purchase of an inapp item. All purchases of one-time
* in-app items are consumable and thereafter can be purchased again.
* 5. An API to get current purchases of the user immediately. This will not contain any
* consumed purchases.
*
* All calls will give a response code with the following possible values
* RESULT_OK = 0 - success
* RESULT_USER_CANCELED = 1 - user pressed back or canceled a dialog
* RESULT_BILLING_UNAVAILABLE = 3 - this billing API version is not supported for the type requested
* RESULT_ITEM_UNAVAILABLE = 4 - requested SKU is not available for purchase
* RESULT_DEVELOPER_ERROR = 5 - invalid arguments provided to the API
* RESULT_ERROR = 6 - Fatal error during the API action
* RESULT_ITEM_ALREADY_OWNED = 7 - Failure to purchase since item is already owned
* RESULT_ITEM_NOT_OWNED = 8 - Failure to consume since item is not owned
*/
interface IInAppBillingService {
/**
* Checks support for the requested billing API version, package and in-app type.
* Minimum API version supported by this interface is 3.
* @param apiVersion the billing version which the app is using
* @param packageName the package name of the calling app
* @param type type of the in-app item being purchased "inapp" for one-time purchases
* and "subs" for subscription.
* @return RESULT_OK(0) on success, corresponding result code on failures
*/
int isBillingSupported(int apiVersion, String packageName, String type);
/**
* Provides details of a list of SKUs
* Given a list of SKUs of a valid type in the skusBundle, this returns a bundle
* with a list JSON strings containing the productId, price, title and description.
* This API can be called with a maximum of 20 SKUs.
* @param apiVersion billing API version that the Third-party is using
* @param packageName the package name of the calling app
* @param skusBundle bundle containing a StringArrayList of SKUs with key "ITEM_ID_LIST"
* @return Bundle containing the following key-value pairs
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
* failure as listed above.
* "DETAILS_LIST" with a StringArrayList containing purchase information
* in JSON format similar to:
* '{ "productId" : "exampleSku", "type" : "inapp", "price" : "$5.00",
* "title : "Example Title", "description" : "This is an example description" }'
*/
Bundle getSkuDetails(int apiVersion, String packageName, String type, in Bundle skusBundle);
/**
* Returns a pending intent to launch the purchase flow for an in-app item by providing a SKU,
* the type, a unique purchase token and an optional developer payload.
* @param apiVersion billing API version that the app is using
* @param packageName package name of the calling app
* @param sku the SKU of the in-app item as published in the developer console
* @param type the type of the in-app item ("inapp" for one-time purchases
* and "subs" for subscription).
* @param developerPayload optional argument to be sent back with the purchase information
* @return Bundle containing the following key-value pairs
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
* failure as listed above.
* "BUY_INTENT" - PendingIntent to start the purchase flow
*
* The Pending intent should be launched with startIntentSenderForResult. When purchase flow
* has completed, the onActivityResult() will give a resultCode of OK or CANCELED.
* If the purchase is successful, the result data will contain the following key-value pairs
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
* failure as listed above.
* "INAPP_PURCHASE_DATA" - String in JSON format similar to
* '{"orderId":"12999763169054705758.1371079406387615",
* "packageName":"com.example.app",
* "productId":"exampleSku",
* "purchaseTime":1345678900000,
* "purchaseToken" : "122333444455555",
* "developerPayload":"example developer payload" }'
* "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that
* was signed with the private key of the developer
* TODO: change this to app-specific keys.
*/
Bundle getBuyIntent(int apiVersion, String packageName, String sku, String type,
String developerPayload);
/**
* Returns the current SKUs owned by the user of the type and package name specified along with
* purchase information and a signature of the data to be validated.
* This will return all SKUs that have been purchased in V3 and managed items purchased using
* V1 and V2 that have not been consumed.
* @param apiVersion billing API version that the app is using
* @param packageName package name of the calling app
* @param type the type of the in-app items being requested
* ("inapp" for one-time purchases and "subs" for subscription).
* @param continuationToken to be set as null for the first call, if the number of owned
* skus are too many, a continuationToken is returned in the response bundle.
* This method can be called again with the continuation token to get the next set of
* owned skus.
* @return Bundle containing the following key-value pairs
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
* failure as listed above.
* "INAPP_PURCHASE_ITEM_LIST" - StringArrayList containing the list of SKUs
* "INAPP_PURCHASE_DATA_LIST" - StringArrayList containing the purchase information
* "INAPP_DATA_SIGNATURE_LIST"- StringArrayList containing the signatures
* of the purchase information
* "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the
* next set of in-app purchases. Only set if the
* user has more owned skus than the current list.
*/
Bundle getPurchases(int apiVersion, String packageName, String type, String continuationToken);
/**
* Consume the last purchase of the given SKU. This will result in this item being removed
* from all subsequent responses to getPurchases() and allow re-purchase of this item.
* @param apiVersion billing API version that the app is using
* @param packageName package name of the calling app
* @param purchaseToken token in the purchase information JSON that identifies the purchase
* to be consumed
* @return 0 if consumption succeeded. Appropriate error values for failures.
*/
int consumePurchase(int apiVersion, String packageName, String purchaseToken);
}

0
app/src/main/assets/highlight/js/lang-Splus.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-aea.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-agc.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-apollo.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-basic.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-cbm.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-cl.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-clj.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-css.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-dart.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-el.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-erl.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-erlang.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-fs.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-go.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-hs.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-lasso.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-lassoscript.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-latex.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-lgt.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-lisp.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-ll.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-llvm.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-logtalk.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-ls.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-lsp.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-lua.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-matlab.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-ml.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-mumps.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-n.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-nemerle.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-pascal.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-proto.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-r.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-rd.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-rkt.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-rust.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-s.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-scala.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-scm.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-sql.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-ss.js Normal file → Executable file
View File

4
app/src/main/assets/highlight/js/lang-swift.js Normal file → Executable file
View File

@ -1,16 +1,18 @@
/*
Copyright (C) 2015 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[ \n\r\t\v\f\0]+/,null," \n\r\t\v\f\x00"],["str",/^"(?:[^"\\]|(?:\\.)|(?:\\\((?:[^"\\)]|\\.)*\)))*"/,null,'"']],[["lit",/^(?:(?:0x[\da-fA-F][\da-fA-F_]*\.[\da-fA-F][\da-fA-F_]*[pP]?)|(?:\d[\d_]*\.\d[\d_]*[eE]?))[+-]?\d[\d_]*/,null],["lit",/^-?(?:(?:0(?:(?:b[01][01_]*)|(?:o[0-7][0-7_]*)|(?:x[\da-fA-F][\da-fA-F_]*)))|(?:\d[\d_]*))/,null],["lit",/^(?:true|false|nil)\b/,null],["kwd",/^\b(?:__COLUMN__|__FILE__|__FUNCTION__|__LINE__|#available|#else|#elseif|#endif|#if|#line|arch|arm|arm64|associativity|as|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|dynamicType|else|enum|fallthrough|final|for|func|get|import|indirect|infix|init|inout|internal|i386|if|in|iOS|iOSApplicationExtension|is|lazy|left|let|mutating|none|nonmutating|operator|optional|OSX|OSXApplicationExtension|override|postfix|precedence|prefix|private|protocol|Protocol|public|required|rethrows|return|right|safe|self|set|static|struct|subscript|super|switch|throw|try|Type|typealias|unowned|unsafe|var|weak|watchOS|while|willSet|x86_64)\b/,
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[ \n\r\t\v\f\0]+/,null," \n\r\t\v\f\x00"],["str",/^"(?:[^"\\]|(?:\\.)|(?:\\\((?:[^"\\)]|\\.)*\)))*"/,null,'"']],[["lit",/^(?:(?:0x[\da-fA-F][\da-fA-F_]*\.[\da-fA-F][\da-fA-F_]*[pP]?)|(?:\d[\d_]*\.\d[\d_]*[eE]?))[+-]?\d[\d_]*/,null],["lit",/^-?(?:(?:0(?:(?:b[01][01_]*)|(?:o[0-7][0-7_]*)|(?:x[\da-fA-F][\da-fA-F_]*)))|(?:\d[\d_]*))/,null],["lit",/^(?:true|false|nil)\b/,null],["kwd",/^\b(?:__COLUMN__|__FILE__|__FUNCTION__|__LINE__|#available|#else|#elseif|#endif|#if|#line|arch|arm|arm64|associativity|as|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|dynamicType|else|enum|extension|fallthrough|final|for|func|get|guard|import|indirect|infix|init|inout|internal|i386|if|in|iOS|iOSApplicationExtension|is|lazy|left|let|mutating|none|nonmutating|operator|optional|OSX|OSXApplicationExtension|override|postfix|precedence|prefix|private|protocol|Protocol|public|required|rethrows|return|right|safe|self|set|static|struct|subscript|super|switch|throw|try|Type|typealias|unowned|unsafe|var|weak|watchOS|while|willSet|x86_64)\b/,
null],["com",/^\/\/.*?[\n\r]/,null],["com",/^\/\*[\s\S]*?(?:\*\/|$)/,null],["pun",/^<<=|<=|<<|>>=|>=|>>|===|==|\.\.\.|&&=|\.\.<|!==|!=|&=|~=|~|\(|\)|\[|\]|{|}|@|#|;|\.|,|:|\|\|=|\?\?|\|\||&&|&\*|&\+|&-|&=|\+=|-=|\/=|\*=|\^=|%=|\|=|->|`|==|\+\+|--|\/|\+|!|\*|%|<|>|&|\||\^|\?|=|-|_/,null],["typ",/^\b(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null]]),["swift"]);

0
app/src/main/assets/highlight/js/lang-tcl.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-tex.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-vb.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-vbs.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-vhd.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-vhdl.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-wiki.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-xq.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-xquery.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-yaml.js Normal file → Executable file
View File

0
app/src/main/assets/highlight/js/lang-yml.js Normal file → Executable file
View File

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +1,32 @@
.prettyprint {
font-family: Menlo, "Bitstream Vera Sans Mono", "DejaVu Sans Mono", Monaco, Consolas, monospace;
border: 0 !important;
font-family: Menlo, "Bitstream Vera Sans Mono", "DejaVu Sans Mono", Monaco, Consolas, monospace !important;
border: 0 !important;
}
.pln {
color: #333;
color: #333 !important;
}
ol.linenums {
margin-top: 0;
margin-bottom: 0;
color: #727272;
margin-top: 0 !important;
margin-bottom: 0 !important;
color: #727272 !important;
}
ol {
margin-left: 0;
padding-left: 0.2em;
margin-left: 0 !important;
padding-left: 0.2em !important;
counter-reset: ol-item
}
ol li:nth-child(-n+9) {
padding-left: 8px;
padding-left: 8px !important;
}
ol li {
margin-left: 0;
padding-left: 0;
list-style-type: none;
margin-left: 0 !important;
padding-left: 0 !important;
list-style-type: none !important;
counter-increment: ol-item
}
@ -34,7 +34,6 @@ ol li:before {
content: counter(ol-item) " "
}
li.L0,
li.L1,
li.L2,
@ -44,91 +43,79 @@ li.L5,
li.L6,
li.L7,
li.L8,
li.L9 {}
li.L9 {
background: transparent !important;
}
@media screen {
/* string content */
/* string content */
.str {
color: #183691 !important;
}
.str {
color: #183691;
}
/* keyword */
.kwd {
color: #a71d5d !important;
}
/* keyword */
/* comment */
.com {
color: #969896 !important;
}
.kwd {
color: #a71d5d;
}
/* type name */
.typ {
color: #0086b3 !important;
}
/* comment */
/* literal value */
.lit {
color: #0086b3 !important;
}
.com {
color: #969896;
}
/* punctuation */
.pun {
color: #333 !important;
}
/* type name */
/* lisp open bracket */
.opn {
color: #333 !important;
}
.typ {
color: #0086b3;
}
/* lisp close bracket */
.clo {
color: #333 !important;
}
/* literal value */
/* markup tag name */
.tag {
color: #000080 !important;
}
.lit {
color: #0086b3;
}
/* markup attribute name */
.atn {
color: #795da3 !important;
}
/* punctuation */
/* markup attribute value */
.atv {
color: #183691 !important;
}
.pun {
color: #333;
}
/* declaration */
.dec {
color: #333 !important;
}
/* lisp open bracket */
/* variable name */
.var {
color: #008080 !important;
}
.opn {
color: #333;
}
/* lisp close bracket */
.clo {
color: #333;
}
/* markup tag name */
.tag {
color: #000080;
}
/* markup attribute name */
.atn {
color: #795da3;
}
/* markup attribute value */
.atv {
color: #183691;
}
/* declaration */
.dec {
color: #333;
}
/* variable name */
.var {
color: #008080;
}
/* function name */
.fun {
color: #900;
}
/* function name */
.fun {
color: #900 !important;
}
}

View File

@ -1,33 +1,33 @@
.prettyprint {
font-family: Menlo, "Bitstream Vera Sans Mono", "DejaVu Sans Mono", Monaco, Consolas, monospace;
border: 0 !important;
font-family: Menlo, "Bitstream Vera Sans Mono", "DejaVu Sans Mono", Monaco, Consolas, monospace !important;
border: 0 !important;
}
.pln {
color: #e6e9ed;
color: #e6e9ed !important;
}
/* Specify class=linenums on a pre to get line numbering */
ol.linenums {
margin-top: 0;
margin-bottom: 0;
color: #656d78;
margin-top: 0 !important;
margin-bottom: 0 !important;
color: #656d78 !important;
}
ol {
margin-left: 0;
padding-left: 0.2em;
margin-left: 0 !important;
padding-left: 0.2em !important;
counter-reset: ol-item
}
ol li:nth-child(-n+9) {
padding-left: 8px;
padding-left: 8px !important;
}
ol li {
margin-left: 0;
padding-left: 0;
list-style-type: none;
margin-left: 0 !important;
padding-left: 0 !important;
list-style-type: none !important;
counter-increment: ol-item
}
@ -44,91 +44,79 @@ li.L5,
li.L6,
li.L7,
li.L8,
li.L9 {}
li.L9 {
background: transparent !important;
}
@media screen {
/* string content */
/* string content */
.str {
color: #ffce54 !important;
}
.str {
color: #ffce54;
}
/* keyword */
.kwd {
color: #4fc1e9 !important;
}
/* keyword */
/* comment */
.com {
color: #656d78 !important;
}
.kwd {
color: #4fc1e9;
}
/* type name */
.typ {
color: #4fc1e9 !important;
}
/* comment */
/* literal value */
.lit {
color: #ac92ec !important;
}
.com {
color: #656d78;
}
/* punctuation */
.pun {
color: #e6e9ed !important;
}
/* type name */
/* lisp open bracket */
.opn {
color: #e6e9ed !important;
}
.typ {
color: #4fc1e9;
}
/* lisp close bracket */
.clo {
color: #e6e9ed !important;
}
/* literal value */
/* markup tag name */
.tag {
color: #ed5565 !important;
}
.lit {
color: #ac92ec;
}
/* markup attribute name */
.atn {
color: #a0d468 !important;
}
/* punctuation */
/* markup attribute value */
.atv {
color: #ffce54 !important;
}
.pun {
color: #e6e9ed;
}
/* declaration */
.dec {
color: #ac92ec !important;
}
/* lisp open bracket */
/* variable name */
.var {
color: #e6e9ed !important;
}
.opn {
color: #e6e9ed;
}
/* lisp close bracket */
.clo {
color: #e6e9ed;
}
/* markup tag name */
.tag {
color: #ed5565;
}
/* markup attribute name */
.atn {
color: #a0d468;
}
/* markup attribute value */
.atv {
color: #ffce54;
}
/* declaration */
.dec {
color: #ac92ec;
}
/* variable name */
.var {
color: #e6e9ed;
}
/* function name */
.fun {
color: #e6e9ed;
}
/* function name */
.fun {
color: #e6e9ed !important;
}
}

View File

@ -9,7 +9,6 @@ import com.annimon.stream.Stream;
import com.fastaccess.R;
import com.fastaccess.data.dao.model.Commit;
import com.fastaccess.data.dao.model.Gist;
import com.fastaccess.data.dao.model.Issue;
import com.fastaccess.data.dao.model.Login;
import com.fastaccess.data.dao.model.PullRequest;
import com.fastaccess.data.dao.types.IssueState;
@ -21,6 +20,7 @@ import com.fastaccess.ui.modules.main.issues.MyIssuesFragment;
import com.fastaccess.ui.modules.main.pullrequests.MyPullRequestFragment;
import com.fastaccess.ui.modules.notification.all.AllNotificationsFragment;
import com.fastaccess.ui.modules.notification.unread.UnreadNotificationsFragment;
import com.fastaccess.ui.modules.profile.events.ProfileEventsFragment;
import com.fastaccess.ui.modules.profile.followers.ProfileFollowersFragment;
import com.fastaccess.ui.modules.profile.following.ProfileFollowingFragment;
import com.fastaccess.ui.modules.profile.gists.ProfileGistsFragment;
@ -74,6 +74,7 @@ import lombok.Setter;
@NonNull public static List<FragmentPagerAdapterModel> buildForProfile(@NonNull Context context, @NonNull String login) {
return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.overview), ProfileOverviewFragment.newInstance(login)),
new FragmentPagerAdapterModel(context.getString(R.string.feed), ProfileEventsFragment.Companion.newInstance(login)),
new FragmentPagerAdapterModel(context.getString(R.string.repos), ProfileReposFragment.newInstance(login)),
new FragmentPagerAdapterModel(context.getString(R.string.starred), ProfileStarredFragment.newInstance(login)),
new FragmentPagerAdapterModel(context.getString(R.string.gists), ProfileGistsFragment.newInstance(login)),
@ -86,7 +87,8 @@ import lombok.Setter;
@NonNull String login, @NonNull String url,
@NonNull String defaultBranch) {
return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.readme), ViewerFragment.newInstance(url, true)),
new FragmentPagerAdapterModel(context.getString(R.string.files), RepoFilePathFragment.newInstance(login, repoId, null, defaultBranch)),
new FragmentPagerAdapterModel(context.getString(R.string.files), RepoFilePathFragment.newInstance(login, repoId, null,
defaultBranch)),
new FragmentPagerAdapterModel(context.getString(R.string.commits), RepoCommitsFragment.newInstance(repoId, login, defaultBranch)),
new FragmentPagerAdapterModel(context.getString(R.string.releases), RepoReleasesFragment.newInstance(repoId, login)),
new FragmentPagerAdapterModel(context.getString(R.string.contributors), RepoContributorsFragment.newInstance(repoId, login)))
@ -101,8 +103,8 @@ import lombok.Setter;
.collect(Collectors.toList());
}
@NonNull public static List<FragmentPagerAdapterModel> buildForIssues(@NonNull Context context, @NonNull Issue issueModel) {
return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.details), IssueTimelineFragment.newInstance(issueModel)))
@NonNull public static List<FragmentPagerAdapterModel> buildForIssues(@NonNull Context context) {
return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.details), IssueTimelineFragment.newInstance()))
.collect(Collectors.toList());
}
@ -111,7 +113,7 @@ import lombok.Setter;
String login = pullRequest.getLogin();
String repoId = pullRequest.getRepoId();
int number = pullRequest.getNumber();
return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.details), PullRequestTimelineFragment.newInstance(pullRequest)),
return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.details), PullRequestTimelineFragment.newInstance()),
new FragmentPagerAdapterModel(context.getString(R.string.commits), PullRequestCommitsFragment.newInstance(repoId, login, number)),
new FragmentPagerAdapterModel(context.getString(R.string.files), PullRequestFilesFragment.newInstance(repoId, login, number)))
.collect(Collectors.toList());

View File

@ -49,8 +49,8 @@ public class GitCommitModel implements Parcelable {
this.committer = in.readParcelable(User.class.getClassLoader());
this.tree = in.readParcelable(User.class.getClassLoader());
this.distincted = in.readByte() != 0;
in.readList(parents, parents.getClass().getClassLoader());
in.readList(this.parents, GitCommitModel.class.getClassLoader());
this.parents = new GitCommitListModel();
in.readList(this.parents, this.parents.getClass().getClassLoader());
this.commentCount = in.readInt();
}

View File

@ -17,12 +17,12 @@ import lombok.Setter;
@Getter @Setter @NoArgsConstructor
public class Pageable<M extends Parcelable> implements Parcelable {
private int first;
private int next;
private int prev;
private int last;
private int totalCount;
private boolean incompleteResults;
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; }

View File

@ -22,17 +22,17 @@ import lombok.Setter;
@Getter @Setter @NoArgsConstructor
public class PayloadModel implements Parcelable {
private String action;
private Repo forkee;
private Issue issue;
private PullRequest pullRequest;
private String ref;
private String refType;
private Comment comment;
private User target;
private User member;
private String head;
private TeamsModel team;
public String action;
public Repo forkee;
public Issue issue;
public PullRequest pullRequest;
public String ref;
public String refType;
public Comment comment;
public User target;
public User member;
public String head;
public TeamsModel team;
@Override public int describeContents() { return 0; }

View File

@ -14,8 +14,9 @@ import lombok.Setter;
@Getter @Setter
public class SimpleUrlsModel implements Parcelable {
private String item;
private String url;
public String item;
public String url;
public SimpleUrlsModel(String item, String url) {
this.item = item;
this.url = url;

View File

@ -280,6 +280,7 @@ import static com.annimon.stream.Collectors.toList;
return comment != null ? (int) comment.getId() : 0;
}
@Override public int describeContents() { return 0; }
@Override public void writeToParcel(Parcel dest, int flags) {
@ -290,6 +291,8 @@ import static com.annimon.stream.Collectors.toList;
dest.writeParcelable(this.pullRequest, flags);
dest.writeParcelable(this.status, 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);
}
@ -301,6 +304,8 @@ import static com.annimon.stream.Collectors.toList;
this.pullRequest = in.readParcelable(PullRequest.class.getClassLoader());
this.status = in.readParcelable(PullRequestStatusModel.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);
}

View File

@ -0,0 +1,39 @@
package com.fastaccess.data.dao
import android.os.Parcel
import android.os.Parcelable
data class TrendingModel(
val title: String? = null,
val description: String? = null,
val language: String? = null,
val stars: String? = null,
val forks: String? = null,
val todayStars: String? = null) : Parcelable {
companion object {
@JvmField val CREATOR: Parcelable.Creator<TrendingModel> = object : Parcelable.Creator<TrendingModel> {
override fun createFromParcel(source: Parcel): TrendingModel = TrendingModel(source)
override fun newArray(size: Int): Array<TrendingModel?> = arrayOfNulls(size)
}
}
constructor(source: Parcel) : this(
source.readString(),
source.readString(),
source.readString(),
source.readString(),
source.readString(),
source.readString()
)
override fun describeContents() = 0
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeString(title)
dest.writeString(description)
dest.writeString(language)
dest.writeString(stars)
dest.writeString(forks)
dest.writeString(todayStars)
}
}

View File

@ -1,47 +0,0 @@
package com.fastaccess.data.dao;
import android.os.Parcel;
import android.os.Parcelable;
import com.github.florent37.retrojsoup.annotations.JsoupText;
import lombok.ToString;
/**
* Created by Kosh on 02 Jun 2017, 1:06 PM
*/
@ToString public class TrendingResponse implements Parcelable { // retroSoup doesn't like it to be kolin class.
@JsoupText(".repo-list > li > .d-inline-block > h3 > a") public String title;
@JsoupText(".repo-list > li > .py-1 > p") public String description;
@JsoupText(".repo-list > li > .f6 > a[href*=/stargazers]") public String stars;
@JsoupText(".repo-list > li > .f6 > a[href*=/network]") public String forks;
@JsoupText(".repo-list > li > .f6 > span.float-right") public String todayStars;
@Override public int describeContents() { return 0; }
@Override public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.title);
dest.writeString(this.description);
dest.writeString(this.stars);
dest.writeString(this.forks);
dest.writeString(this.todayStars);
}
public TrendingResponse() {}
protected TrendingResponse(Parcel in) {
this.title = in.readString();
this.description = in.readString();
this.stars = in.readString();
this.forks = in.readString();
this.todayStars = in.readString();
}
public static final Parcelable.Creator<TrendingResponse> CREATOR = new Parcelable.Creator<TrendingResponse>() {
@Override public TrendingResponse createFromParcel(Parcel source) {return new TrendingResponse(source);}
@Override public TrendingResponse[] newArray(int size) {return new TrendingResponse[size];}
};
}

View File

@ -12,7 +12,6 @@ import com.fastaccess.data.dao.GithubFileModel;
import com.fastaccess.data.dao.converters.GitHubFilesConverter;
import com.fastaccess.data.dao.converters.UserConverter;
import com.fastaccess.helper.InputHelper;
import com.fastaccess.helper.ObjectsCompat;
import com.fastaccess.helper.RxHelper;
import com.fastaccess.ui.widgets.SpannableBuilder;
import com.google.gson.annotations.SerializedName;
@ -35,7 +34,7 @@ import lombok.NoArgsConstructor;
* Created by Kosh on 16 Mar 2017, 7:32 PM
*/
@Entity @NoArgsConstructor public abstract class AbstractGist implements Parcelable {
@Entity() @NoArgsConstructor public abstract class AbstractGist implements Parcelable {
@SerializedName("nooope") @Key long id;
String url;
String forksUrl;
@ -79,11 +78,11 @@ import lombok.NoArgsConstructor;
.single()
.toObservable()
.flatMap(integer -> Observable.fromIterable(gists))
.filter(ObjectsCompat::nonNull)
.flatMap(gist -> {
.map(gist -> {
gist.setOwnerName(ownerName);
return gist.save(gist).toObservable();
}));
return gist;
})
.flatMap(gist -> gist.save(gist).toObservable()));
}
@NonNull public static Single<List<Gist>> getMyGists(@NonNull String ownerName) {
@ -168,7 +167,16 @@ import lombok.NoArgsConstructor;
spannableBuilder.append(description);
}
if (InputHelper.isEmpty(spannableBuilder.toString())) {
if (isFromProfile) spannableBuilder.bold("N/A");
if (isFromProfile) {
List<FilesListModel> files = getFilesAsList();
if (!files.isEmpty()) {
FilesListModel filesListModel = files.get(0);
if (!InputHelper.isEmpty(filesListModel.getFilename()) && filesListModel.getFilename().trim().length() > 2) {
spannableBuilder.append(" ")
.append(filesListModel.getFilename());
}
}
}
}
return spannableBuilder;
}

View File

@ -8,6 +8,7 @@ import com.fastaccess.data.dao.Pageable;
import com.fastaccess.data.dao.model.Comment;
import com.fastaccess.data.dao.model.Gist;
import io.reactivex.Observable;
import retrofit2.Response;
import retrofit2.http.Body;
import retrofit2.http.DELETE;
@ -19,7 +20,6 @@ import retrofit2.http.PUT;
import retrofit2.http.Path;
import retrofit2.http.Query;
import retrofit2.http.Url;
import io.reactivex.Observable;
/**
* Created by Kosh on 20 Nov 2016, 10:28 AM
@ -38,11 +38,10 @@ public interface GistService {
@GET("gists/public") Observable<Pageable<Gist>> getPublicGists(@Query("per_page") int perPage, @Query("page") int page);
@GET("gists") Observable<Pageable<Gist>> getMyGists(@Query("per_page") int perPage, @Query("page") int page);
@GET("gists") Observable<Pageable<Gist>> getMyGists(@Query("page") int page);
@GET("users/{username}/gists")
Observable<Pageable<Gist>> getUserGists(@NonNull @Path("username") String username,
@Query("per_page") int perPage, @Query("page") int page);
Observable<Pageable<Gist>> getUserGists(@NonNull @Path("username") String username, @Query("page") int page);
@GET("gists/{id}")
Observable<Gist> getGist(@Path("id") String id);

View File

@ -1,9 +1,12 @@
package com.fastaccess.data.service;
import com.fastaccess.data.dao.TrendingResponse;
import com.github.florent37.retrojsoup.annotations.Select;
import android.support.annotation.Nullable;
import io.reactivex.Observable;
import retrofit2.http.GET;
import retrofit2.http.Path;
import retrofit2.http.Query;
/**
* Created by Kosh on 02 Jun 2017, 12:58 PM
@ -11,5 +14,5 @@ import io.reactivex.Observable;
public interface TrendingService {
@Select(".repo-list") Observable<TrendingResponse> getTrending();
@GET("{lan}") Observable<String> getTrending(@Path("lan") @Nullable String lan, @Nullable @Query("since") String since);
}

View File

@ -34,15 +34,22 @@ public interface UserRestService {
@GET("users/{username}/received_events")
Observable<Pageable<Event>> getReceivedEvents(@NonNull @Path("username") String userName, @Query("page") int page);
@GET("/users/{username}/repos")
Observable<Pageable<Repo>> getRepos(@Path("username") @NonNull String username, @QueryMap(encoded=true) Map<String, String> filterParams, @Query("page") int page);
@GET("users/{username}/events")
Observable<Pageable<Event>> getUserEvents(@NonNull @Path("username") String userName, @Query("page") int page);
@GET("/user/repos")
Observable<Pageable<Repo>> getRepos(@QueryMap(encoded=true) Map<String, String> filterParams, @Query(value = "page") int page);
@GET("users/{username}/repos")
Observable<Pageable<Repo>> getRepos(@Path("username") @NonNull String username, @QueryMap(encoded = true) Map<String, String> filterParams,
@Query("page") int page);
@GET("user/repos")
Observable<Pageable<Repo>> getRepos(@QueryMap(encoded = true) Map<String, String> filterParams, @Query(value = "page") int page);
@GET("users/{username}/starred") Observable<Pageable<Repo>>
getStarred(@Path("username") @NonNull String username, @Query("page") int page);
@GET("users/{username}/starred?per_page=1") Observable<Pageable<Repo>>
getStarredCount(@Path("username") @NonNull String username);
@GET("users/{username}/following")
Observable<Pageable<User>> getFollowing(@Path("username") @NonNull String username, @Query("page") int page);
@ -52,10 +59,10 @@ public interface UserRestService {
@GET("user/following/{username}")
Observable<Response<Boolean>> getFollowStatus(@Path("username") @NonNull String username);
@PUT("/user/following/{username}")
@PUT("user/following/{username}")
Observable<Response<Boolean>> followUser(@Path("username") @NonNull String username);
@DELETE("/user/following/{username}")
@DELETE("user/following/{username}")
Observable<Response<Boolean>> unfollowUser(@Path("username") @NonNull String username);
@GET Observable<String> getContributions(@Url String url);

View File

@ -60,7 +60,7 @@ public class ParseDateFormat {
return INSTANCE;
}
public static String getDateByDays(int days) {
private static String getDateByDays(int days) {
Calendar cal = Calendar.getInstance();
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH);
cal.add(Calendar.DAY_OF_YEAR, days);

View File

@ -21,7 +21,6 @@ public class RxHelper {
public static <T> Observable<T> safeObservable(@NonNull Observable<T> observable) {
return getObserver(observable)
.onErrorReturn(throwable -> (T) new Object())
.doOnError(Throwable::printStackTrace);
}

View File

@ -23,6 +23,7 @@ import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import io.reactivex.Observable;
@ -33,6 +34,9 @@ import io.reactivex.Observable;
public class ColorsProvider {
private static List<String> popularLanguages = Stream.of("Java", "Kotlin", "JavaScript", "Python", "CSS", "PHP",
"Ruby", "C++", "C", "GO", "Swift").toList();//predefined languages.
private static Map<String, LanguageColorModel> colors = new LinkedHashMap<>();
public static void load() {
@ -57,10 +61,14 @@ public class ColorsProvider {
}
@NonNull public static ArrayList<String> languages() {
return Stream.of(colors)
ArrayList<String> lang = new ArrayList<>();
lang.add("All Language");
lang.addAll(Stream.of(colors)
.filter(value -> value != null && !InputHelper.isEmpty(value.getKey()))
.map(Map.Entry::getKey)
.collect(Collectors.toCollection(ArrayList::new));
.sortBy(s -> !popularLanguages.contains(s))
.collect(Collectors.toCollection(ArrayList::new)));
return lang;
}
@Nullable public static LanguageColorModel getColor(@NonNull String lang) {

View File

@ -60,7 +60,7 @@ public class RestProvider {
.setPrettyPrinting()
.create();
public static OkHttpClient provideOkHttpClient(boolean isRawString) {
private static OkHttpClient provideOkHttpClient(boolean isRawString) {
if (okHttpClient == null) {
OkHttpClient.Builder client = new OkHttpClient.Builder();
if (BuildConfig.DEBUG) {

View File

@ -1,24 +1,36 @@
package com.fastaccess.provider.rest.interceptors;
import android.support.annotation.NonNull;
import com.fastaccess.data.service.NotificationService;
import com.fastaccess.helper.InputHelper;
import java.io.IOException;
import java.net.URI;
import lombok.AllArgsConstructor;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
@AllArgsConstructor
public class AuthenticationInterceptor implements Interceptor {
private String authToken;
private String otp;
private boolean isScrapping;
@Override public Response intercept(Chain chain) throws IOException {
public AuthenticationInterceptor(String authToken, String otp) {
this.authToken = authToken;
this.otp = otp;
}
public AuthenticationInterceptor(String authToken, String otp, boolean isScrapping) {
this.authToken = authToken;
this.otp = otp;
this.isScrapping = isScrapping;
}
@Override public Response intercept(@NonNull Chain chain) throws IOException {
Request original = chain.request();
if (original.url() != HttpUrl.get(URI.create(NotificationService.SUBSCRIPTION_URL))) {
Request.Builder builder = original.newBuilder();
@ -28,6 +40,7 @@ public class AuthenticationInterceptor implements Interceptor {
if (!InputHelper.isEmpty(otp)) {
builder.addHeader("X-GitHub-OTP", otp.trim());
}
if (!isScrapping) builder.addHeader("User-Agent", "FastHub");
Request request = builder.build();
return chain.proceed(request);
}

View File

@ -1,23 +1,22 @@
package com.fastaccess.provider.rest.jsoup;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.fastaccess.BuildConfig;
import com.fastaccess.data.service.TrendingService;
import com.fastaccess.helper.InputHelper;
import com.fastaccess.helper.PrefGetter;
import com.fastaccess.provider.rest.converters.GithubResponseConverter;
import com.fastaccess.provider.rest.interceptors.AuthenticationInterceptor;
import com.github.florent37.retrojsoup.RetroJsoup;
import com.google.gson.Gson;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
/**
* Created by Kosh on 02 Jun 2017, 12:47 PM
*/
public class RetroJsoupProvider {
public class JsoupProvider {
private static OkHttpClient okHttpClient;
@ -28,16 +27,18 @@ public class RetroJsoupProvider {
client.addInterceptor(new HttpLoggingInterceptor()
.setLevel(HttpLoggingInterceptor.Level.BODY));
}
client.addInterceptor(new AuthenticationInterceptor(PrefGetter.getToken(), PrefGetter.getOtpCode()));
client.addInterceptor(new AuthenticationInterceptor(PrefGetter.getToken(), PrefGetter.getOtpCode(), true));
okHttpClient = client.build();
}
return okHttpClient;
}
public static TrendingService getTrendingService(@NonNull String since, @Nullable String lang) {
return new RetroJsoup.Builder()
.url("https://github.com/trending/" + (!InputHelper.isEmpty(lang) ? lang : "") + "?since=" + since)
public static TrendingService getTrendingService() {
return new Retrofit.Builder()
.baseUrl("https://github.com/trending/")
.client(provideOkHttpClient())
.addConverterFactory(new GithubResponseConverter(new Gson()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
.create(TrendingService.class);
}

View File

@ -23,7 +23,7 @@ class LinkParserHelper {
static final String API_AUTHORITY = "api.github.com";
static final String PROTOCOL_HTTPS = "https";
static final ArrayList<String> IGNORED_LIST = Stream.of("notifications", "settings", "blog", "explore",
"dashboard", "repositories", "logout", "sessions", "site", "security", "contact", "about", "logos", "login", "trending", "")
"dashboard", "repositories", "logout", "sessions", "site", "security", "contact", "about", "logos", "login", "")
.collect(Collectors.toCollection(ArrayList::new));

View File

@ -23,6 +23,7 @@ import com.fastaccess.ui.modules.repos.code.releases.ReleasesListActivity;
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.trending.TrendingActivity;
import com.fastaccess.ui.modules.user.UserPagerActivity;
import java.util.List;
@ -108,6 +109,7 @@ public class SchemeParser {
String authority = data.getAuthority();
if (TextUtils.equals(authority, HOST_DEFAULT) || TextUtils.equals(authority, RAW_AUTHORITY) ||
TextUtils.equals(authority, API_AUTHORITY)) {
Intent trending = getTrending(context, data);
Intent userIntent = getUser(context, data);
Intent repoIssues = getRepoIssueIntent(context, data);
Intent repoPulls = getRepoPullRequestIntent(context, data);
@ -119,7 +121,7 @@ public class SchemeParser {
Intent commit = getCommit(context, data, showRepoBtn);
Intent commits = getCommits(context, data, showRepoBtn);
Intent blob = getBlob(context, data);
Optional<Intent> intentOptional = returnNonNull(userIntent, repoIssues, repoPulls, pullRequestIntent, commit, commits,
Optional<Intent> intentOptional = returnNonNull(trending, userIntent, repoIssues, repoPulls, pullRequestIntent, commit, commits,
createIssueIntent, issueIntent, releasesIntent, repoIntent, blob);
Optional<Intent> empty = Optional.empty();
if (intentOptional != null && intentOptional.isPresent() && intentOptional != empty) {
@ -324,6 +326,25 @@ public class SchemeParser {
return null;
}
@Nullable private static Intent getTrending(@NonNull Context context, @NonNull Uri uri) {
List<String> segments = uri.getPathSegments();
if (segments != null && !segments.isEmpty()) {
if (uri.getPathSegments().get(0).equals("trending")) {
String query = "";
String lang = "";
if (uri.getPathSegments().size() > 1) {
lang = uri.getPathSegments().get(1);
}
if (uri.getQueryParameterNames() != null && !uri.getQueryParameterNames().isEmpty()) {
query = uri.getQueryParameter("since");
}
return TrendingActivity.Companion.getTrendingIntent(context, lang, query);
}
return null;
}
return null;
}
/**
* https://github.com/owner/repo/issues/new
*/

View File

@ -5,6 +5,7 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
@ -18,6 +19,7 @@ import com.fastaccess.data.dao.model.Login;
import com.fastaccess.data.dao.model.Notification;
import com.fastaccess.helper.AppHelper;
import com.fastaccess.helper.InputHelper;
import com.fastaccess.helper.Logger;
import com.fastaccess.helper.ParseDateFormat;
import com.fastaccess.helper.PrefGetter;
import com.fastaccess.helper.RxHelper;
@ -33,6 +35,7 @@ import com.firebase.jobdispatcher.RetryStrategy;
import com.firebase.jobdispatcher.Trigger;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.assist.ImageSize;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import java.util.List;
@ -125,25 +128,42 @@ public class NotificationSchedulerJobTask extends JobService {
}
Context context = getApplicationContext();
int accentColor = ContextCompat.getColor(this, R.color.material_blue_700);
String[] url = new String[1];
Notification first = notificationThreadModels.get(0);
Observable.fromIterable(notificationThreadModels)
.subscribeOn(Schedulers.io())
.filter(notification -> notification.isUnread() && first.getId() != notification.getId())
.take(10)
.flatMap(notification -> RestProvider.getNotificationService()
.getComment(notification.getSubject().getLatestCommentUrl())
.subscribeOn(Schedulers.io()), (thread, comment) -> {
url[0] = comment.getUser().getAvatarUrl();
if (!InputHelper.isEmpty(thread.getSubject().getLatestCommentUrl())) {
getNotificationWithComment(context, accentColor, thread, comment, url[0]);
return null;
.flatMap(notification -> {
Logger.e(notification.getSubject().getTitle());
if (notification.getSubject() != null && notification.getSubject().getLatestCommentUrl() != null) {
return RestProvider.getNotificationService()
.getComment(notification.getSubject().getLatestCommentUrl())
.subscribeOn(Schedulers.io());
} else {
return Observable.empty();
}
showNotificationWithoutComment(context, accentColor, thread, url[0]);
return thread;
}, (thread, comment) -> {
CustomNotificationModel customNotificationModel = new CustomNotificationModel();
String url;
if (comment != null && comment.getUser() != null) {
url = comment.getUser().getAvatarUrl();
if (!InputHelper.isEmpty(thread.getSubject().getLatestCommentUrl())) {
customNotificationModel.comment = comment;
customNotificationModel.url = url;
}
}
customNotificationModel.notification = thread;
return customNotificationModel;
})
.subscribeOn(Schedulers.io())
.subscribe(thread -> {/*do nothing in here*/}, throwable -> jobFinished(job, true), () -> {
.subscribe(custom -> {
if (custom.comment != null) {
getNotificationWithComment(context, accentColor, custom.notification, custom.comment, custom.url);
} else {
showNotificationWithoutComment(context, accentColor, custom.notification, custom.url);
}
}, throwable -> finishJob(job), () -> {
android.app.Notification grouped = getSummaryGroupNotification(first, accentColor);
showNotification(first.getId(), grouped);
finishJob(job);
@ -155,134 +175,84 @@ public class NotificationSchedulerJobTask extends JobService {
}
private void showNotificationWithoutComment(Context context, int accentColor, Notification thread, String iconUrl) {
ImageLoader.getInstance().loadImage(iconUrl, new ImageLoadingListener() {
@Override
public void onLoadingStarted(String s, View view) {
if (!InputHelper.isEmpty(iconUrl)) {
withoutComments(null, thread, context, accentColor);
} else {
ImageLoader.getInstance().loadImage(iconUrl, new ImageSize(50, 50), new ImageLoadingListener() {
@Override public void onLoadingStarted(String s, View view) {}
}
@Override public void onLoadingFailed(String s, View view, FailReason failReason) {
withoutComments(null, thread, context, accentColor);
}
@Override
public void onLoadingFailed(String s, View view, FailReason failReason) {
android.app.Notification toAdd = getNotification(thread.getSubject().getTitle(), thread.getRepository().getFullName())
.setContentIntent(getPendingIntent(thread.getId(), thread.getSubject().getUrl()))
.addAction(R.drawable.ic_github, context.getString(R.string.open), getPendingIntent(thread.getId(), thread
.getSubject().getUrl()))
.addAction(R.drawable.ic_eye_off, context.getString(R.string.mark_as_read), getReadOnlyPendingIntent(thread.getId(), thread
.getSubject().getUrl()))
.setWhen(thread.getUpdatedAt() != null ? thread.getUpdatedAt().getTime() : System.currentTimeMillis())
.setShowWhen(true)
.setColor(accentColor)
.setGroup(NOTIFICATION_GROUP_ID)
.build();
showNotification(thread.getId(), toAdd);
}
@Override public void onLoadingComplete(String s, View view, Bitmap bitmap) {
withoutComments(bitmap, thread, context, accentColor);
}
@Override
public void onLoadingComplete(String s, View view, Bitmap bitmap) {
android.app.Notification toAdd = getNotification(thread.getSubject().getTitle(), thread.getRepository().getFullName())
.setLargeIcon(bitmap)
.setContentIntent(getPendingIntent(thread.getId(), thread.getSubject().getUrl()))
.addAction(R.drawable.ic_github, context.getString(R.string.open), getPendingIntent(thread.getId(), thread
.getSubject().getUrl()))
.addAction(R.drawable.ic_eye_off, context.getString(R.string.mark_as_read), getReadOnlyPendingIntent(thread.getId(), thread
.getSubject().getUrl()))
.setWhen(thread.getUpdatedAt() != null ? thread.getUpdatedAt().getTime() : System.currentTimeMillis())
.setShowWhen(true)
.setColor(accentColor)
.setGroup(NOTIFICATION_GROUP_ID)
.build();
showNotification(thread.getId(), toAdd);
}
@Override public void onLoadingCancelled(String s, View view) {
withoutComments(null, thread, context, accentColor);
@Override
public void onLoadingCancelled(String s, View view) {
android.app.Notification toAdd = getNotification(thread.getSubject().getTitle(), thread.getRepository().getFullName())
.setContentIntent(getPendingIntent(thread.getId(), thread.getSubject().getUrl()))
.addAction(R.drawable.ic_github, context.getString(R.string.open), getPendingIntent(thread.getId(), thread
.getSubject().getUrl()))
.addAction(R.drawable.ic_eye_off, context.getString(R.string.mark_as_read), getReadOnlyPendingIntent(thread.getId(), thread
.getSubject().getUrl()))
.setWhen(thread.getUpdatedAt() != null ? thread.getUpdatedAt().getTime() : System.currentTimeMillis())
.setShowWhen(true)
.setColor(accentColor)
.setGroup(NOTIFICATION_GROUP_ID)
.build();
showNotification(thread.getId(), toAdd);
}
});
}
});
}
}
private void getNotificationWithComment(Context context, int accentColor,
Notification thread, Comment comment, String url) {
ImageLoader.getInstance().loadImage(url, new ImageLoadingListener() {
@Override
public void onLoadingStarted(String s, View view) {
private void withoutComments(Bitmap bitmap, Notification thread, Context context, int accentColor) {
android.app.Notification toAdd = getNotification(thread.getSubject().getTitle(), thread.getRepository().getFullName())
.setLargeIcon(bitmap == null ? BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher) : bitmap)
.setContentIntent(getPendingIntent(thread.getId(), thread.getSubject().getUrl()))
.addAction(R.drawable.ic_github, context.getString(R.string.open), getPendingIntent(thread.getId(), thread
.getSubject().getUrl()))
.addAction(R.drawable.ic_eye_off, context.getString(R.string.mark_as_read), getReadOnlyPendingIntent(thread.getId(), thread
.getSubject().getUrl()))
.setWhen(thread.getUpdatedAt() != null ? thread.getUpdatedAt().getTime() : System.currentTimeMillis())
.setShowWhen(true)
.setColor(accentColor)
.setGroup(NOTIFICATION_GROUP_ID)
.build();
showNotification(thread.getId(), toAdd);
}
}
private void getNotificationWithComment(Context context, int accentColor, Notification thread, Comment comment, String url) {
if (!InputHelper.isEmpty(url)) {
ImageLoader.getInstance().loadImage(url, new ImageSize(50, 50), new ImageLoadingListener() {
@Override public void onLoadingStarted(String s, View view) {}
@Override
public void onLoadingFailed(String s, View view, FailReason failReason) {
android.app.Notification toAdd = getNotification(comment.getUser() != null ? comment.getUser().getLogin() : "", comment.getBody())
.setSmallIcon(R.drawable.ic_notification)
.setStyle(new NotificationCompat.BigTextStyle()
.setBigContentTitle(comment.getUser() != null ? comment.getUser().getLogin() : "")
.bigText(comment.getBody()))
.setWhen(comment.getCreatedAt().getTime())
.setShowWhen(true)
.addAction(R.drawable.ic_github, context.getString(R.string.open), getPendingIntent(thread.getId(),
thread.getSubject().getUrl()))
.addAction(R.drawable.ic_eye_off, context.getString(R.string.mark_as_read), getReadOnlyPendingIntent(thread.getId(),
thread.getSubject().getUrl()))
.setContentIntent(getPendingIntent(thread.getId(), thread.getSubject().getUrl()))
.setColor(accentColor)
.setGroup(NOTIFICATION_GROUP_ID)
.build();
showNotification(thread.getId(), toAdd);
}
@Override public void onLoadingFailed(String s, View view, FailReason failReason) {
withComments(null, comment, context, thread, accentColor);
}
@Override
public void onLoadingComplete(String s, View view, Bitmap bitmap) {
android.app.Notification toAdd = getNotification(comment.getUser() != null ? comment.getUser().getLogin() : "", comment.getBody())
.setLargeIcon(bitmap)
.setSmallIcon(R.drawable.ic_notification)
.setStyle(new NotificationCompat.BigTextStyle()
.setBigContentTitle(comment.getUser() != null ? comment.getUser().getLogin() : "")
.bigText(comment.getBody()))
.setWhen(comment.getCreatedAt().getTime())
.setShowWhen(true)
.addAction(R.drawable.ic_github, context.getString(R.string.open), getPendingIntent(thread.getId(),
thread.getSubject().getUrl()))
.addAction(R.drawable.ic_eye_off, context.getString(R.string.mark_as_read), getReadOnlyPendingIntent(thread.getId(),
thread.getSubject().getUrl()))
.setContentIntent(getPendingIntent(thread.getId(), thread.getSubject().getUrl()))
.setColor(accentColor)
.setGroup(NOTIFICATION_GROUP_ID)
.build();
showNotification(thread.getId(), toAdd);
}
@Override public void onLoadingComplete(String s, View view, Bitmap bitmap) {
withComments(bitmap, comment, context, thread, accentColor);
}
@Override
public void onLoadingCancelled(String s, View view) {
android.app.Notification toAdd = getNotification(comment.getUser() != null ? comment.getUser().getLogin() : "", comment.getBody())
.setSmallIcon(R.drawable.ic_notification)
.setStyle(new NotificationCompat.BigTextStyle()
.setBigContentTitle(comment.getUser() != null ? comment.getUser().getLogin() : "")
.bigText(comment.getBody()))
.setWhen(comment.getCreatedAt().getTime())
.setShowWhen(true)
.addAction(R.drawable.ic_github, context.getString(R.string.open), getPendingIntent(thread.getId(),
thread.getSubject().getUrl()))
.addAction(R.drawable.ic_eye_off, context.getString(R.string.mark_as_read), getReadOnlyPendingIntent(thread.getId(),
thread.getSubject().getUrl()))
.setContentIntent(getPendingIntent(thread.getId(), thread.getSubject().getUrl()))
.setColor(accentColor)
.setGroup(NOTIFICATION_GROUP_ID)
.build();
showNotification(thread.getId(), toAdd);
}
});
@Override public void onLoadingCancelled(String s, View view) {
withComments(null, comment, context, thread, accentColor);
}
});
} else {
withComments(null, comment, context, thread, accentColor);
}
}
private void withComments(Bitmap bitmap, Comment comment, Context context, Notification thread, int accentColor) {
android.app.Notification toAdd = getNotification(comment.getUser() != null ? comment.getUser().getLogin() : "", comment.getBody())
.setLargeIcon(bitmap == null ? BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher) : bitmap)
.setSmallIcon(R.drawable.ic_notification)
.setStyle(new NotificationCompat.BigTextStyle()
.setBigContentTitle(comment.getUser() != null ? comment.getUser().getLogin() : "")
.bigText(comment.getBody()))
.setWhen(comment.getCreatedAt().getTime())
.setShowWhen(true)
.addAction(R.drawable.ic_github, context.getString(R.string.open), getPendingIntent(thread.getId(),
thread.getSubject().getUrl()))
.addAction(R.drawable.ic_eye_off, context.getString(R.string.mark_as_read), getReadOnlyPendingIntent(thread.getId(),
thread.getSubject().getUrl()))
.setContentIntent(getPendingIntent(thread.getId(), thread.getSubject().getUrl()))
.setColor(accentColor)
.setGroup(NOTIFICATION_GROUP_ID)
.build();
showNotification(thread.getId(), toAdd);
}
private android.app.Notification getSummaryGroupNotification(@NonNull Notification thread, int accentColor) {
@ -325,4 +295,10 @@ public class NotificationSchedulerJobTask extends JobService {
return PendingIntent.getService(getApplicationContext(), InputHelper.getSafeIntId(id), intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
private static class CustomNotificationModel {
public String url;
public Notification notification;
public Comment comment;
}
}

View File

@ -90,12 +90,6 @@ public class HtmlHelper {
return mySpanner;
}
private static final String TAG_ROOT = "githubroot";
private static final String ROOT_START = '<' + TAG_ROOT + '>';
private static final String ROOT_END = "</" + TAG_ROOT + '>';
private static final String TOGGLE_START = "<span class=\"email-hidden-toggle\">";
private static final String TOGGLE_END = "</span>";
@ -122,23 +116,16 @@ public class HtmlHelper {
private static final String PARAGRAPH_END = "</p>";
private static final String BLOCKQUOTE_START = "<blockquote>";
private static final String BLOCKQUOTE_END = "</blockquote>";
//https://github.com/k0shk0sh/GitHubSdk/blob/master/library/src/main/java/com/meisolsson/githubsdk/core/HtmlUtils.java
@NonNull public static CharSequence format(final String html) {
if (html == null || html.length() == 0) return "";
StringBuilder formatted = new StringBuilder(html);
strip(formatted, TOGGLE_START, TOGGLE_END);
strip(formatted, SIGNATURE_START, SIGNATURE_END);
replace(formatted, REPLY_START, REPLY_END, BLOCKQUOTE_START, BLOCKQUOTE_END);
strip(formatted, REPLY_START, REPLY_END);
strip(formatted, HIDDEN_REPLY_START, HIDDEN_REPLY_END);
if (replace(formatted, PARAGRAPH_START, BREAK)) replace(formatted, PARAGRAPH_END, BREAK);
formatEmailFragments(formatted);
trim(formatted);
formatted.insert(0, ROOT_START);
formatted.append(ROOT_END);
return formatted;
}
@ -165,65 +152,15 @@ public class HtmlHelper {
return true;
}
private static void replace(final StringBuilder input, final String fromStart, final String fromEnd,
final String toStart, final String toEnd) {
int start = input.indexOf(fromStart);
if (start == -1)
return;
final int fromStartLength = fromStart.length();
final int fromEndLength = fromEnd.length();
final int toStartLength = toStart.length();
while (start != -1) {
input.replace(start, start + fromStartLength, toStart);
int end = input.indexOf(fromEnd, start + toStartLength);
if (end != -1)
input.replace(end, end + fromEndLength, toEnd);
start = input.indexOf(fromStart);
}
}
private static void formatEmailFragments(final StringBuilder input) {
int emailStart = input.indexOf(EMAIL_START);
int breakAdvance = BREAK.length() - 1;
while (emailStart != -1) {
int startLength = EMAIL_START.length();
int emailEnd = input.indexOf(EMAIL_END, emailStart + startLength);
if (emailEnd == -1)
break;
input.delete(emailEnd, emailEnd + EMAIL_END.length());
input.delete(emailStart, emailStart + startLength);
int fullEmail = emailEnd - startLength;
for (int i = emailStart; i < fullEmail; i++)
if (input.charAt(i) == '\n') {
input.deleteCharAt(i);
input.insert(i, BREAK);
i += breakAdvance;
fullEmail += breakAdvance;
}
emailStart = input.indexOf(EMAIL_START, fullEmail);
}
}
private static void trim(final StringBuilder input) {
int length = input.length();
int breakLength = BREAK.length();
while (length > 0) {
if (input.indexOf(BREAK) == 0)
input.delete(0, breakLength);
else if (length >= breakLength
&& input.lastIndexOf(BREAK) == length - breakLength)
input.delete(length - breakLength, length);
else if (Character.isWhitespace(input.charAt(0)))
input.deleteCharAt(0);
else if (Character.isWhitespace(input.charAt(length - 1)))
input.deleteCharAt(length - 1);
else
break;
if (input.indexOf(BREAK) == 0) input.delete(0, breakLength);
else if (length >= breakLength && input.lastIndexOf(BREAK) == length - breakLength) input.delete(length - breakLength, length);
else if (Character.isWhitespace(input.charAt(0))) input.deleteCharAt(0);
else if (Character.isWhitespace(input.charAt(length - 1))) input.deleteCharAt(length - 1);
else break;
length = input.length();
}
}

View File

@ -4,7 +4,6 @@ import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.text.SpannableStringBuilder;
import com.fastaccess.helper.Logger;
import com.fastaccess.ui.widgets.SpannableBuilder;
import net.nightwhistler.htmlspanner.TagNodeHandler;
@ -47,7 +46,6 @@ import lombok.NoArgsConstructor;
TodoItems todoItem = null;
if (node.getChildTags() != null && node.getChildTags().length > 0) {
for (TagNode tagNode : node.getChildTags()) {
Logger.e(tagNode.getName(), tagNode.getAttributes(), tagNode.getText());
if (tagNode.getName() != null && tagNode.getName().equals("input")) {
todoItem = new TodoItems();
todoItem.isChecked = tagNode.getAttributeByName("checked") != null;

View File

@ -16,12 +16,19 @@ import java.util.ArrayList;
public class FeedsAdapter extends BaseRecyclerAdapter<Event, FeedsViewHolder, BaseViewHolder.OnItemClickListener<Event>> {
public FeedsAdapter(@NonNull ArrayList<Event> Events) {
super(Events);
private boolean noImage;
public FeedsAdapter(@NonNull ArrayList<Event> events) {
this(events, false);
}
public FeedsAdapter(@NonNull ArrayList<Event> events, boolean noImage) {
super(events);
this.noImage = noImage;
}
@Override protected FeedsViewHolder viewHolder(ViewGroup parent, int viewType) {
return new FeedsViewHolder(FeedsViewHolder.getView(parent), this);
return new FeedsViewHolder(FeedsViewHolder.getView(parent, noImage), this);
}
@Override protected void onBindView(FeedsViewHolder holder, int position) {

View File

@ -66,11 +66,7 @@ public class IssuePullsTimelineAdapter extends BaseRecyclerAdapter<TimelineModel
@Override protected void onBindView(BaseViewHolder holder, int position) {
TimelineModel model = getItem(position);
if (model.getType() == TimelineModel.HEADER) {
if (model.getIssue() != null) {
((IssueDetailsViewHolder) holder).bind(model);
} else if (model.getPullRequest() != null) {
((IssueDetailsViewHolder) holder).bind(model);
}
((IssueDetailsViewHolder) holder).bind(model);
} else if (model.getType() == TimelineModel.EVENT) {
((IssueTimelineViewHolder) holder).bind(model);
} else if (model.getType() == TimelineModel.COMMENT) {

View File

@ -2,7 +2,7 @@ package com.fastaccess.ui.adapter
import android.view.ViewGroup
import com.fastaccess.R
import com.fastaccess.data.dao.TrendingResponse
import com.fastaccess.data.dao.TrendingModel
import com.fastaccess.ui.adapter.viewholder.TrendingViewHolder
import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter
import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder
@ -11,9 +11,8 @@ import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder
* Created by Kosh on 02 Jun 2017, 1:36 PM
*/
class TrendingAdapter(data: MutableList<TrendingResponse>) : BaseRecyclerAdapter<TrendingResponse,
TrendingViewHolder, BaseViewHolder.OnItemClickListener<TrendingResponse>>(data) {
class TrendingAdapter(data: MutableList<TrendingModel>) : BaseRecyclerAdapter<TrendingModel,
TrendingViewHolder, BaseViewHolder.OnItemClickListener<TrendingModel>>(data) {
override fun viewHolder(parent: ViewGroup?, viewType: Int): TrendingViewHolder {
return TrendingViewHolder(BaseViewHolder.getView(parent!!, R.layout.trending_row_item), this)
}

View File

@ -11,7 +11,6 @@ import com.fastaccess.R;
import com.fastaccess.data.dao.PayloadModel;
import com.fastaccess.data.dao.model.Event;
import com.fastaccess.data.dao.types.EventsType;
import com.fastaccess.helper.InputHelper;
import com.fastaccess.helper.ParseDateFormat;
import com.fastaccess.provider.markdown.MarkDownProvider;
import com.fastaccess.ui.widgets.AvatarLayout;
@ -29,7 +28,7 @@ import butterknife.BindView;
public class FeedsViewHolder extends BaseViewHolder<Event> {
@BindView(R.id.avatarLayout) AvatarLayout avatar;
@Nullable @BindView(R.id.avatarLayout) AvatarLayout avatar;
@BindView(R.id.description) FontTextView description;
@BindView(R.id.title) FontTextView title;
@BindView(R.id.date) FontTextView date;
@ -40,15 +39,21 @@ public class FeedsViewHolder extends BaseViewHolder<Event> {
super(itemView, adapter);
}
public static View getView(@NonNull ViewGroup viewGroup) {
return getView(viewGroup, R.layout.feeds_row_item);
public static View getView(@NonNull ViewGroup viewGroup, boolean noImage) {
if (noImage) {
return getView(viewGroup, R.layout.feeds_row_no_image_item);
} else {
return getView(viewGroup, R.layout.feeds_row_item);
}
}
@Override public void bind(@NonNull Event eventsModel) {
if (eventsModel.getActor() != null) {
avatar.setUrl(eventsModel.getActor().getAvatarUrl(), eventsModel.getActor().getLogin(), eventsModel.getActor().isOrganizationType());
} else {
avatar.setUrl(null, null);
if (avatar != null) {
if (eventsModel.getActor() != null) {
avatar.setUrl(eventsModel.getActor().getAvatarUrl(), eventsModel.getActor().getLogin(), eventsModel.getActor().isOrganizationType());
} else {
avatar.setUrl(null, null);
}
}
SpannableBuilder spannableBuilder = SpannableBuilder.builder();
spannableBuilder.append(eventsModel.getActor() != null ? eventsModel.getActor().getLogin() : "N/A").append(" ");
@ -76,12 +81,13 @@ public class FeedsViewHolder extends BaseViewHolder<Event> {
spannableBuilder.bold(action != null ? action.toLowerCase() : "")
.append(eventsModel.getPayload() != null && eventsModel.getPayload().getAction() != null ? " " : "");
if (type != EventsType.WatchEvent) {
if (type == EventsType.CreateEvent && !InputHelper.isEmpty(eventsModel.getPayload().getRef())) {
if (type == EventsType.CreateEvent && eventsModel.getPayload() != null && eventsModel.getPayload().getRefType() != null) {
spannableBuilder
.bold(itemView.getResources().getString(type.getType()).toLowerCase())
.append(" ")
.bold(eventsModel.getPayload().getRefType())
.append(" ")
.append(eventsModel.getPayload().getRef() != null ? eventsModel.getPayload().getRef() + " " : "")
.append(in)
.append(" ");
} else if ((type == EventsType.PushEvent || type == EventsType.DeleteEvent) && eventsModel.getPayload() != null) {

View File

@ -7,6 +7,7 @@ import android.view.ViewGroup;
import com.fastaccess.R;
import com.fastaccess.data.dao.model.Gist;
import com.fastaccess.helper.Logger;
import com.fastaccess.helper.ParseDateFormat;
import com.fastaccess.ui.widgets.AvatarLayout;
import com.fastaccess.ui.widgets.FontTextView;
@ -26,6 +27,7 @@ public class GistsViewHolder extends BaseViewHolder<Gist> {
@BindView(R.id.date) FontTextView date;
private boolean isFromProfile;
private GistsViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter, boolean isFromProfile) {
super(itemView, adapter);
title.setMaxLines(2);
@ -40,7 +42,6 @@ public class GistsViewHolder extends BaseViewHolder<Gist> {
}
}
@Override public void bind(@NonNull Gist item) {
if (!isFromProfile) {
if (avatar != null) {

View File

@ -13,6 +13,7 @@ import com.fastaccess.data.dao.ReactionsModel;
import com.fastaccess.data.dao.TimelineModel;
import com.fastaccess.data.dao.model.Issue;
import com.fastaccess.data.dao.model.PullRequest;
import com.fastaccess.data.dao.model.User;
import com.fastaccess.helper.InputHelper;
import com.fastaccess.helper.Logger;
import com.fastaccess.helper.ParseDateFormat;
@ -26,6 +27,8 @@ import com.fastaccess.ui.widgets.SpannableBuilder;
import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter;
import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder;
import java.util.Date;
import butterknife.BindView;
/**
@ -159,30 +162,34 @@ public class IssueDetailsViewHolder extends BaseViewHolder<TimelineModel> {
}
private void bind(@NonNull Issue issueModel) {
avatar.setUrl(issueModel.getUser().getAvatarUrl(), issueModel.getUser().getLogin());
name.setText(issueModel.getUser().getLogin());
date.setText(ParseDateFormat.getTimeAgo(issueModel.getCreatedAt()));
if (!InputHelper.isEmpty(issueModel.getBodyHtml())) {
HtmlHelper.htmlIntoTextView(comment, issueModel.getBodyHtml());
} else {
comment.setText(R.string.no_description_provided);
}
if (issueModel.getReactions() != null) {
appendEmojies(issueModel.getReactions());
}
setup(issueModel.getUser(), issueModel.getBodyHtml(), issueModel.getReactions());
setupDate(issueModel.getCreatedAt(), issueModel.getUpdatedAt());
}
private void bind(@NonNull PullRequest pullRequest) {
avatar.setUrl(pullRequest.getUser().getAvatarUrl(), pullRequest.getUser().getLogin());
name.setText(pullRequest.getUser().getLogin());
date.setText(ParseDateFormat.getTimeAgo(pullRequest.getCreatedAt()));
if (!InputHelper.isEmpty(pullRequest.getBodyHtml())) {
HtmlHelper.htmlIntoTextView(comment, pullRequest.getBodyHtml());
setup(pullRequest.getUser(), pullRequest.getBodyHtml(), pullRequest.getReactions());
setupDate(pullRequest.getCreatedAt(), pullRequest.getUpdatedAt());
}
private void setup(User user, String description, ReactionsModel reactionsModel) {
avatar.setUrl(user.getAvatarUrl(), user.getLogin(), user.isOrganizationType());
name.setText(user.getLogin());
if (reactionsModel != null) {
appendEmojies(reactionsModel);
}
if (!InputHelper.isEmpty(description)) {
HtmlHelper.htmlIntoTextView(comment, description);
} else {
comment.setText(R.string.no_description_provided);
}
if (pullRequest.getReactions() != null) {
appendEmojies(pullRequest.getReactions());
}
private void setupDate(@NonNull Date createdDate, @NonNull Date updated) {
if (createdDate.before(updated)) {
date.setText(String.format("%s %s", ParseDateFormat.getTimeAgo(updated),
date.getResources().getString(R.string.edited)));
} else {
date.setText(ParseDateFormat.getTimeAgo(createdDate));
}
}

View File

@ -2,7 +2,8 @@ package com.fastaccess.ui.adapter.viewholder
import android.view.View
import com.fastaccess.R
import com.fastaccess.data.dao.TrendingResponse
import com.fastaccess.data.dao.TrendingModel
import com.fastaccess.provider.colors.ColorsProvider
import com.fastaccess.provider.emoji.EmojiParser
import com.fastaccess.ui.widgets.FontTextView
import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter
@ -12,16 +13,17 @@ import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder
* Created by Kosh on 02 Jun 2017, 1:27 PM
*/
open class TrendingViewHolder(itemView: View, adapter: BaseRecyclerAdapter<TrendingResponse,
TrendingViewHolder, OnItemClickListener<TrendingResponse>>) : BaseViewHolder<TrendingResponse>(itemView, adapter) {
open class TrendingViewHolder(itemView: View, adapter: BaseRecyclerAdapter<TrendingModel,
TrendingViewHolder, OnItemClickListener<TrendingModel>>) : BaseViewHolder<TrendingModel>(itemView, adapter) {
val title by lazy { itemView.findViewById(R.id.title) as FontTextView }
val description by lazy { itemView.findViewById(R.id.description) as FontTextView }
val todayStars by lazy { itemView.findViewById(R.id.todayStars) as FontTextView }
val stars by lazy { itemView.findViewById(R.id.stars) as FontTextView }
val fork by lazy { itemView.findViewById(R.id.forks) as FontTextView }
val lang by lazy { itemView.findViewById(R.id.language) as FontTextView }
override fun bind(t: TrendingResponse) {
override fun bind(t: TrendingModel) {
title.text = t.title
if (!t.description.isNullOrEmpty()) {
val descriptionValue: String = EmojiParser.parseToUnicode(t.description)
@ -33,6 +35,12 @@ open class TrendingViewHolder(itemView: View, adapter: BaseRecyclerAdapter<Trend
todayStars.text = t.todayStars
stars.text = t.stars
fork.text = t.forks
lang.text = t.language
if (!t.language.isNullOrEmpty()) {
lang.tintDrawables(ColorsProvider.getColorAsColor(t.language!!, itemView.context))
lang.setTextColor(ColorsProvider.getColorAsColor(t.language, itemView.context))
}
lang.visibility = if (t.language.isNullOrEmpty()) View.GONE else View.VISIBLE
}
}

View File

@ -161,12 +161,7 @@ public abstract class BaseActivity<V extends BaseMvp.FAView, P extends BasePrese
@Override public void showMessage(@NonNull String titleRes, @NonNull String msgRes) {
hideProgress();
if (toast != null) toast.cancel();
Context context;
if (!isFinishing()) {
context = this;
} else {
context = App.getInstance();
}
Context context = App.getInstance(); // WindowManager$BadTokenException
toast = titleRes.equals(context.getString(R.string.error))
? Toasty.error(context, msgRes, Toast.LENGTH_LONG)
: Toasty.info(context, msgRes, Toast.LENGTH_LONG);
@ -186,7 +181,7 @@ public abstract class BaseActivity<V extends BaseMvp.FAView, P extends BasePrese
if (resId != 0) {
msg = getString(resId);
}
if (!isProgressShowing) {
if (!isProgressShowing && !isFinishing()) {
ProgressDialogFragment fragment = (ProgressDialogFragment) AppHelper.getFragmentByTag(getSupportFragmentManager(),
ProgressDialogFragment.TAG);
if (fragment == null) {
@ -207,7 +202,7 @@ public abstract class BaseActivity<V extends BaseMvp.FAView, P extends BasePrese
}
@Override public void onRequireLogin() {
Toasty.warning(this, getString(R.string.unauthorized_user), Toast.LENGTH_LONG).show();
Toasty.warning(App.getInstance(), getString(R.string.unauthorized_user), Toast.LENGTH_LONG).show();
ImageLoader.getInstance().clearDiskCache();
ImageLoader.getInstance().clearMemoryCache();
PrefHelper.clearKey("token");
@ -340,6 +335,13 @@ public abstract class BaseActivity<V extends BaseMvp.FAView, P extends BasePrese
}
}
protected void onSelectTrending() {
if (extraNav != null) {
extraNav.getMenu().findItem(R.id.trending).setCheckable(true);
extraNav.getMenu().findItem(R.id.trending).setChecked(true);
}
}
protected void onOpenOrgsDialog() {
OrgListDialogFragment.newInstance().show(getSupportFragmentManager(), "OrgListDialogFragment");
}
@ -575,7 +577,7 @@ public abstract class BaseActivity<V extends BaseMvp.FAView, P extends BasePrese
if (backPressTimer + 2000 > System.currentTimeMillis()) {
return true;
} else {
Toast.makeText(getBaseContext(), R.string.press_again_to_exit, Toast.LENGTH_SHORT).show();
Toast.makeText(App.getInstance(), R.string.press_again_to_exit, Toast.LENGTH_SHORT).show();
}
backPressTimer = System.currentTimeMillis();
return false;

View File

@ -114,13 +114,9 @@ public abstract class BaseFragment<V extends BaseMvp.FAView, P extends BasePrese
callback.onRequireLogin();
}
@Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) {
@Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) {}
}
@Override public void onDialogDismissed() {
}
@Override public void onDialogDismissed() {}
@Override public void onLogoutPressed() {
callback.onLogoutPressed();

View File

@ -2,7 +2,6 @@ package com.fastaccess.ui.modules.about;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
@ -15,11 +14,14 @@ import com.danielstone.materialaboutlibrary.MaterialAboutActivity;
import com.danielstone.materialaboutlibrary.items.MaterialAboutActionItem;
import com.danielstone.materialaboutlibrary.model.MaterialAboutCard;
import com.danielstone.materialaboutlibrary.model.MaterialAboutList;
import com.fastaccess.BuildConfig;
import com.fastaccess.R;
import com.fastaccess.data.dao.model.Release;
import com.fastaccess.helper.ActivityHelper;
import com.fastaccess.helper.AppHelper;
import com.fastaccess.helper.BundleConstant;
import com.fastaccess.helper.PrefGetter;
import com.fastaccess.ui.modules.changelog.ChangelogBottomSheetDialog;
import com.fastaccess.ui.modules.repos.RepoPagerActivity;
import com.fastaccess.ui.modules.repos.issues.create.CreateIssueActivity;
import com.fastaccess.ui.modules.user.UserPagerActivity;
@ -27,13 +29,16 @@ import com.mikepenz.aboutlibraries.Libs;
import com.mikepenz.aboutlibraries.LibsBuilder;
import es.dmoral.toasty.Toasty;
import io.reactivex.disposables.Disposable;
/**
* Created by danielstone on 12 Mar 2017, 1:57 AM
*/
public class FastHubAboutActivity extends MaterialAboutActivity {
View malRecyclerview;
private View malRecyclerview;
private Disposable disposable;
@Override protected void onCreate(@Nullable Bundle savedInstanceState) {
int themeMode = PrefGetter.getThemeType(getApplicationContext());
@ -48,70 +53,14 @@ public class FastHubAboutActivity extends MaterialAboutActivity {
@Override protected MaterialAboutList getMaterialAboutList(Context context) {
MaterialAboutCard.Builder appCardBuilder = new MaterialAboutCard.Builder();
try {
appCardBuilder.addItem(ConvenienceBuilder.createVersionActionItem(context, ContextCompat.getDrawable(context, R.drawable.ic_issues),
getString(R.string.version), false));
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
appCardBuilder.addItem(ConvenienceBuilder.createRateActionItem(context, ContextCompat.getDrawable(context, R.drawable.ic_star_filled),
getString(R.string.rate_app), null));
appCardBuilder.addItem(new MaterialAboutActionItem.Builder()
.text(R.string.report_issue)
.subText(R.string.report_issue_here)
.icon(ContextCompat.getDrawable(context, R.drawable.ic_bug))
.setOnClickListener(b -> CreateIssueActivity.startForResult(this, CreateIssueActivity.startForResult(this), malRecyclerview))
.build());
appCardBuilder.addItem(new MaterialAboutActionItem.Builder()
.text(R.string.open_source_libs)
.icon(R.drawable.ic_github)
.setOnClickListener(b -> new LibsBuilder()
.withActivityStyle(AppHelper.isNightMode(getResources()) ? Libs.ActivityStyle.DARK : Libs.ActivityStyle.LIGHT)
.withAutoDetect(true)
.withAboutIconShown(true)
.withAboutVersionShown(true)
.start(this))
.build());
buildApp(context, appCardBuilder);
MaterialAboutCard.Builder miscCardBuilder = new MaterialAboutCard.Builder();
buildMisc(context, miscCardBuilder);
MaterialAboutCard.Builder authorCardBuilder = new MaterialAboutCard.Builder();
authorCardBuilder.title(R.string.author);
authorCardBuilder.addItem(new MaterialAboutActionItem.Builder()
.text("Kosh")
.subText("k0shk0sh")
.icon(ContextCompat.getDrawable(context, R.drawable.ic_profile))
.setOnClickListener(b -> UserPagerActivity.startActivity(context, "k0shk0sh"))
.build());
authorCardBuilder.addItem(new MaterialAboutActionItem.Builder()
.text(R.string.fork_github)
.icon(ContextCompat.getDrawable(context, R.drawable.ic_github))
.setOnClickListener(b -> startActivity(RepoPagerActivity.createIntent(this, "FastHub", "k0shk0sh")))
.build());
authorCardBuilder.addItem(ConvenienceBuilder.createEmailItem(context, ContextCompat.getDrawable(context, R.drawable.ic_email),
getString(R.string.send_email), true, getString(R.string.email_address), getString(R.string.question_concerning_fasthub)));
buildAuthor(context, authorCardBuilder);
MaterialAboutCard.Builder logoAuthor = new MaterialAboutCard.Builder();
logoAuthor.title(getString(R.string.logo_designer, "Kevin Aguilar"));
logoAuthor.addItem(new MaterialAboutActionItem.Builder()
.text(R.string.google_plus)
.icon(ContextCompat.getDrawable(context, R.drawable.ic_profile))
.setOnClickListener(b -> ActivityHelper.startCustomTab(this, "https://plus.google.com/+KevinAguilarC"))
.build());
logoAuthor.addItem(new MaterialAboutActionItem.Builder()
.text(R.string.twitter)
.icon(ContextCompat.getDrawable(context, R.drawable.ic_profile))
.setOnClickListener(b -> ActivityHelper.startCustomTab(this, "https://twitter.com/kevttob"))
.build());
logoAuthor.addItem(new MaterialAboutActionItem.Builder()
.text(R.string.website)
.icon(ContextCompat.getDrawable(context, R.drawable.ic_brower))
.setOnClickListener(b -> ActivityHelper.startCustomTab(this, "https://www.221pixels.com/"))
.build());
return new MaterialAboutList(appCardBuilder.build(), authorCardBuilder.build(), logoAuthor.build());
buildLogo(context, logoAuthor);
return new MaterialAboutList(appCardBuilder.build(), miscCardBuilder.build(), authorCardBuilder.build(), logoAuthor.build());
}
@Override protected CharSequence getActivityTitle() {
@ -131,4 +80,96 @@ public class FastHubAboutActivity extends MaterialAboutActivity {
}
return false;//override
}
@Override protected void onDestroy() {
if (disposable != null && !disposable.isDisposed()) {
disposable.dispose();
}
super.onDestroy();
}
private void buildLogo(Context context, MaterialAboutCard.Builder logoAuthor) {
logoAuthor.title(getString(R.string.logo_designer, "Kevin Aguilar"));
logoAuthor.addItem(new MaterialAboutActionItem.Builder()
.text(R.string.google_plus)
.icon(ContextCompat.getDrawable(context, R.drawable.ic_profile))
.setOnClickListener(b -> ActivityHelper.startCustomTab(this, "https://plus.google.com/+KevinAguilarC"))
.build())
.addItem(new MaterialAboutActionItem.Builder()
.text(R.string.twitter)
.icon(ContextCompat.getDrawable(context, R.drawable.ic_profile))
.setOnClickListener(b -> ActivityHelper.startCustomTab(this, "https://twitter.com/kevttob"))
.build())
.addItem(new MaterialAboutActionItem.Builder()
.text(R.string.website)
.icon(ContextCompat.getDrawable(context, R.drawable.ic_brower))
.setOnClickListener(b -> ActivityHelper.startCustomTab(this, "https://www.221pixels.com/"))
.build());
}
private void buildAuthor(Context context, MaterialAboutCard.Builder authorCardBuilder) {
authorCardBuilder.title(R.string.author);
authorCardBuilder.addItem(new MaterialAboutActionItem.Builder()
.text("Kosh Sergani")
.subText("k0shk0sh")
.icon(ContextCompat.getDrawable(context, R.drawable.ic_profile))
.setOnClickListener(b -> UserPagerActivity.startActivity(context, "k0shk0sh"))
.build())
.addItem(new MaterialAboutActionItem.Builder()
.text(R.string.fork_github)
.icon(ContextCompat.getDrawable(context, R.drawable.ic_github))
.setOnClickListener(b -> startActivity(RepoPagerActivity.createIntent(this, "FastHub", "k0shk0sh")))
.build())
.addItem(ConvenienceBuilder.createEmailItem(context, ContextCompat.getDrawable(context, R.drawable.ic_email),
getString(R.string.send_email), true, getString(R.string.email_address), getString(R.string.question_concerning_fasthub)));
}
private void buildMisc(Context context, MaterialAboutCard.Builder miscCardBuilder) {
miscCardBuilder.title(R.string.about)
.addItem(new MaterialAboutActionItem.Builder()
.text(R.string.changelog)
.icon(ContextCompat.getDrawable(context, R.drawable.ic_track_changes))
.setOnClickListener(b -> new ChangelogBottomSheetDialog().show(getSupportFragmentManager(), "ChangelogBottomSheetDialog"))
.build())
.addItem(new MaterialAboutActionItem.Builder()
.text(R.string.join_slack)
.icon(ContextCompat.getDrawable(context, R.drawable.ic_slack))
.setOnClickListener(b -> ActivityHelper.startCustomTab(this, "http://rebrand.ly/fasthub"))
.build())
.addItem(new MaterialAboutActionItem.Builder()
.text(R.string.open_source_libs)
.icon(ContextCompat.getDrawable(context, R.drawable.ic_github))
.setOnClickListener(b -> new LibsBuilder()
.withActivityStyle(AppHelper.isNightMode(getResources()) ? Libs.ActivityStyle.DARK : Libs.ActivityStyle.LIGHT)
.withAutoDetect(true)
.withAboutIconShown(true)
.withAboutVersionShown(true)
.start(this))
.build());
}
private void buildApp(Context context, MaterialAboutCard.Builder appCardBuilder) {
appCardBuilder.addItem(new MaterialAboutActionItem.Builder()
.text(getString(R.string.version))
.icon(ContextCompat.getDrawable(context, R.drawable.ic_update))
.subText(BuildConfig.VERSION_NAME)
.setOnClickListener(b -> disposable = Release.get("FastHub", "k0shk0sh")
.subscribe(releases -> {
if (releases != null && !releases.isEmpty()) {
if (releases.get(0).getTagName().contains(BuildConfig.VERSION_NAME))
Toasty.success(context, getString(R.string.up_to_date)).show();
else
Toasty.warning(context, getString(R.string.new_version)).show();
}
}))
.build())
.addItem(ConvenienceBuilder.createRateActionItem(context, ContextCompat.getDrawable(context, R.drawable.ic_star_filled),
getString(R.string.rate_app), null))
.addItem(new MaterialAboutActionItem.Builder()
.text(R.string.report_issue)
.subText(R.string.report_issue_here)
.icon(ContextCompat.getDrawable(context, R.drawable.ic_bug))
.setOnClickListener(b -> CreateIssueActivity.startForResult(this, CreateIssueActivity.startForResult(this), malRecyclerview))
.build());
}
}

View File

@ -18,6 +18,7 @@ import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.ListView;
import com.evernote.android.state.State;
import com.fastaccess.BuildConfig;
import com.fastaccess.R;
import com.fastaccess.data.dao.EditReviewCommentModel;
@ -46,7 +47,6 @@ import butterknife.OnClick;
import butterknife.OnItemClick;
import butterknife.OnTextChanged;
import es.dmoral.toasty.Toasty;
import com.evernote.android.state.State;
import uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt;
import static android.view.View.GONE;
@ -70,16 +70,15 @@ public class EditorActivity extends BaseActivity<EditorMvp.View, EditorPresenter
@BindView(R.id.sentVia) CheckBox sentVia;
@BindView(R.id.list_divider) View listDivider;
@BindView(R.id.parentView) View parentView;
@State @BundleConstant.ExtraTYpe String extraType;
@BindView(R.id.autocomplete) ListView mention;
@State @BundleConstant.ExtraTYpe String extraType;
@State String itemId;
@State String login;
@State int issueNumber;
@State long commentId = 0;
@State String sha;
@State EditReviewCommentModel reviewComment;
@BindView(R.id.autocomplete)
ListView mention;
@Override protected int layout() {
return R.layout.editor_layout;
@ -239,36 +238,6 @@ public class EditorActivity extends BaseActivity<EditorMvp.View, EditorPresenter
editText.requestFocus();
}
private void onCreate() {
Intent intent = getIntent();
if (intent != null && intent.getExtras() != null) {
Bundle bundle = intent.getExtras();
//noinspection WrongConstant
extraType = bundle.getString(BundleConstant.EXTRA_TYPE);
reviewComment = bundle.getParcelable(BundleConstant.REVIEW_EXTRA);
itemId = bundle.getString(BundleConstant.ID);
login = bundle.getString(BundleConstant.EXTRA_TWO);
if (extraType.equalsIgnoreCase(BundleConstant.ExtraTYpe.EDIT_COMMIT_COMMENT_EXTRA) ||
extraType.equalsIgnoreCase(BundleConstant.ExtraTYpe.NEW_COMMIT_COMMENT_EXTRA)) {
sha = bundle.getString(BundleConstant.EXTRA_THREE);
} else {
issueNumber = bundle.getInt(BundleConstant.EXTRA_THREE);
}
commentId = bundle.getLong(BundleConstant.EXTRA_FOUR);
String textToUpdate = bundle.getString(BundleConstant.EXTRA);
if (!InputHelper.isEmpty(textToUpdate)) {
editText.setText(String.format("%s ", textToUpdate));
editText.setSelection(InputHelper.toString(editText).length());
}
if (bundle.getString("message", "").isEmpty())
replyQuote.setVisibility(GONE);
else {
MarkDownProvider.setMdText(quote, bundle.getString("message", ""));
}
participants = bundle.getStringArrayList("participants");
}
}
@Override public void onSendResultAndFinish(@NonNull Comment commentModel, boolean isNew) {
hideProgress();
Intent intent = new Intent();
@ -307,7 +276,7 @@ public class EditorActivity extends BaseActivity<EditorMvp.View, EditorPresenter
if (item.getItemId() == R.id.submit) {
if (PrefGetter.isSentViaEnabled()) {
String temp = savedText.toString();
if (!temp.contains(sentFromFastHub) && !InputHelper.isEmpty(savedText)) {
if (!temp.contains(sentFromFastHub)) {
savedText = savedText + sentFromFastHub;
}
}
@ -361,6 +330,36 @@ public class EditorActivity extends BaseActivity<EditorMvp.View, EditorPresenter
}
}
private void onCreate() {
Intent intent = getIntent();
if (intent != null && intent.getExtras() != null) {
Bundle bundle = intent.getExtras();
//noinspection WrongConstant
extraType = bundle.getString(BundleConstant.EXTRA_TYPE);
reviewComment = bundle.getParcelable(BundleConstant.REVIEW_EXTRA);
itemId = bundle.getString(BundleConstant.ID);
login = bundle.getString(BundleConstant.EXTRA_TWO);
if (extraType.equalsIgnoreCase(BundleConstant.ExtraTYpe.EDIT_COMMIT_COMMENT_EXTRA) ||
extraType.equalsIgnoreCase(BundleConstant.ExtraTYpe.NEW_COMMIT_COMMENT_EXTRA)) {
sha = bundle.getString(BundleConstant.EXTRA_THREE);
} else {
issueNumber = bundle.getInt(BundleConstant.EXTRA_THREE);
}
commentId = bundle.getLong(BundleConstant.EXTRA_FOUR);
String textToUpdate = bundle.getString(BundleConstant.EXTRA);
if (!InputHelper.isEmpty(textToUpdate)) {
editText.setText(String.format("%s ", textToUpdate));
editText.setSelection(InputHelper.toString(editText).length());
}
if (bundle.getString("message", "").isEmpty())
replyQuote.setVisibility(GONE);
else {
MarkDownProvider.setMdText(quote, bundle.getString("message", ""));
}
participants = bundle.getStringArrayList("participants");
}
}
private void updateMentionList(@NonNull String mentioning) {
if (participants != null) {
ArrayList<String> mentions = new ArrayList<>();

View File

@ -11,7 +11,6 @@ import android.view.View;
import com.fastaccess.R;
import com.fastaccess.data.dao.SimpleUrlsModel;
import com.fastaccess.data.dao.model.Event;
import com.fastaccess.helper.ActivityHelper;
import com.fastaccess.helper.PrefGetter;
import com.fastaccess.provider.rest.loadmore.OnLoadMore;
import com.fastaccess.provider.scheme.SchemeParser;
@ -82,8 +81,7 @@ public class FeedsFragment extends BaseFragment<FeedsMvp.View, FeedsPresenter> i
}
@Override public void showProgress(@StringRes int resId) {
refresh.setRefreshing(true);
refresh.setRefreshing(true);
stateLayout.showProgress();
}
@ -133,45 +131,7 @@ refresh.setRefreshing(true);
}
@Override public void onShowGuide(@NonNull View itemView, @NonNull Event model) {
if (!PrefGetter.isUserIconGuideShowed()) {
final boolean[] dismissed = {false};
/*new MaterialTapTargetPrompt.Builder(getActivity())
.setTarget(itemView.findViewById(R.id.avatarLayout))
.setPrimaryText(R.string.users)
.setSecondaryText(R.string.avatar_click_hint)
.setBackgroundColourAlpha(244)
.setBackgroundColour(ViewHelper.getAccentColor(getContext()))
.setOnHidePromptListener(new MaterialTapTargetPrompt.OnHidePromptListener() {
@Override public void onHidePrompt(MotionEvent event, boolean tappedTarget) {}
@Override public void onHidePromptComplete() {
if (!dismissed[0])
new MaterialTapTargetPrompt.Builder(getActivity())
.setTarget(itemView)
.setPrimaryText(R.string.fork)
.setSecondaryText(R.string.feeds_fork_hint)
.setCaptureTouchEventOutsidePrompt(true)
.setBackgroundColourAlpha(244)
.setBackgroundColour(ViewHelper.getAccentColor(getContext()))
.setOnHidePromptListener(new MaterialTapTargetPrompt.OnHidePromptListener() {
@Override
public void onHidePrompt(MotionEvent motionEvent, boolean b) {
ActivityHelper.hideDismissHints(FeedsFragment.this.getContext());
}
@Override
public void onHidePromptComplete() {
}
})
.show();
ActivityHelper.bringDismissAllToFront(getContext());
}
})
.setCaptureTouchEventOutsidePrompt(true)
.show();*/
ActivityHelper.showDismissHints(getContext(), () -> dismissed[0] = true);
}
if (!PrefGetter.isUserIconGuideShowed()) {}
}
private void showReload() {

View File

@ -6,6 +6,7 @@ import android.content.Intent;
import android.content.res.Resources;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.text.Editable;
import android.view.KeyEvent;
@ -15,6 +16,7 @@ import android.view.inputmethod.EditorInfo;
import android.widget.PopupWindow;
import android.widget.Toast;
import com.evernote.android.state.State;
import com.fastaccess.R;
import com.fastaccess.data.dao.LabelModel;
import com.fastaccess.data.dao.MilestoneModel;
@ -49,7 +51,6 @@ import butterknife.OnClick;
import butterknife.OnEditorAction;
import butterknife.OnTextChanged;
import es.dmoral.toasty.Toasty;
import com.evernote.android.state.State;
/**
* Created by Kosh on 09 Apr 2017, 6:23 PM
@ -174,52 +175,37 @@ public class FilterIssuesActivity extends BaseActivity<FilterIssuesActivityMvp.V
}
@SuppressLint("InflateParams") @OnClick(R.id.labels) public void onLabelsClicked() {
if (hideWindow()) return;
if (labels.getTag() != null) return;
labels.setTag(true);
ViewHolder viewHolder = new ViewHolder(LayoutInflater.from(this).inflate(R.layout.simple_list_dialog, null));
popupWindow = new PopupWindow(this);
popupWindow.setContentView(viewHolder.view);
popupWindow.setOutsideTouchable(true);
popupWindow.setBackgroundDrawable(new ColorDrawable(ViewHelper.getWindowBackground(this)));
popupWindow.setElevation(getResources().getDimension(R.dimen.spacing_normal));
setupPopupWindow(viewHolder);
viewHolder.recycler.setAdapter(getLabelsAdapter());
AnimHelper.revealPopupWindow(popupWindow, labels);
}
@SuppressLint("InflateParams") @OnClick(R.id.milestone) public void onMilestoneClicked() {
if (hideWindow()) return;
if (milestone.getTag() != null) return;
milestone.setTag(true);
ViewHolder viewHolder = new ViewHolder(LayoutInflater.from(this).inflate(R.layout.simple_list_dialog, null));
popupWindow = new PopupWindow(this);
popupWindow.setContentView(viewHolder.view);
popupWindow.setOutsideTouchable(true);
popupWindow.setElevation(getResources().getDimension(R.dimen.spacing_micro));
popupWindow.setBackgroundDrawable(new ColorDrawable(ViewHelper.getWindowBackground(this)));
popupWindow.setElevation(getResources().getDimension(R.dimen.spacing_normal));
setupPopupWindow(viewHolder);
viewHolder.recycler.setAdapter(getMilestonesAdapter());
AnimHelper.revealPopupWindow(popupWindow, milestone);
}
@SuppressLint("InflateParams") @OnClick(R.id.assignee) public void onAssigneeClicked() {
if (hideWindow()) return;
if (assignee.getTag() != null) return;
assignee.setTag(true);
ViewHolder viewHolder = new ViewHolder(LayoutInflater.from(this).inflate(R.layout.simple_list_dialog, null));
popupWindow = new PopupWindow(this);
popupWindow.setContentView(viewHolder.view);
popupWindow.setOutsideTouchable(true);
popupWindow.setElevation(getResources().getDimension(R.dimen.spacing_micro));
popupWindow.setBackgroundDrawable(new ColorDrawable(ViewHelper.getWindowBackground(this)));
popupWindow.setElevation(getResources().getDimension(R.dimen.spacing_normal));
setupPopupWindow(viewHolder);
viewHolder.recycler.setAdapter(getAssigneesAdapter());
AnimHelper.revealPopupWindow(popupWindow, assignee);
}
@SuppressLint("InflateParams") @OnClick(R.id.sort) public void onSortClicked() {
if (hideWindow()) return;
if (sort.getTag() != null) return;
sort.setTag(true);
ViewHolder viewHolder = new ViewHolder(LayoutInflater.from(this).inflate(R.layout.simple_list_dialog, null));
popupWindow = new PopupWindow(this);
popupWindow.setContentView(viewHolder.view);
popupWindow.setOutsideTouchable(true);
popupWindow.setElevation(getResources().getDimension(R.dimen.spacing_micro));
popupWindow.setBackgroundDrawable(new ColorDrawable(ViewHelper.getWindowBackground(this)));
popupWindow.setElevation(getResources().getDimension(R.dimen.spacing_normal));
setupPopupWindow(viewHolder);
ArrayList<String> lists = new ArrayList<>();
Collections.addAll(lists, getResources().getStringArray(R.array.sort_prs_issues));
lists.add(CommentsHelper.getThumbsUp());
@ -301,12 +287,23 @@ public class FilterIssuesActivity extends BaseActivity<FilterIssuesActivityMvp.V
}
}
private boolean hideWindow() {
if (popupWindow != null && popupWindow.isShowing()) {
popupWindow.dismiss();
return true;
private void setupPopupWindow(@NonNull ViewHolder viewHolder) {
if (popupWindow == null) {
popupWindow = new PopupWindow(this);
popupWindow.setElevation(getResources().getDimension(R.dimen.spacing_micro));
popupWindow.setOutsideTouchable(true);
popupWindow.setBackgroundDrawable(new ColorDrawable(ViewHelper.getWindowBackground(this)));
popupWindow.setElevation(getResources().getDimension(R.dimen.spacing_normal));
popupWindow.setOnDismissListener(() -> new Handler().postDelayed(() -> {
//hacky way to dismiss on re-selecting tab.
if (assignee == null || milestone == null || sort == null || labels == null) return;
assignee.setTag(null);
milestone.setTag(null);
sort.setTag(null);
labels.setTag(null);
}, 100));
}
return false;
popupWindow.setContentView(viewHolder.view);
}
private void onSearch() {
@ -470,7 +467,7 @@ public class FilterIssuesActivity extends BaseActivity<FilterIssuesActivityMvp.V
onSearch();
}
private void appendSort(String item) {
private void appendSort(String item) {
dismissPopup();
appendIfEmpty();
Resources resources = getResources();

Some files were not shown because too many files have changed in this diff Show More