From 495b1bd49835070ca43a523831caee0f70079604 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Wed, 19 Jul 2017 00:28:56 -0700 Subject: Dev - minor updates (#73) * Add lint * Add new libs * Update libs and add friends tab * Aggressively hide nonrecent posts * Update dependencies * Add php to most recents * Add full size image downloader * Fix css cleaner --- .travis.yml | 2 +- app/build.gradle | 9 ++ .../assets/css/components/round_icons.compact.css | 2 +- .../main/assets/css/components/round_icons.scss | 2 +- .../pitchedapps/frost/activities/AboutActivity.kt | 20 +--- .../pitchedapps/frost/activities/ImageActivity.kt | 26 +----- .../pitchedapps/frost/activities/MainActivity.kt | 3 +- .../frost/activities/SettingsActivity.kt | 2 +- .../kotlin/com/pitchedapps/frost/facebook/FbTab.kt | 28 +++--- .../com/pitchedapps/frost/injectors/CssAssets.kt | 1 + .../com/pitchedapps/frost/injectors/CssHider.kt | 4 +- .../com/pitchedapps/frost/injectors/JsInjector.kt | 2 +- .../frost/services/FrostNotifications.kt | 2 + .../kotlin/com/pitchedapps/frost/utils/iab/IAB.kt | 2 +- .../pitchedapps/frost/web/FrostWebViewClients.kt | 13 ++- app/src/main/res/layout/item_keyword.xml | 1 - app/src/main/res/layout/web_context_menu.xml | 27 ------ app/src/main/res/transition/web_context_enter.xml | 23 ----- app/src/main/res/xml/changelog.xml | 101 -------------------- app/src/main/res/xml/frost_changelog.xml | 102 +++++++++++++++++++++ build.gradle | 2 +- docs/Changelog.md | 7 ++ gradle.properties | 4 +- 23 files changed, 167 insertions(+), 218 deletions(-) delete mode 100644 app/src/main/res/layout/web_context_menu.xml delete mode 100644 app/src/main/res/transition/web_context_enter.xml delete mode 100644 app/src/main/res/xml/changelog.xml create mode 100644 app/src/main/res/xml/frost_changelog.xml diff --git a/.travis.yml b/.travis.yml index 9066b498..b12aa29f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ script: - cd $TRAVIS_BUILD_DIR/ - printf "Starting script\n" - ./gradlew --quiet androidGitVersion -- if [[ "$TRAVIS_BRANCH" == "master" ]]; then ./gradlew publishRelease; else ./gradlew testReleaseUnitTest assembleReleaseTest; fi +- if [[ "$TRAVIS_BRANCH" == "master" ]]; then ./gradlew lintRelease publishRelease; else ./gradlew lintReleaseTest testReleaseUnitTest assembleReleaseTest; fi notifications: email: false slack: diff --git a/app/build.gradle b/app/build.gradle index 8729ed69..a433c6f2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -43,6 +43,15 @@ android { } } + lintOptions { + warningsAsErrors true + disable 'LogNotTimber', + 'TrustAllX509TrustManager', + 'UnusedResources', + 'ContentDescription', + 'RtlSymmetry' + } + signingConfigs { def releaseProps = new Properties() diff --git a/app/src/main/assets/css/components/round_icons.compact.css b/app/src/main/assets/css/components/round_icons.compact.css index 0ae132de..76ff52cc 100644 --- a/app/src/main/assets/css/components/round_icons.compact.css +++ b/app/src/main/assets/css/components/round_icons.compact.css @@ -1 +1 @@ -#threadlist_rows i.img:not(.profpic), i.img.profpic:not(._1_0m), ._42b6._42b6._42b6, ._5i9c.img, img._2cu2, i.img.l, [id*=threadlist] i.img:not(._1_0m) { border-radius: 50%; } +#threadlist_rows i.img:not(.profpic), i.img.profpic:not(._1_0m), ._42b6._42b6._42b6, ._5i9c.img, img._2cu2, i.img.l, [id*=threadlist] i.img:not(._1_0m) { border-radius: 50% !important; } diff --git a/app/src/main/assets/css/components/round_icons.scss b/app/src/main/assets/css/components/round_icons.scss index 58d20670..ad89b112 100644 --- a/app/src/main/assets/css/components/round_icons.scss +++ b/app/src/main/assets/css/components/round_icons.scss @@ -1,3 +1,3 @@ #threadlist_rows i.img:not(.profpic), i.img.profpic:not(._1_0m), ._42b6._42b6._42b6, ._5i9c.img, img._2cu2, i.img.l, [id*=threadlist] i.img:not(._1_0m) { - border-radius: 50%; + border-radius: 50% !important; } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt index 63ad8bae..b21cc3ab 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt @@ -40,6 +40,8 @@ class AboutActivity : AboutActivityBase(null, { val include = arrayOf( "AboutLibraries", "AndroidIconics", + "androidslidinguppanel", + "Crashlytics", "dbflow", "fastadapter", "glide", @@ -47,24 +49,10 @@ class AboutActivity : AboutActivityBase(null, { "kau", "kotterknife", "materialdialogs", - "materialdrawer" + "materialdrawer", + "subsamplingscaleimageview" ) - /* - * These are great libraries, but either aren't used directly or are too common to be listed - * Give more emphasis on the unique libs! - */ - val exclude = arrayOf( - "GoogleMaterialDesignIcons", - "intellijannotations", - "MaterialDesignIconicIcons", - "MaterialDesignIcons", - "materialize", - "appcompat_v7", - "design", - "recyclerview_v7", - "support_v4" - ) val l = libs.prepareLibraries(this, include, null, false, true) // l.forEach { KL.d("Lib ${it.definedName}") } return l diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt index 487f3a9d..0b8c1a56 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt @@ -166,11 +166,9 @@ class ImageActivity : AppCompatActivity() { } } - @Suppress("SIMPLE_DATE_FORMAT") @Throws(IOException::class) private fun createImageFile(): File { // Create an image file name - @SuppressLint("SimpleDateFormat") val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date()) val imageFileName = "Frost_" + timeStamp + "_" val storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES) @@ -264,27 +262,9 @@ internal enum class FabStates(val iicon: IIcon, val iconColor: Int = Prefs.iconC * If it's in view, give it some animations */ fun update(fab: FloatingActionButton) { - if (!fab.isShown) { - fab.setIcon(iicon, color = iconColor) - fab.backgroundTintList = ColorStateList.valueOf(backgroundTint) - } else { - var switched = false - ValueAnimator.ofFloat(1.0f, 0.0f, 1.0f).apply { - duration = 500L - addUpdateListener { - val x = it.animatedValue as Float - val scale = x * 0.3f + 0.7f - fab.scaleX = scale - fab.scaleY = scale - fab.imageAlpha = (x * 255).toInt() - if (it.animatedFraction > 0.5f && !switched) { - switched = true - fab.setIcon(iicon, color = iconColor) - fab.backgroundTintList = ColorStateList.valueOf(backgroundTint) - } - } - start() - } + fab.transition { + setIcon(iicon, color = iconColor) + backgroundTintList = ColorStateList.valueOf(backgroundTint) } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt index 1227fd6b..8ca18385 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt @@ -110,7 +110,7 @@ class MainActivity : BaseActivity(), SearchWebView.SearchContract, if (BuildConfig.VERSION_CODE > Prefs.versionCode) { Prefs.versionCode = BuildConfig.VERSION_CODE if (!BuildConfig.DEBUG) { - showChangelog(R.xml.changelog, Prefs.textColor) { theme() } + showChangelog(R.xml.frost_changelog, Prefs.textColor) { theme() } frostAnswersCustom("Version") { putCustomAttribute("Version code", BuildConfig.VERSION_CODE) putCustomAttribute("Version name", BuildConfig.VERSION_NAME) @@ -288,6 +288,7 @@ class MainActivity : BaseActivity(), SearchWebView.SearchContract, divider() primaryFrostItem(FbTab.PHOTOS) primaryFrostItem(FbTab.GROUPS) + primaryFrostItem(FbTab.FRIENDS) primaryFrostItem(FbTab.PAGES) divider() primaryFrostItem(FbTab.EVENTS) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt index b3b3bd7c..c40a705f 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt @@ -132,7 +132,7 @@ class SettingsActivity : KPrefActivity(), IabBroadcastReceiver.IabBroadcastListe items(Support.values().map { string(it.title) }) itemsCallback { _, _, which, _ -> Support.values()[which].sendEmail(this@SettingsActivity) } } - R.id.action_changelog -> showChangelog(R.xml.changelog, Prefs.textColor) { theme() } + R.id.action_changelog -> showChangelog(R.xml.frost_changelog, Prefs.textColor) { theme() } else -> return super.onOptionsItemSelected(item) } return true diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbTab.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbTab.kt index 7e7a8f42..d1f0b046 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbTab.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbTab.kt @@ -11,26 +11,26 @@ import com.pitchedapps.frost.web.FrostWebViewClientMenu import com.pitchedapps.frost.web.FrostWebViewCore enum class FbTab(@StringRes val titleId: Int, val icon: IIcon, relativeUrl: String, val webClient: ((webCore: FrostWebViewCore) -> FrostWebViewClient)? = null) { - FEED(R.string.feed, CommunityMaterial.Icon.cmd_newspaper, ""), - FEED_MOST_RECENT(R.string.most_recent, GoogleMaterial.Icon.gmd_history, "?sk=h_chr"), - FEED_TOP_STORIES(R.string.top_stories, GoogleMaterial.Icon.gmd_star, "?sk=h_nor"), - PROFILE(R.string.profile, CommunityMaterial.Icon.cmd_account, "me"), - EVENTS(R.string.events, GoogleMaterial.Icon.gmd_event_note, "events/upcoming"), - FRIENDS(R.string.friends, GoogleMaterial.Icon.gmd_people, "friends/center/requests"), - MESSAGES(R.string.messages, MaterialDesignIconic.Icon.gmi_comments, "messages"), - NOTIFICATIONS(R.string.notifications, MaterialDesignIconic.Icon.gmi_globe, "notifications"), ACTIVITY_LOG(R.string.activity_log, GoogleMaterial.Icon.gmd_list, "me/allactivity"), - PAGES(R.string.pages, GoogleMaterial.Icon.gmd_flag, "pages"), - GROUPS(R.string.groups, GoogleMaterial.Icon.gmd_group, "groups"), - SAVED(R.string.saved, GoogleMaterial.Icon.gmd_bookmark, "saved"), BIRTHDAYS(R.string.birthdays, GoogleMaterial.Icon.gmd_cake, "events/birthdays"), CHAT(R.string.chat, GoogleMaterial.Icon.gmd_chat, "buddylist"), - PHOTOS(R.string.photos, GoogleMaterial.Icon.gmd_photo, "me/photos"), - SETTINGS(R.string.settings, GoogleMaterial.Icon.gmd_settings, "settings"), + EVENTS(R.string.events, GoogleMaterial.Icon.gmd_event_note, "events/upcoming"), + FEED(R.string.feed, CommunityMaterial.Icon.cmd_newspaper, ""), + FEED_MOST_RECENT(R.string.most_recent, GoogleMaterial.Icon.gmd_history, "home.php?sk=h_chr"), + FEED_TOP_STORIES(R.string.top_stories, GoogleMaterial.Icon.gmd_star, "home.php?sk=h_nor"), + FRIENDS(R.string.friends, GoogleMaterial.Icon.gmd_person_add, "friends/center/requests"), + GROUPS(R.string.groups, GoogleMaterial.Icon.gmd_group, "groups"), MENU(R.string.menu, GoogleMaterial.Icon.gmd_menu, "settings", { FrostWebViewClientMenu(it) }), + MESSAGES(R.string.messages, MaterialDesignIconic.Icon.gmi_comments, "messages"), NOTES(R.string.notes, CommunityMaterial.Icon.cmd_note, "notes"), + NOTIFICATIONS(R.string.notifications, MaterialDesignIconic.Icon.gmi_globe, "notifications"), ON_THIS_DAY(R.string.on_this_day, GoogleMaterial.Icon.gmd_today, "onthisday"), - SEARCH(R.string.search_menu_title, GoogleMaterial.Icon.gmd_search, "search") + PAGES(R.string.pages, GoogleMaterial.Icon.gmd_flag, "pages"), + PHOTOS(R.string.photos, GoogleMaterial.Icon.gmd_photo, "me/photos"), + PROFILE(R.string.profile, CommunityMaterial.Icon.cmd_account, "me"), + SAVED(R.string.saved, GoogleMaterial.Icon.gmd_bookmark, "saved"), + SEARCH(R.string.search_menu_title, GoogleMaterial.Icon.gmd_search, "search"), + SETTINGS(R.string.settings, GoogleMaterial.Icon.gmd_settings, "settings"), ; val url = "$FB_URL_BASE$relativeUrl" diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt index 35acdcb3..2f2050cc 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt @@ -3,6 +3,7 @@ package com.pitchedapps.frost.injectors import android.graphics.Color import android.webkit.WebView import ca.allanwang.kau.utils.* +import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs /** diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt index cb33e527..e8a3128d 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt @@ -1,7 +1,6 @@ package com.pitchedapps.frost.injectors import android.webkit.WebView -import com.pitchedapps.frost.utils.L /** * Created by Allan Wang on 2017-05-31. @@ -16,7 +15,8 @@ enum class CssHider(vararg val items: String) : InjectorContract { "article[data-store*=sponsor]" ), PEOPLE_YOU_MAY_KNOW("article._d2r"), - MESSENGER("._s15", "[data-testid=info_panel]", "js_i") + MESSENGER("._s15", "[data-testid=info_panel]", "js_i"), + NON_RECENT("article:not([data-store*=actor_name])") ; val injector: JsInjector by lazy { JsBuilder().css("${items.joinToString(separator = ",")}{display:none!important}").build() } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt index 1f35464b..1b7dad1c 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt @@ -25,7 +25,7 @@ class JsBuilder { override fun toString(): String { val builder = StringBuilder().append("!function(){") if (css.isNotBlank()) { - val cssMin = css.replace(Regex("\\s+"), "") + val cssMin = css.replace(Regex("[\\r\\n\\t\\f\\v]\\s*"), "") builder.append("var a=document.createElement('style');a.innerHTML='$cssMin';document.head.appendChild(a);") } if (js.isNotBlank()) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt index 737b86ab..a24e4778 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt @@ -35,6 +35,8 @@ val Context.frostNotification: NotificationCompat.Builder color = color(R.color.frost_notification_accent) } +@Suppress("DEPRECATION") +//The update feature is for Android O and seems to still be in beta fun Notification.frostConfig() = apply { if (Prefs.notificationVibrate) defaults = defaults or Notification.DEFAULT_VIBRATE if (Prefs.notificationSound) defaults = defaults or Notification.DEFAULT_SOUND diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IAB.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IAB.kt index 669b2c9e..445f3ddf 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IAB.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IAB.kt @@ -134,7 +134,7 @@ fun SettingsActivity.restorePurchases() { finishRestore(restore, false) } getInventory(false, true, reset) { - inv, helper -> + inv, _ -> val proSku = inv.hasPurchase(FROST_PRO) Prefs.pro = proSku L.d("Play Store Restore found: ${Prefs.pro}") diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt index 3e6ddd06..89eef258 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt @@ -79,6 +79,7 @@ open class FrostWebViewClient(val webCore: FrostWebViewCore) : BaseWebViewClient internal fun injectAndFinish() { L.d("Page finished reveal") webCore.jsInject(CssHider.HEADER, + CssHider.NON_RECENT.maybe(webCore.url.contains("?sk=h_chr")), Prefs.themeInjector, callback = { refreshObservable.onNext(false) @@ -104,15 +105,25 @@ open class FrostWebViewClient(val webCore: FrostWebViewCore) : BaseWebViewClient * returns true to override the url */ private fun launchRequest(request: WebResourceRequest): Boolean { - L.d("Launching ${request.url}") + L.d("Launching Url", request.url.toString()) webCore.context.launchWebOverlay(request.url.toString()) return true } + private fun launchImage(request: WebResourceRequest, text: String? = null): Boolean { + L.d("Launching Image", request.url.toString()) + webCore.context.launchImageActivity(request.url.toString(), text) + if (webCore.canGoBack()) webCore.goBack() + return true + } + override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean { L.i("Url Loading ${request.url}") val path = request.url.path ?: return super.shouldOverrideUrlLoading(view, request) + L.v("Url Loading Path $path") if (path.startsWith("/composer/")) return launchRequest(request) + if (request.url.toString().contains("scontent-sea1-1.xx.fbcdn.net") && (path.endsWith(".jpg") || path.endsWith(".png"))) + return launchImage(request) return super.shouldOverrideUrlLoading(view, request) } diff --git a/app/src/main/res/layout/item_keyword.xml b/app/src/main/res/layout/item_keyword.xml index 2c24997f..3894fc7e 100644 --- a/app/src/main/res/layout/item_keyword.xml +++ b/app/src/main/res/layout/item_keyword.xml @@ -21,5 +21,4 @@ android:background="?android:attr/selectableItemBackground" android:scaleType="center" /> - \ No newline at end of file diff --git a/app/src/main/res/layout/web_context_menu.xml b/app/src/main/res/layout/web_context_menu.xml deleted file mode 100644 index d5f80c0f..00000000 --- a/app/src/main/res/layout/web_context_menu.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/transition/web_context_enter.xml b/app/src/main/res/transition/web_context_enter.xml deleted file mode 100644 index 213ace90..00000000 --- a/app/src/main/res/transition/web_context_enter.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/xml/changelog.xml b/app/src/main/res/xml/changelog.xml deleted file mode 100644 index cb1f5f64..00000000 --- a/app/src/main/res/xml/changelog.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/xml/frost_changelog.xml b/app/src/main/res/xml/frost_changelog.xml new file mode 100644 index 00000000..f608f70a --- /dev/null +++ b/app/src/main/res/xml/frost_changelog.xml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 9d775f6a..db334854 100644 --- a/build.gradle +++ b/build.gradle @@ -19,7 +19,7 @@ task clean(type: Delete) { } task generateChangelogMd() { - def parsedProjectXml = (new XmlParser()).parse("$project.rootDir/app/src/main/res/xml/changelog.xml") + def parsedProjectXml = (new XmlParser()).parse("$project.rootDir/app/src/main/res/xml/frost_changelog.xml") def sw = new StringWriter() sw.append("# Changelog\n") parsedProjectXml.depthFirst().each { diff --git a/docs/Changelog.md b/docs/Changelog.md index 0345bae0..ae525797 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -1,9 +1,16 @@ # Changelog ## Beta Updates +* Add friend request tab in nav bar +* Aggressively filter nonrecent posts in recents mode +* Add download option for full sized images + +## v1.4 * Update IAB helper * Create image viewing and downloading; long press any image! * Start filtering out unnecessary loads +* Fix notification duplicates +* Fix long pressing album images ## v1.3 * Create toggle for notifications only from primary account diff --git a/gradle.properties b/gradle.properties index 8ae68213..96a0843d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,10 +17,10 @@ MIN_SDK=21 TARGET_SDK=26 BUILD_TOOLS=26.0.0 -KAU=eddaded +KAU=v2.1 KOTLIN=1.1.3-2 CRASHLYTICS=2.6.8 -DBFLOW=4.0.4 +DBFLOW=4.0.5 GLIDE=4.0.0-RC1 IICON_COMMUNITY=1.9.32.2 IICON_MATERIAL=2.2.0.3 -- cgit v1.2.3