From d36dfe98a52ced46c5106b28304ae5d245180a7f Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Wed, 21 Mar 2018 01:28:31 -0400 Subject: Feature/bugsnag (#807) * Add bugsnag * Remove crashlytics * Remove pro features and iab * Make analytics opt in * Clean settings activity * Clean settings activity 2 --- .../main/kotlin/com/pitchedapps/frost/FrostApp.kt | 11 +- .../pitchedapps/frost/activities/AboutActivity.kt | 2 +- .../frost/activities/BaseMainActivity.kt | 26 +-- .../pitchedapps/frost/activities/ImageActivity.kt | 4 +- .../pitchedapps/frost/activities/LoginActivity.kt | 9 +- .../frost/activities/SettingsActivity.kt | 30 +--- .../com/pitchedapps/frost/dbflow/CookiesDb.kt | 4 +- .../pitchedapps/frost/fragments/FragmentBase.kt | 2 +- .../frost/services/FrostNotifications.kt | 4 +- .../frost/services/NotificationService.kt | 6 +- .../com/pitchedapps/frost/settings/Appearance.kt | 13 +- .../kotlin/com/pitchedapps/frost/settings/Feed.kt | 5 - .../main/kotlin/com/pitchedapps/frost/utils/L.kt | 6 +- .../kotlin/com/pitchedapps/frost/utils/Prefs.kt | 12 +- .../kotlin/com/pitchedapps/frost/utils/Utils.kt | 30 +--- .../com/pitchedapps/frost/utils/iab/IABDialogs.kt | 95 ----------- .../com/pitchedapps/frost/utils/iab/IabBinder.kt | 188 --------------------- .../kotlin/com/pitchedapps/frost/utils/iab/Key.kt | 33 ---- .../com/pitchedapps/frost/web/DebugWebView.kt | 5 +- .../pitchedapps/frost/web/FrostWebViewClients.kt | 7 +- 20 files changed, 43 insertions(+), 449 deletions(-) delete mode 100644 app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABDialogs.kt delete mode 100644 app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IabBinder.kt delete mode 100644 app/src/main/kotlin/com/pitchedapps/frost/utils/iab/Key.kt (limited to 'app/src/main/kotlin') diff --git a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt index 36b51753..16e23d53 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt @@ -7,10 +7,9 @@ import android.net.Uri import android.os.Bundle import android.widget.ImageView import ca.allanwang.kau.logging.KL +import com.bugsnag.android.Bugsnag import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.signature.ApplicationVersionSignature -import com.crashlytics.android.Crashlytics -import com.crashlytics.android.answers.Answers import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader import com.mikepenz.materialdrawer.util.DrawerImageLoader import com.pitchedapps.frost.dbflow.CookiesDb @@ -28,7 +27,6 @@ import com.raizlabs.android.dbflow.config.DatabaseConfig import com.raizlabs.android.dbflow.config.FlowConfig import com.raizlabs.android.dbflow.config.FlowManager import com.raizlabs.android.dbflow.runtime.ContentResolverNotifier -import io.fabric.sdk.android.Fabric import io.reactivex.plugins.RxJavaPlugins import java.net.SocketTimeoutException import java.util.* @@ -63,8 +61,11 @@ class FrostApp : Application() { // if (LeakCanary.isInAnalyzerProcess(this)) return // refWatcher = LeakCanary.install(this) if (!BuildConfig.DEBUG) { - Fabric.with(this, Crashlytics(), Answers()) - Crashlytics.setUserIdentifier(Prefs.frostId) + Bugsnag.init(this) + Bugsnag.setAutoCaptureSessions(true) + Bugsnag.getClient().setUserId(Prefs.frostId) + +// setUser("userId", "user@email.com", "User Name") } KL.shouldLog = { BuildConfig.DEBUG } Prefs.verboseLogging = false 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 691f050e..8e6677f9 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt @@ -136,7 +136,7 @@ class AboutActivity : AboutActivityBase(null, { val c = itemView.context val size = c.dimenPixelSize(R.dimen.kau_avatar_bounds) images = arrayOf Unit>>( - GoogleMaterial.Icon.gmd_star to { c.startPlayStoreLink(R.string.play_store_package_id) }, +// GoogleMaterial.Icon.gmd_star to { c.startPlayStoreLink(R.string.play_store_package_id) }, CommunityMaterial.Icon.cmd_reddit to { c.startLink(R.string.reddit_url) }, CommunityMaterial.Icon.cmd_github_circle to { c.startLink(R.string.github_url) }, CommunityMaterial.Icon.cmd_xda to { c.startLink(R.string.xda_url) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt index 809e8a56..8b584112 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt @@ -38,7 +38,6 @@ import co.zsmb.materialdrawerkt.draweritems.badgeable.secondaryItem import co.zsmb.materialdrawerkt.draweritems.divider import co.zsmb.materialdrawerkt.draweritems.profile.profile import co.zsmb.materialdrawerkt.draweritems.profile.profileSetting -import com.crashlytics.android.answers.ContentViewEvent import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.typeface.IIcon @@ -54,7 +53,6 @@ import com.pitchedapps.frost.dbflow.TAB_COUNT import com.pitchedapps.frost.dbflow.loadFbCookie import com.pitchedapps.frost.dbflow.loadFbTabs import com.pitchedapps.frost.enums.MainActivityLayout -import com.pitchedapps.frost.enums.Theme import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.facebook.FbItem import com.pitchedapps.frost.facebook.PROFILE_PICTURE_URL @@ -63,9 +61,6 @@ import com.pitchedapps.frost.fragments.WebFragment import com.pitchedapps.frost.parsers.FrostSearch import com.pitchedapps.frost.parsers.SearchParser import com.pitchedapps.frost.utils.* -import com.pitchedapps.frost.utils.iab.FrostBilling -import com.pitchedapps.frost.utils.iab.IS_FROST_PRO -import com.pitchedapps.frost.utils.iab.IabMain import com.pitchedapps.frost.views.BadgedIcon import com.pitchedapps.frost.views.FrostVideoViewer import com.pitchedapps.frost.views.FrostViewPager @@ -77,8 +72,7 @@ import com.pitchedapps.frost.views.FrostViewPager */ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, FileChooserContract by FileChooserDelegate(), - VideoViewHolder, SearchViewHolder, - FrostBilling by IabMain() { + VideoViewHolder, SearchViewHolder { protected lateinit var adapter: SectionsPagerAdapter override val frameWrapper: FrameLayout by bindView(R.id.frame_wrapper) @@ -115,13 +109,12 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, onNestedCreate(savedInstanceState) L.i { "Main finished loading UI in ${System.currentTimeMillis() - start} ms" } controlWebview = WebView(this) - onCreateBilling() if (BuildConfig.VERSION_CODE > Prefs.versionCode) { Prefs.prevVersionCode = Prefs.versionCode Prefs.versionCode = BuildConfig.VERSION_CODE if (!BuildConfig.DEBUG) { frostChangelog() - frostAnswersCustom("Version", + frostEvent("Version", "Version code" to BuildConfig.VERSION_CODE, "Prev version code" to Prefs.prevVersionCode, "Version name" to BuildConfig.VERSION_NAME, @@ -283,11 +276,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, selectedColor = 0x00000001.toLong() identifier = item.titleId.toLong() onClick { _ -> - frostAnswers { - logContentView(ContentViewEvent() - .putContentName(item.name) - .putContentType("drawer_item")) - } + frostEvent("Drawer Tab", "name" to item.name) launchWebOverlay(item.url) false } @@ -419,16 +408,7 @@ abstract class BaseMainActivity : BaseActivity(), MainActivityContract, super.onPause() } - override fun onStart() { - //validate some pro features - if (!IS_FROST_PRO) { - if (Prefs.theme == Theme.CUSTOM.ordinal) Prefs.theme = Theme.DEFAULT.ordinal - } - super.onStart() - } - override fun onDestroy() { - onDestroyBilling() controlWebview?.destroy() super.onDestroy() } 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 1bc3334f..e9426beb 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt @@ -121,7 +121,7 @@ class ImageActivity : KauBaseActivity() { photo.setOnImageEventListener(object : SubsamplingScaleImageView.DefaultOnImageEventListener() { override fun onImageLoadError(e: Exception?) { errorRef = e - e.logFrostAnswers("Image load error") + e.logFrostEvent("Image load error") L.e { "Failed to load image $imageUrl" } tempFile?.delete() fabAction = FabStates.ERROR @@ -307,7 +307,7 @@ internal enum class FabStates(val iicon: IIcon, val iconColor: Int = Prefs.iconC activity.startActivity(intent) } catch (e: Exception) { activity.errorRef = e - e.logFrostAnswers("Image share failed") + e.logFrostEvent("Image share failed") activity.frostSnackbar(R.string.image_share_failed) } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt index aa2e5871..9afca21e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt @@ -15,7 +15,6 @@ import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.engine.GlideException import com.bumptech.glide.request.RequestListener import com.bumptech.glide.request.target.Target -import com.crashlytics.android.answers.LoginEvent import com.pitchedapps.frost.R import com.pitchedapps.frost.dbflow.CookieModel import com.pitchedapps.frost.dbflow.fetchUsername @@ -90,11 +89,7 @@ class LoginActivity : BaseActivity() { } textview.text = String.format(getString(R.string.welcome), name) textview.fadeIn() - frostAnswers { - logLogin(LoginEvent() - .putMethod("frost_browser") - .putSuccess(true)) - } + frostEvent("Login" , "success" to true ) /* * The user may have logged into an account that is already in the database * We will let the db handle duplicates and load it now after the new account has been saved @@ -123,7 +118,7 @@ class LoginActivity : BaseActivity() { } override fun onLoadFailed(e: GlideException?, model: Any?, target: Target?, isFirstResource: Boolean): Boolean { - e.logFrostAnswers("Profile loading exception") + e.logFrostEvent("Profile loading exception") profileSubject.onSuccess(false) return false } 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 8d4e521f..97d82884 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt @@ -11,25 +11,20 @@ import android.view.MenuItem import ca.allanwang.kau.kpref.activity.CoreAttributeContract import ca.allanwang.kau.kpref.activity.KPrefActivity import ca.allanwang.kau.kpref.activity.KPrefAdapterBuilder -import ca.allanwang.kau.kpref.activity.items.KPrefItemBase import ca.allanwang.kau.ui.views.RippleCanvas import ca.allanwang.kau.utils.* import com.mikepenz.community_material_typeface_library.CommunityMaterial import com.mikepenz.google_material_typeface_library.GoogleMaterial -import com.pitchedapps.frost.BuildConfig import com.pitchedapps.frost.R import com.pitchedapps.frost.enums.Support import com.pitchedapps.frost.settings.* import com.pitchedapps.frost.utils.* -import com.pitchedapps.frost.utils.iab.FrostBilling -import com.pitchedapps.frost.utils.iab.IS_FROST_PRO -import com.pitchedapps.frost.utils.iab.IabSettings /** * Created by Allan Wang on 2017-06-06. */ -class SettingsActivity : KPrefActivity(), FrostBilling by IabSettings() { +class SettingsActivity : KPrefActivity() { var resultFlag = Activity.RESULT_CANCELED @@ -56,8 +51,6 @@ class SettingsActivity : KPrefActivity(), FrostBilling by IabSettings() { return } } - if (!onActivityResultBilling(requestCode, resultCode, data)) - super.onActivityResult(requestCode, resultCode, data) reloadList() } @@ -125,12 +118,7 @@ class SettingsActivity : KPrefActivity(), FrostBilling by IabSettings() { iicon = CommunityMaterial.Icon.cmd_flask_outline } - plainText(R.string.get_pro) { - descRes = R.string.get_pro_desc - iicon = GoogleMaterial.Icon.gmd_star - visible = { !IS_FROST_PRO } - onClick = { restorePurchases() } - } + // todo add donation? plainText(R.string.about_frost) { descRes = R.string.about_frost_desc @@ -159,14 +147,6 @@ class SettingsActivity : KPrefActivity(), FrostBilling by IabSettings() { visible = { Prefs.debugSettings } } - if (BuildConfig.DEBUG) { - checkbox(R.string.custom_pro, { Prefs.debugPro }, { Prefs.debugPro = it }) - } - } - - fun KPrefItemBase.BaseContract<*>.dependsOnPro() { - onDisabledClick = { purchasePro() } - enabler = { IS_FROST_PRO } } fun shouldRestartMain() { @@ -179,7 +159,6 @@ class SettingsActivity : KPrefActivity(), FrostBilling by IabSettings() { super.onCreate(savedInstanceState) animate = Prefs.animate themeExterior(false) - onCreateBilling() } fun themeExterior(animate: Boolean = true) { @@ -222,9 +201,4 @@ class SettingsActivity : KPrefActivity(), FrostBilling by IabSettings() { fun setFrostResult(flag: Int) { resultFlag = resultFlag or flag } - - override fun onDestroy() { - onDestroyBilling() - super.onDestroy() - } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/dbflow/CookiesDb.kt b/app/src/main/kotlin/com/pitchedapps/frost/dbflow/CookiesDb.kt index e98020d4..69cf32b7 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/dbflow/CookiesDb.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/dbflow/CookiesDb.kt @@ -6,7 +6,7 @@ import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork import com.pitchedapps.frost.facebook.FbItem import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.frostJsoup -import com.pitchedapps.frost.utils.logFrostAnswers +import com.pitchedapps.frost.utils.logFrostEvent import com.raizlabs.android.dbflow.annotation.ConflictAction import com.raizlabs.android.dbflow.annotation.Database import com.raizlabs.android.dbflow.annotation.PrimaryKey @@ -76,7 +76,7 @@ inline fun CookieModel.fetchUsername(crossinline callback: (String) -> Unit) { L.d { "Fetch username found" } } catch (e: Exception) { if (e !is UnknownHostException) - e.logFrostAnswers("Fetch username failed") + e.logFrostEvent("Fetch username failed") } finally { if (result.isBlank() && (name?.isNotBlank() == true)) { callback(name!!) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt index a644e966..cf48893c 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentBase.kt @@ -55,7 +55,7 @@ abstract class BaseFragment : Fragment(), FragmentContract, DynamicUiContract { if (value || this is WebFragment) return arguments!!.putBoolean(ARG_VALID, value) L.e { "Invalidating position $position" } - frostAnswersCustom("Native Fallback", + frostEvent("Native Fallback", "Item" to baseEnum.name) (context as MainActivityContract).reloadFragment(this) } 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 30c94744..ab61b37d 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt @@ -36,7 +36,7 @@ import com.pitchedapps.frost.parsers.ParseNotification import com.pitchedapps.frost.utils.ARG_USER_ID import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs -import com.pitchedapps.frost.utils.frostAnswersCustom +import com.pitchedapps.frost.utils.frostEvent import java.util.* /** @@ -190,7 +190,7 @@ enum class NotificationType( if (newLatestEpoch > prevLatestEpoch) putTime(prevNotifTime, newLatestEpoch).save() L.d { "Notif $name new epoch ${getTime(lastNotificationTime(userId))}" } - frostAnswersCustom("Notifications", "Type" to name, "Count" to notifs.size) + frostEvent("Notifications", "Type" to name, "Count" to notifs.size) if (notifs.size > 1) summaryNotification(context, userId, notifs.size).notify(context) val ringtone = ringtone() diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt index 6ba968e7..22477eab 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt @@ -10,7 +10,7 @@ import com.pitchedapps.frost.dbflow.CookieModel import com.pitchedapps.frost.dbflow.loadFbCookiesSync import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs -import com.pitchedapps.frost.utils.frostAnswersCustom +import com.pitchedapps.frost.utils.frostEvent import org.jetbrains.anko.doAsync import java.util.concurrent.Future @@ -31,7 +31,7 @@ class NotificationService : JobService() { override fun onStopJob(params: JobParameters?): Boolean { val time = System.currentTimeMillis() - startTime L.d { "Notification service has finished abruptly in $time ms" } - frostAnswersCustom("NotificationTime", + frostEvent("NotificationTime", "Type" to "Service force stop", "IM Included" to Prefs.notificationsInstantMessages, "Duration" to time) @@ -43,7 +43,7 @@ class NotificationService : JobService() { fun finish(params: JobParameters?) { val time = System.currentTimeMillis() - startTime L.i { "Notification service has finished in $time ms" } - frostAnswersCustom("NotificationTime", + frostEvent("NotificationTime", "Type" to "Service", "IM Included" to Prefs.notificationsInstantMessages, "Duration" to time) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt index eeeca01f..314590e2 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt @@ -11,7 +11,6 @@ import com.pitchedapps.frost.enums.MainActivityLayout import com.pitchedapps.frost.enums.Theme import com.pitchedapps.frost.injectors.CssAssets import com.pitchedapps.frost.utils.* -import com.pitchedapps.frost.utils.iab.IS_FROST_PRO import com.pitchedapps.frost.views.KPrefTextSeekbar /** @@ -25,22 +24,16 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = { onClick = { materialDialogThemed { title(R.string.theme) - items(Theme.values() - .map { if (it == Theme.CUSTOM && !IS_FROST_PRO) R.string.custom_pro else it.textRes } - .map { string(it) }) + items(Theme.values().map { string(it.textRes) }) itemsCallbackSingleChoice(item.pref) { _, _, which, _ -> if (item.pref != which) { - if (which == Theme.CUSTOM.ordinal && !IS_FROST_PRO) { - purchasePro() - return@itemsCallbackSingleChoice true - } item.pref = which shouldRestartMain() reload() setFrostTheme(true) themeExterior() invalidateOptionsMenu() - frostAnswersCustom("Theme", "Count" to Theme(which).name) + frostEvent("Theme", "Count" to Theme(which).name) } true } @@ -125,7 +118,7 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = { if (item.pref != which) { item.pref = which shouldRestartMain() - frostAnswersCustom("Main Layout", "Type" to MainActivityLayout(which).name) + frostEvent("Main Layout", "Type" to MainActivityLayout(which).name) } true } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt index 78898eeb..5de68e21 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt @@ -46,14 +46,11 @@ fun SettingsActivity.getFeedPrefs(): KPrefAdapterBuilder.() -> Unit = { descRes = R.string.composer_desc } - header(R.string.pro_features) - checkbox(R.string.suggested_friends, Prefs::showSuggestedFriends, { Prefs.showSuggestedFriends = it setFrostResult(REQUEST_REFRESH) }) { descRes = R.string.suggested_friends_desc - dependsOnPro() } checkbox(R.string.suggested_groups, Prefs::showSuggestedGroups, { @@ -61,7 +58,6 @@ fun SettingsActivity.getFeedPrefs(): KPrefAdapterBuilder.() -> Unit = { setFrostResult(REQUEST_REFRESH) }) { descRes = R.string.suggested_groups_desc - dependsOnPro() } checkbox(R.string.facebook_ads, Prefs::showFacebookAds, { @@ -69,6 +65,5 @@ fun SettingsActivity.getFeedPrefs(): KPrefAdapterBuilder.() -> Unit = { setFrostResult(REQUEST_REFRESH) }) { descRes = R.string.facebook_ads_desc - dependsOnPro() } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/L.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/L.kt index a108745c..4f31f5f5 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/L.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/L.kt @@ -2,7 +2,7 @@ package com.pitchedapps.frost.utils import android.util.Log import ca.allanwang.kau.logging.KauLogger -import com.crashlytics.android.Crashlytics +import com.bugsnag.android.Bugsnag import com.pitchedapps.frost.BuildConfig @@ -34,9 +34,9 @@ object L : KauLogger("Frost", { super.logImpl(priority, message, t) else { if (message != null) - Crashlytics.log(priority, tag, message) + Bugsnag.leaveBreadcrumb(message) if (t != null) - Crashlytics.logException(t) + Bugsnag.notify(t) } } 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 26d7894e..95a5f39b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt @@ -135,19 +135,9 @@ object Prefs : KPref() { var enablePip: Boolean by kpref("enable_pip", true) - /** - * Cache like value to determine if user has or had pro - * In most cases, [com.pitchedapps.frost.utils.iab.IS_FROST_PRO] should be looked at instead - * This has been renamed to pro for short, but keep in mind that it only reflects the value - * of when it was previously verified - */ - var pro: Boolean by kpref("previously_pro", false) - - var debugPro: Boolean by kpref("debug_pro", false) - var verboseLogging: Boolean by kpref("verbose_logging", false) - var analytics: Boolean by kpref("analytics", true) + var analytics: Boolean by kpref("analytics", false) var overlayEnabled: Boolean by kpref("overlay_enabled", true) 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 d73f29e9..b1b129fb 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt @@ -23,15 +23,12 @@ import ca.allanwang.kau.mediapicker.createPrivateMediaFile import ca.allanwang.kau.utils.* import ca.allanwang.kau.xml.showChangelog import com.afollestad.materialdialogs.MaterialDialog -import com.crashlytics.android.answers.Answers -import com.crashlytics.android.answers.CustomEvent import com.pitchedapps.frost.BuildConfig import com.pitchedapps.frost.R import com.pitchedapps.frost.activities.* import com.pitchedapps.frost.dbflow.CookieModel import com.pitchedapps.frost.facebook.* import com.pitchedapps.frost.facebook.FbUrlFormatter.Companion.VIDEO_REDIRECT -import com.pitchedapps.frost.utils.iab.IS_FROST_PRO import org.apache.commons.text.StringEscapeUtils import org.jsoup.Jsoup import org.jsoup.nodes.Element @@ -175,29 +172,19 @@ inline fun Activity.setFrostColors(builder: ActivityThemeUtils.() -> Unit) { themer.theme(this) } -fun frostAnswers(action: Answers.() -> Unit) { - if (BuildConfig.DEBUG || !Prefs.analytics) return - Answers.getInstance().action() -} -fun frostAnswersCustom(name: String, vararg events: Pair) { - frostAnswers { - logCustom(CustomEvent("Frost $name").apply { - events.forEach { (key, value) -> - if (value is Number) putCustomAttribute(key, value) - else putCustomAttribute(key, value.toString()) - } - }) - } +fun frostEvent(name: String, vararg events: Pair) { + // todo bind + L.v { "Event: $name ${events.joinToString(", ")}" } } /** * Helper method to quietly keep track of throwable issues */ -fun Throwable?.logFrostAnswers(text: String) { +fun Throwable?.logFrostEvent(text: String) { val msg = if (this == null) text else "$text: $message" L.e { msg } - frostAnswersCustom("Errors", "text" to text, "message" to (this?.message ?: "NA")) + frostEvent("Errors", "text" to text, "message" to (this?.message ?: "NA")) } fun Activity.frostSnackbar(@StringRes text: Int, builder: Snackbar.() -> Unit = {}) = snackbar(text, Snackbar.LENGTH_LONG, frostSnackbar(builder)) @@ -291,10 +278,6 @@ inline val String?.isExplicitIntent fun Context.frostChangelog() = showChangelog(R.xml.frost_changelog, Prefs.textColor) { theme() - if (System.currentTimeMillis() - Prefs.installDate > 2592000000) { //show after 1 month - neutralText(R.string.kau_rate) - onNeutral { _, _ -> startPlayStoreLink(R.string.play_store_package_id) } - } } fun Context.frostUriFromFile(file: File): Uri = @@ -311,7 +294,8 @@ inline fun Context.sendFrostEmail(subjectId: String, crossinline builder: EmailB fun EmailBuilder.addFrostDetails() { addItem("Prev version", Prefs.prevVersionCode.toString()) - val proTag = if (IS_FROST_PRO) "TY" else "FP" + val proTag = "FO" +// if (IS_FROST_PRO) "TY" else "FP" addItem("Random Frost ID", "${Prefs.frostId}-$proTag") addItem("Locale", Locale.getDefault().displayName) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABDialogs.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABDialogs.kt deleted file mode 100644 index 15d707a9..00000000 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABDialogs.kt +++ /dev/null @@ -1,95 +0,0 @@ -package com.pitchedapps.frost.utils.iab - -import android.app.Activity -import ca.allanwang.kau.utils.restart -import ca.allanwang.kau.utils.startLink -import ca.allanwang.kau.utils.startPlayStoreLink -import ca.allanwang.kau.utils.string -import com.crashlytics.android.answers.PurchaseEvent -import com.pitchedapps.frost.R -import com.pitchedapps.frost.activities.SettingsActivity -import com.pitchedapps.frost.utils.* - -/** - * Created by Allan Wang on 2017-06-30. - */ - -private fun playStoreLog(text: String) { - L.e(Throwable(text)) { "IAB Play Store Exception" } -} - -/** - * Properly restart an activity - */ -private fun Activity.playRestart() { - if (this is SettingsActivity) { - setResult(REQUEST_RESTART) - finish() - } else restart() -} - -fun Activity?.playStoreNoLongerPro() { - Prefs.pro = false - L.d { "IAB No longer pro" } - frostAnswers { - logPurchase(PurchaseEvent() - .putCustomAttribute("result", "no longer pro") - .putSuccess(false)) - } - if (this == null) return - materialDialogThemed { - title(R.string.uh_oh) - content(R.string.play_store_not_pro) - positiveText(R.string.reload) - dismissListener { - this@playStoreNoLongerPro.playRestart() - } - } -} - -fun Activity?.playStoreFoundPro() { - Prefs.pro = true - L.d { "Found pro" } - if (this == null) return - materialDialogThemed { - title(R.string.found_pro) - content(R.string.found_pro_desc) - positiveText(R.string.reload) - dismissListener { - this@playStoreFoundPro.playRestart() - } - } -} - -fun Activity.playStorePurchaseUnsupported() { - L.d { "Play store not found" } - materialDialogThemed { - title(R.string.uh_oh) - content(R.string.play_store_unsupported) - negativeText(R.string.kau_close) - positiveText(R.string.kau_play_store) - neutralText(R.string.paypal) - onPositive { _, _ -> startPlayStoreLink(R.string.play_store_package_id) } - onNeutral { _, _ -> startLink(string(R.string.dev_paypal)) } - } -} - -fun Activity.playStorePurchasedSuccessfully(key: String) { - L.d { "Play store purchased $key successfully" } - materialDialogThemed { - title(R.string.play_thank_you) - content(R.string.play_purchased_pro) - positiveText(R.string.kau_ok) - neutralText(R.string.kau_rate) - onNeutral { _, _ -> startPlayStoreLink(R.string.play_store_package_id) } - } -} - -fun Activity.purchaseRestored() { - L.d { "Purchase restored" } - materialDialogThemed { - title(R.string.play_thank_you) - content(R.string.purchases_restored_with_pro) - positiveText(R.string.kau_ok) - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IabBinder.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IabBinder.kt deleted file mode 100644 index 568127a2..00000000 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IabBinder.kt +++ /dev/null @@ -1,188 +0,0 @@ -package com.pitchedapps.frost.utils.iab - -import android.app.Activity -import android.content.Intent -import com.anjlab.android.iab.v3.BillingProcessor -import com.anjlab.android.iab.v3.TransactionDetails -import com.crashlytics.android.answers.PurchaseEvent -import com.pitchedapps.frost.BuildConfig -import com.pitchedapps.frost.utils.L -import com.pitchedapps.frost.utils.Prefs -import com.pitchedapps.frost.utils.frostAnswers -import com.pitchedapps.frost.utils.logFrostAnswers -import org.jetbrains.anko.doAsync -import org.jetbrains.anko.onComplete -import org.jetbrains.anko.uiThread -import java.lang.ref.WeakReference -import java.math.BigDecimal -import java.util.* - -/** - * Created by Allan Wang on 2017-07-22. - */ -private const val FROST_PRO = "frost_pro" - -/** - * Implemented pro checker with a hook for debug builds - * Use this when checking if the pro feature is enabled - */ -inline val IS_FROST_PRO: Boolean - get() = Prefs.pro || (BuildConfig.DEBUG && Prefs.debugPro) - -interface FrostBilling : BillingProcessor.IBillingHandler { - fun Activity.onCreateBilling() - fun onDestroyBilling() - fun purchasePro() - fun restorePurchases() - fun onActivityResultBilling(requestCode: Int, resultCode: Int, data: Intent?): Boolean -} - -abstract class IabBinder : FrostBilling { - - var bp: BillingProcessor? = null - lateinit var activityRef: WeakReference - val activity - get() = activityRef.get() - - final override fun Activity.onCreateBilling() { - activityRef = WeakReference(this) - doAsync { - bp = BillingProcessor.newBillingProcessor(this@onCreateBilling, PUBLIC_BILLING_KEY, this@IabBinder) - bp?.initialize() - } - } - - override fun onDestroyBilling() { - activityRef.clear() - bp?.release() - bp = null - } - - override fun onBillingInitialized() = L.i { "IAB initialized" } - - override fun onPurchaseHistoryRestored() = L.d { "IAB restored" } - - override fun onProductPurchased(productId: String, details: TransactionDetails?) { - bp.doAsync { - L.i { "IAB $productId purchased" } - val listing = weakRef.get()?.getPurchaseListingDetails(productId) ?: return@doAsync - val currency = try { - Currency.getInstance(listing.currency) - } catch (e: Exception) { - null - } - frostAnswers { - logPurchase(PurchaseEvent().apply { - putItemId(productId) - putSuccess(true) - if (currency != null) { - putCurrency(currency) - putItemType(productId) - putItemPrice(BigDecimal.valueOf(listing.priceValue)) - } - }) - } - } - } - - override fun onBillingError(errorCode: Int, error: Throwable?) { - frostAnswers { - logPurchase(PurchaseEvent() - .putCustomAttribute("result", errorCode.toString()) - .putSuccess(false)) - } - error.logFrostAnswers("IAB error $errorCode") - } - - override fun onActivityResultBilling(requestCode: Int, resultCode: Int, data: Intent?): Boolean = bp?.handleActivityResult(requestCode, resultCode, data) - ?: false - - override fun purchasePro() { - val bp = this.bp - if (bp == null) { - frostAnswers { - logPurchase(PurchaseEvent() - .putCustomAttribute("result", "null bp") - .putSuccess(false)) - } - L.eThrow("IAB null bp on purchase attempt") - return - } - val a = activity ?: return - - if (!BillingProcessor.isIabServiceAvailable(a) || !bp.isInitialized || !bp.isOneTimePurchaseSupported) - a.playStorePurchaseUnsupported() - else - bp.purchase(a, FROST_PRO) - } - -} - -class IabSettings : IabBinder() { - - override fun onProductPurchased(productId: String, details: TransactionDetails?) { - super.onProductPurchased(productId, details) - activity?.playStorePurchasedSuccessfully(productId) - } - - override fun onBillingError(errorCode: Int, error: Throwable?) { - super.onBillingError(errorCode, error) - L.e { "Billing error $errorCode ${error?.message}" } - } - - /** - * Attempts to get pro, or launch purchase flow if user doesn't have it - */ - override fun restorePurchases() { - bp.doAsync { - val load = weakRef.get()?.loadOwnedPurchasesFromGoogle() ?: return@doAsync - L.d { "IAB settings load from google $load" } - uiThread { - if (!(weakRef.get()?.isPurchased(FROST_PRO) ?: return@uiThread)) { - if (Prefs.pro) activity.playStoreNoLongerPro() - else purchasePro() - } else { - if (!Prefs.pro) activity.playStoreFoundPro() - else activity?.purchaseRestored() - } - } - } - } -} - -class IabMain : IabBinder() { - - override fun onBillingInitialized() { - super.onBillingInitialized() - restorePurchases() - } - - override fun onPurchaseHistoryRestored() { - super.onPurchaseHistoryRestored() - restorePurchases() - } - - private var restored = false - - /** - * Checks for pro and only does so once - * A null check is added but it should never happen - * given that this is only called with bp is ready - */ - override fun restorePurchases() { - if (restored || bp == null) return - restored = true - bp.doAsync { - val load = weakRef.get()?.loadOwnedPurchasesFromGoogle() ?: false - L.d { "IAB main load from google $load" } - onComplete { - if (weakRef.get()?.isPurchased(FROST_PRO) != true) { - if (Prefs.pro) activity.playStoreNoLongerPro() - } else { - if (!Prefs.pro) activity.playStoreFoundPro() - } - onDestroyBilling() - } - } - } -} \ No newline at end of file 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 deleted file mode 100644 index a21d8670..00000000 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/Key.kt +++ /dev/null @@ -1,33 +0,0 @@ -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 diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/DebugWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/DebugWebView.kt index 4ac9e600..4c4e5525 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/DebugWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/DebugWebView.kt @@ -15,7 +15,6 @@ import com.pitchedapps.frost.injectors.jsInject import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.createFreshFile -import com.pitchedapps.frost.utils.iab.IS_FROST_PRO import com.pitchedapps.frost.utils.isFacebookUrl import org.jetbrains.anko.withAlpha import java.io.File @@ -85,8 +84,8 @@ class DebugWebView @JvmOverloads constructor( CssAssets.ROUND_ICONS.maybe(Prefs.showRoundedIcons), CssHider.CORE, CssHider.COMPOSER.maybe(!Prefs.showComposer), - CssHider.PEOPLE_YOU_MAY_KNOW.maybe(!Prefs.showSuggestedFriends && IS_FROST_PRO), - CssHider.SUGGESTED_GROUPS.maybe(!Prefs.showSuggestedGroups && IS_FROST_PRO), + CssHider.PEOPLE_YOU_MAY_KNOW.maybe(!Prefs.showSuggestedFriends), + CssHider.SUGGESTED_GROUPS.maybe(!Prefs.showSuggestedGroups), Prefs.themeInjector, CssHider.NON_RECENT.maybe((url?.contains("?sk=h_chr") ?: false) && Prefs.aggressiveRecents)) 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 d4e1c103..f1d03f35 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt @@ -10,7 +10,6 @@ import com.pitchedapps.frost.facebook.FB_URL_BASE import com.pitchedapps.frost.facebook.FbItem import com.pitchedapps.frost.injectors.* import com.pitchedapps.frost.utils.* -import com.pitchedapps.frost.utils.iab.IS_FROST_PRO import com.pitchedapps.frost.views.FrostWebView import io.reactivex.subjects.Subject import org.jetbrains.anko.withAlpha @@ -67,14 +66,14 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() { CssAssets.ROUND_ICONS.maybe(Prefs.showRoundedIcons), CssHider.CORE, CssHider.COMPOSER.maybe(!Prefs.showComposer), - CssHider.PEOPLE_YOU_MAY_KNOW.maybe(!Prefs.showSuggestedFriends && IS_FROST_PRO), - CssHider.SUGGESTED_GROUPS.maybe(!Prefs.showSuggestedGroups && IS_FROST_PRO), + CssHider.PEOPLE_YOU_MAY_KNOW.maybe(!Prefs.showSuggestedFriends), + CssHider.SUGGESTED_GROUPS.maybe(!Prefs.showSuggestedGroups), Prefs.themeInjector, CssHider.NON_RECENT.maybe((web.url?.contains("?sk=h_chr") ?: false) && Prefs.aggressiveRecents), JsAssets.DOCUMENT_WATCHER, JsAssets.CLICK_A, - CssHider.ADS.maybe(!Prefs.showFacebookAds && IS_FROST_PRO), + CssHider.ADS.maybe(!Prefs.showFacebookAds), JsAssets.CONTEXT_A, JsAssets.HEADER_HIDER, JsAssets.MEDIA) -- cgit v1.2.3