diff options
Diffstat (limited to 'app/src/main/kotlin/com/pitchedapps')
9 files changed, 202 insertions, 42 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt index ab3ffd09..b8feef0f 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt @@ -15,6 +15,7 @@ import android.support.v4.view.ViewPager import android.support.v7.widget.Toolbar import android.view.Menu import android.view.MenuItem +import ca.allanwang.kau.changelog.showChangelog import ca.allanwang.kau.utils.* import co.zsmb.materialdrawerkt.builders.Builder import co.zsmb.materialdrawerkt.builders.accountHeader @@ -36,7 +37,6 @@ import com.pitchedapps.frost.facebook.FbCookie.switchUser import com.pitchedapps.frost.facebook.FbTab import com.pitchedapps.frost.facebook.PROFILE_PICTURE_URL import com.pitchedapps.frost.fragments.WebFragment -import com.pitchedapps.frost.injectors.CssAssets import com.pitchedapps.frost.utils.* import com.pitchedapps.frost.views.BadgedIcon import io.reactivex.android.schedulers.AndroidSchedulers @@ -61,14 +61,20 @@ class MainActivity : BaseActivity() { companion object { const val FRAGMENT_REFRESH = 99 + /* + * Possible responses from the SettingsActivity + * after the configurations have changed + */ const val REQUEST_RESTART = 90909 + const val REQUEST_REFRESH = 80808 + const val REQUEST_NAV = 10101 } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (BuildConfig.VERSION_CODE > Prefs.versionCode) { Prefs.versionCode = BuildConfig.VERSION_CODE - showChangelog(R.xml.changelog, { theme() }) + showChangelog(R.xml.changelog, Prefs.textColor) { theme() } } setContentView(R.layout.activity_main) setSupportActionBar(toolbar) @@ -129,12 +135,12 @@ class MainActivity : BaseActivity() { }) headerBadgeObservable.throttleFirst(15, TimeUnit.SECONDS).subscribeOn(Schedulers.newThread()) .map { Jsoup.parse(it) } - .filter { it.select("[data-sigil=\"count\"]").size >= 0 } //ensure headers exist + .filter { it.select("[data-sigil=count]").size >= 0 } //ensure headers exist .map { - val feed = it.select("[data-sigil*=\"feed\"] [data-sigil=\"count\"]") - val requests = it.select("[data-sigil*=\"requests\"] [data-sigil=\"count\"]") - val messages = it.select("[data-sigil*=\"messages\"] [data-sigil=\"count\"]") - val notifications = it.select("[data-sigil*=\"notifications\"] [data-sigil=\"count\"]") + val feed = it.select("[data-sigil*=feed] [data-sigil=count]") + val requests = it.select("[data-sigil*=requests] [data-sigil=count]") + val messages = it.select("[data-sigil*=messages] [data-sigil=count]") + val notifications = it.select("[data-sigil*=notifications] [data-sigil=count]") return@map arrayOf(feed, requests, messages, notifications).map { it?.getOrNull(0)?.ownText() } } .observeOn(AndroidSchedulers.mainThread()) @@ -303,8 +309,10 @@ class MainActivity : BaseActivity() { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) - if (resultCode == REQUEST_RESTART) { - restart() + when (requestCode) { + REQUEST_RESTART -> restart() + REQUEST_REFRESH -> webFragmentObservable.onNext(FRAGMENT_REFRESH) + REQUEST_NAV -> frostNavigationBar() } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/SettingsActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/SettingsActivity.kt index 79e65621..cf20aa0f 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/SettingsActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/SettingsActivity.kt @@ -3,17 +3,22 @@ package com.pitchedapps.frost import android.os.Bundle import android.view.Menu import android.view.MenuItem +import ca.allanwang.kau.changelog.showChangelog import ca.allanwang.kau.email.sendEmail import ca.allanwang.kau.kpref.CoreAttributeContract import ca.allanwang.kau.kpref.KPrefActivity import ca.allanwang.kau.kpref.KPrefAdapterBuilder import ca.allanwang.kau.kpref.items.KPrefColorPicker +import ca.allanwang.kau.kpref.items.KPrefItemBase import ca.allanwang.kau.utils.* import ca.allanwang.kau.views.RippleCanvas +import com.mikepenz.community_material_typeface_library.CommunityMaterial import com.mikepenz.google_material_typeface_library.GoogleMaterial +import com.pitchedapps.frost.facebook.FeedSort import com.pitchedapps.frost.injectors.CssAssets import com.pitchedapps.frost.utils.* -import com.pitchedapps.frost.utils.iab.openPlayPurchase +import com.pitchedapps.frost.utils.iab.IS_FROST_PRO +import com.pitchedapps.frost.utils.iab.openPlayProPurchase import com.pitchedapps.frost.views.Keywords @@ -32,27 +37,39 @@ class SettingsActivity : KPrefActivity() { descRes = R.string.appearance_desc iicon = GoogleMaterial.Icon.gmd_palette } + + subItems(R.string.newsfeed, subPrefsFeed()) { + descRes = R.string.newsfeed_desc + iicon = CommunityMaterial.Icon.cmd_newspaper + } + subItems(R.string.notifications, subPrefsNotifications()) { descRes = R.string.notifications_desc iicon = GoogleMaterial.Icon.gmd_notifications } + if (BuildConfig.DEBUG) { + checkbox(R.string.custom_pro, { Prefs.debugPro }, { Prefs.debugPro = it }) + } } fun subPrefsAppearance(): KPrefAdapterBuilder.() -> Unit = { - header(R.string.base_customization) + header(R.string.theme_customization) text(R.string.theme, { Prefs.theme }, { Prefs.theme = it }) { onClick = { _, _, item -> this@SettingsActivity.materialDialogThemed { title(R.string.theme) - items(Theme.values().map { this@SettingsActivity.string(it.textRes) }) + items(Theme.values() + .map { if (it == Theme.CUSTOM && !IS_FROST_PRO) R.string.custom_pro else it.textRes } + .map { this@SettingsActivity.string(it) }) itemsCallbackSingleChoice(item.pref, { _, _, which, text -> if (item.pref != which) { - if (which == Theme.CUSTOM.ordinal) { - this@SettingsActivity.openPlayPurchase("asdf", 9) + if (which == Theme.CUSTOM.ordinal && !IS_FROST_PRO) { + this@SettingsActivity.openPlayProPurchase(9) + return@itemsCallbackSingleChoice true } item.pref = which shouldRestartMain() @@ -68,8 +85,7 @@ class SettingsActivity : KPrefActivity() { true } textGetter = { - this@SettingsActivity.string(if (it == Theme.CUSTOM.ordinal) - R.string.kau_custom else Theme(it).textRes) + this@SettingsActivity.string(Theme(it).textRes) } } @@ -83,21 +99,33 @@ class SettingsActivity : KPrefActivity() { CssAssets.CUSTOM.injector = null } - colorPicker(R.string.text_color, { Prefs.customTextColor }, { Prefs.customTextColor = it; reload(); invalidateCustomTheme() }) { + colorPicker(R.string.text_color, { Prefs.customTextColor }, { + Prefs.customTextColor = it + reload() + invalidateCustomTheme() + shouldRestartMain() + }) { dependsOnCustom() allowCustomAlpha = false } - colorPicker(R.string.background_color, { Prefs.customBackgroundColor }, - { Prefs.customBackgroundColor = it; bgCanvas.ripple(it, duration = 500L); invalidateCustomTheme() }) { + colorPicker(R.string.background_color, { Prefs.customBackgroundColor }, { + Prefs.customBackgroundColor = it + bgCanvas.ripple(it, duration = 500L) + invalidateCustomTheme() + setFrostTheme(true) + shouldRestartMain() + }) { dependsOnCustom() allowCustomAlpha = true } colorPicker(R.string.header_color, { Prefs.customHeaderColor }, { Prefs.customHeaderColor = it - this@SettingsActivity.navigationBarColor = it + if (Prefs.tintNavBar) this@SettingsActivity.frostNavigationBar() toolbarCanvas.ripple(it, RippleCanvas.MIDDLE, RippleCanvas.END, duration = 500L) + reload() + shouldRestartMain() }) { dependsOnCustom() allowCustomAlpha = true @@ -106,32 +134,82 @@ class SettingsActivity : KPrefActivity() { colorPicker(R.string.icon_color, { Prefs.customIconColor }, { Prefs.customIconColor = it invalidateOptionsMenu() + shouldRestartMain() }) { dependsOnCustom() allowCustomAlpha = false } - checkbox(R.string.rounded_icons, { Prefs.showRoundedIcons }, { Prefs.showRoundedIcons = it }) + header(R.string.global_customization) + + checkbox(R.string.rounded_icons, { Prefs.showRoundedIcons }, { + Prefs.showRoundedIcons = it + setResult(MainActivity.REQUEST_REFRESH) + }) { + descRes = R.string.rounded_icons_desc + } checkbox(R.string.fancy_animations, { Prefs.animate }, { Prefs.animate = it; animate = it }) { descRes = R.string.fancy_animations_desc } - header(R.string.feed_customization) + checkbox(R.string.tint_nav, { Prefs.tintNavBar }, { + Prefs.tintNavBar = it + this@SettingsActivity.frostNavigationBar() + setResult(MainActivity.REQUEST_NAV) + }) { + descRes = R.string.tint_nav_desc + } + } + + fun KPrefItemBase.BaseContract<*>.dependsOnPro() { + onDisabledClick = { _, _, _ -> openPlayProPurchase(0); true } + enabler = { IS_FROST_PRO } + } - checkbox(R.string.suggested_friends, { Prefs.showSuggestedFriends }, { Prefs.showSuggestedFriends = it }) { + fun subPrefsFeed(): KPrefAdapterBuilder.() -> Unit = { + + text(R.string.newsfeed_sort, { Prefs.feedSort }, { Prefs.feedSort = it }) { + descRes = R.string.newsfeed_sort_desc + onClick = { + _, _, item -> + this@SettingsActivity.materialDialogThemed { + title(R.string.newsfeed_sort) + items(FeedSort.values().map { this@SettingsActivity.string(it.textRes) }) + itemsCallbackSingleChoice(item.pref, { + _, _, which, text -> + if (item.pref != which) { + item.pref = which + shouldRestartMain() + } + true + }) + } + true + } + textGetter = { string(FeedSort(it).textRes) } + } + + checkbox(R.string.suggested_friends, { Prefs.showSuggestedFriends }, { + Prefs.showSuggestedFriends = it + setResult(MainActivity.REQUEST_REFRESH) + }) { descRes = R.string.suggested_friends_desc + dependsOnPro() } - checkbox(R.string.facebook_ads, { Prefs.showFacebookAds }, { Prefs.showFacebookAds = it }) { + checkbox(R.string.facebook_ads, { Prefs.showFacebookAds }, { + Prefs.showFacebookAds = it + setResult(MainActivity.REQUEST_REFRESH) + }) { descRes = R.string.facebook_ads_desc + dependsOnPro() } - } fun subPrefsNotifications(): KPrefAdapterBuilder.() -> Unit = { - text(R.string.notification_frequency, { Prefs.notificationFreq }, { Prefs.notificationFreq = it; reloadByTitle(R.string.notification_frequency) }) { + text(R.string.notification_frequency, { Prefs.notificationFreq }, { Prefs.notificationFreq = it }) { val options = longArrayOf(-1, 15, 30, 60, 120, 180, 300, 1440, 2880) val texts = options.map { this@SettingsActivity.minuteToText(it) } onClick = { @@ -140,7 +218,7 @@ class SettingsActivity : KPrefActivity() { title(R.string.notification_frequency) items(texts) itemsCallbackSingleChoice(options.indexOf(item.pref), { - _, _, which, text -> + _, _, which, _ -> item.pref = options[which] this@SettingsActivity.scheduleNotifications(item.pref) true @@ -151,7 +229,7 @@ class SettingsActivity : KPrefActivity() { textGetter = { this@SettingsActivity.minuteToText(it) } } - text<String?>(R.string.notification_keywords, { null }, { }) { + plainText(R.string.notification_keywords) { descRes = R.string.notification_keywords_desc onClick = { _, _, _ -> @@ -184,7 +262,7 @@ class SettingsActivity : KPrefActivity() { else bgCanvas.set(Prefs.bgColor) if (animate) toolbarCanvas.ripple(Prefs.headerColor, RippleCanvas.MIDDLE, RippleCanvas.END) else toolbarCanvas.set(Prefs.headerColor) - this.navigationBarColor = Prefs.headerColor + frostNavigationBar() } override fun onBackPressed() { @@ -208,7 +286,7 @@ class SettingsActivity : KPrefActivity() { R.id.action_email -> sendEmail(R.string.dev_email, R.string.frost_feedback) { addItem("Random Frost ID", Prefs.frostId) } - R.id.action_changelog -> showChangelog(R.xml.changelog, { theme() }) + R.id.action_changelog -> showChangelog(R.xml.changelog, Prefs.textColor) { theme() } else -> return super.onOptionsItemSelected(item) } return true diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FeedSort.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FeedSort.kt new file mode 100644 index 00000000..f3073f6d --- /dev/null +++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FeedSort.kt @@ -0,0 +1,18 @@ +package com.pitchedapps.frost.facebook + +import android.support.annotation.StringRes +import com.pitchedapps.frost.R + +/** + * Created by Allan Wang on 2017-06-23. + */ +enum class FeedSort(@StringRes val textRes: Int) { + DEFAULT(R.string.kau_default), + MOST_RECENT(R.string.most_recent), + TOP(R.string.top_stories); + + companion object { + val values = values() //save one instance + operator fun invoke(index: Int) = values[index] + } +}
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt index dfc3eaad..cd15c2c3 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt @@ -9,6 +9,8 @@ import android.view.ViewGroup import ca.allanwang.kau.utils.withBundle import com.pitchedapps.frost.MainActivity import com.pitchedapps.frost.facebook.FbTab +import com.pitchedapps.frost.facebook.FeedSort +import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.web.FrostWebView import com.pitchedapps.frost.web.FrostWebViewCore import io.reactivex.android.schedulers.AndroidSchedulers @@ -29,7 +31,15 @@ class WebFragment : Fragment() { operator fun invoke(data: FbTab, position: Int) = WebFragment().withBundle { putString(ARG_URL, data.url) putInt(ARG_POSITION, position) - putSerializable(ARG_URL_ENUM, data) + putSerializable(ARG_URL_ENUM, when (data) { + //If is feed, check if sorting method is specified + FbTab.FEED -> when (FeedSort(Prefs.feedSort)) { + FeedSort.DEFAULT -> data + FeedSort.MOST_RECENT -> FbTab.FEED_MOST_RECENT + FeedSort.TOP -> FbTab.FEED_TOP_STORIES + } + else -> data + }) } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt index ab86724e..9b41d454 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt @@ -6,6 +6,7 @@ import ca.allanwang.kau.kpref.StringSet import ca.allanwang.kau.kpref.kpref import ca.allanwang.kau.utils.isColorVisibleOn import ca.allanwang.kau.utils.lazyResettable +import com.pitchedapps.frost.facebook.FeedSort import com.pitchedapps.frost.injectors.InjectorContract /** @@ -23,11 +24,11 @@ object Prefs : KPref() { var theme: Int by kpref("theme", 0, postSetter = { _: Int -> loader.invalidate() }) - var customTextColor: Int by kpref("color_text", Color.BLACK) + var customTextColor: Int by kpref("color_text", Color.WHITE) - var customBackgroundColor: Int by kpref("color_bg", 0xfffafafa.toInt()) + var customBackgroundColor: Int by kpref("color_bg", 0xff37474f.toInt()) - var customHeaderColor: Int by kpref("color_header", 0xff3b5998.toInt()) + var customHeaderColor: Int by kpref("color_header", 0xff039be5.toInt()) var customIconColor: Int by kpref("color_icons", Color.WHITE) @@ -69,6 +70,10 @@ object Prefs : KPref() { val frostId: String get() = "${installDate}-${identifier}" + var tintNavBar: Boolean by kpref("tint_nav_bar", true) + + var feedSort: Int by kpref("feed_sort", FeedSort.DEFAULT.ordinal) + var showRoundedIcons: Boolean by kpref("rounded_icons", true) var showSuggestedFriends: Boolean by kpref("suggested_friends_feed", true) @@ -81,4 +86,8 @@ object Prefs : KPref() { //check if this is the first time launching the web overlay; show snackbar if true var firstWebOverlay: Boolean by kpref("first_web_overlay", true) + + var previouslyPro: Boolean by kpref("previously_pro", false) + + var debugPro: Boolean by kpref("debug_pro", false) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Theme.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Theme.kt index 7535eaa2..b4162a66 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Theme.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Theme.kt @@ -1,6 +1,7 @@ package com.pitchedapps.frost.utils import android.graphics.Color +import android.support.annotation.StringRes import com.pitchedapps.frost.R import com.pitchedapps.frost.injectors.CssAssets import com.pitchedapps.frost.injectors.InjectorContract @@ -9,7 +10,7 @@ import com.pitchedapps.frost.injectors.JsActions /** * Created by Allan Wang on 2017-06-14. */ -enum class Theme(val textRes: Int, val injector: InjectorContract, +enum class Theme(@StringRes val textRes: Int, val injector: InjectorContract, private val textColorGetter: () -> Int, private val backgroundColorGetter: () -> Int, private val headerColorGetter: () -> Int, private val iconColorGetter: () -> Int) { DEFAULT(R.string.kau_default, JsActions.EMPTY, { Color.BLACK }, { 0xfffafafa.toInt() }, { 0xff3b5998.toInt() }, { Color.WHITE }), diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt index 9322af3f..3fe33475 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt @@ -163,4 +163,8 @@ fun View.frostSnackbar(@StringRes text: Int, builder: Snackbar.() -> Unit = {}) } show() } +} + +fun Activity.frostNavigationBar() { + navigationBarColor = if (Prefs.tintNavBar) Prefs.headerColor else Color.BLACK }
\ No newline at end of file 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 007611c5..11fa1c4b 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 @@ -7,10 +7,7 @@ import ca.allanwang.kau.utils.startPlayStoreLink import com.crashlytics.android.answers.PurchaseEvent import com.pitchedapps.frost.BuildConfig import com.pitchedapps.frost.R -import com.pitchedapps.frost.utils.L -import com.pitchedapps.frost.utils.frostAnswers -import com.pitchedapps.frost.utils.frostAnswersCustom -import com.pitchedapps.frost.utils.materialDialogThemed +import com.pitchedapps.frost.utils.* import org.jetbrains.anko.doAsync /** @@ -38,8 +35,10 @@ object IAB { } } -val Context.isFrostPro: Boolean - get() = BuildConfig.DEBUG || isFromGooglePlay +private const val FROST_PRO = "frost_pro" + +val IS_FROST_PRO: Boolean + get() = (BuildConfig.DEBUG && Prefs.debugPro) || (IAB.helper?.queryInventory()?.getSkuDetails(FROST_PRO) != null) private fun Context.checkFromPlay(): Boolean { val isPlay = isFromGooglePlay @@ -53,7 +52,7 @@ private fun Context.checkFromPlay(): Boolean { return isPlay } -fun Activity.openPlayProPurchase(code: Int) = openPlayPurchase("frost_pro", code) +fun Activity.openPlayProPurchase(code: Int) = openPlayPurchase(FROST_PRO, code) fun Activity.openPlayPurchase(key: String, code: Int) { if (!checkFromPlay()) return diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/Key.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/Key.kt new file mode 100644 index 00000000..a21d8670 --- /dev/null +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/Key.kt @@ -0,0 +1,33 @@ +package com.pitchedapps.frost.utils.iab + +/** + * Created by Allan Wang on 2017-06-23. + * + * NOTE + * + * Since this is an open source project and all other components are essentially public, + * I have decided to add the keys here too; + * they can be reverse engineered relatively easily since they are constants anyways. + * This is the public billing key from the play store + */ +private const val play_key_1 = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgyTZS" +private const val play_key_2 = "K9Bd3ALpr9KJUsVGczP9CcPelWkdnJfNrrzu1EztJyrHRsGQ4" +private const val play_key_3 = "QVWY9NZwc6Nrk9qdJlEdr8AJAxJ+JiwUqsj3/TxxUYm/G7q8Z" +private const val play_key_4 = "7zo8jSkYZyzqwoAl2PDx2kleI4sZLkhCRLyE6dGQEZQmvJ6kk" +private const val play_key_5 = "W12Gz3FagAM5luRGsoWZj40pJItUrGJA9euMWq4rMhVZv4mVk" +private const val play_key_6 = "KFJB9/vhF/XGz7txpYlFxMESzXuKsbEDKmKCHzvySLq8Ki4N9" +private const val play_key_7 = "DzbgUiw+VzA2KpSVp66JH3GEU8egO8i9SvAWeCPikuolooRVh" +private const val play_key_8 = "jwfBV7gDxZztoLuvmQU6kXvCwRnRa+mkfUnBKKLkH1QIDAQAB" + +internal val PUBLIC_BILLING_KEY: String by lazy { + StringBuilder() + .append(play_key_1) + .append(play_key_2) + .append(play_key_3) + .append(play_key_4) + .append(play_key_5) + .append(play_key_6) + .append(play_key_7) + .append(play_key_8) + .toString() +}
\ No newline at end of file |