diff options
Diffstat (limited to 'app/src')
13 files changed, 105 insertions, 68 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt index 27c2106a..17ef972e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt @@ -1,8 +1,10 @@ package com.pitchedapps.frost +import android.app.Activity import android.app.Application import android.graphics.drawable.Drawable import android.net.Uri +import android.os.Bundle import android.widget.ImageView import ca.allanwang.kau.logging.KL import com.bumptech.glide.Glide @@ -51,8 +53,6 @@ class FrostApp : Application() { if (Prefs.identifier == -1) Prefs.identifier = Random().nextInt(Int.MAX_VALUE) Prefs.lastLaunch = System.currentTimeMillis() - - super.onCreate() /** @@ -67,6 +67,24 @@ class FrostApp : Application() { .thumbnail(old).into(imageView) } }) + if (BuildConfig.DEBUG) + registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks { + override fun onActivityPaused(activity: Activity) {} + override fun onActivityResumed(activity: Activity) {} + override fun onActivityStarted(activity: Activity) {} + + override fun onActivityDestroyed(activity: Activity) { + L.d("Activity ${activity.localClassName} destroyed") + } + + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {} + + override fun onActivityStopped(activity: Activity) {} + + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle) { + L.d("Activity ${activity.localClassName} created") + } + }) } 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 867555a6..4514eb10 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt @@ -53,6 +53,7 @@ class AboutActivity : AboutActivityBase(null, { "kotterknife", "materialdialogs", "materialdrawer", + "rxjava", "subsamplingscaleimageview" ) @@ -78,7 +79,6 @@ class AboutActivity : AboutActivityBase(null, { } } adapter.add(LibraryIItem(frost)).add(AboutLinks()) - } class AboutLinks : AbstractItem<AboutLinks, AboutLinks.ViewHolder>(), ThemableIItem by ThemableIItemDelegate() { @@ -121,7 +121,7 @@ class AboutActivity : AboutActivityBase(null, { setImageDrawable(icon.toDrawable(context, 32)) scaleType = ImageView.ScaleType.CENTER background = context.resolveDrawable(android.R.attr.selectableItemBackgroundBorderless) - setOnClickListener({ onClick() }) + setOnClickListener { onClick() } container.addView(this) } } 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 ff8ea050..31479d54 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt @@ -95,8 +95,8 @@ class ImageActivity : KauBaseActivity() { }) fab.setOnClickListener { fabAction.onClick(this) } photo.setOnImageEventListener(object : SubsamplingScaleImageView.DefaultOnImageEventListener() { - override fun onImageLoadError(e: Exception) { - L.e(e, "Image load error") + override fun onImageLoadError(e: Exception?) { + e.logFrostAnswers("Image load error") imageCallback(null, false) } }) @@ -248,7 +248,7 @@ internal enum class FabStates(val iicon: IIcon, val iconColor: Int = Prefs.iconC } activity.startActivity(intent) } catch (e: Exception) { - L.e(e, "Image share failed"); + e.logFrostAnswers("Image share failed") activity.snackbar(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 fa26502a..67f07635 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt @@ -112,7 +112,7 @@ class LoginActivity : BaseActivity() { } override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean { - if (e != null) L.e(e, "Profile loading exception") + e.logFrostAnswers( "Profile loading exception") profileObservable.onSuccess(false) return false } 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 901ba02d..14d15bd6 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/dbflow/CookiesDb.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/dbflow/CookiesDb.kt @@ -2,9 +2,11 @@ package com.pitchedapps.frost.dbflow import android.os.Parcel import android.os.Parcelable +import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork import com.pitchedapps.frost.facebook.FACEBOOK_COM import com.pitchedapps.frost.facebook.FbTab import com.pitchedapps.frost.utils.L +import com.pitchedapps.frost.utils.logFrostAnswers import com.raizlabs.android.dbflow.annotation.ConflictAction import com.raizlabs.android.dbflow.annotation.Database import com.raizlabs.android.dbflow.annotation.PrimaryKey @@ -64,26 +66,31 @@ fun removeCookie(id: Long) { } fun CookieModel.fetchUsername(callback: (String) -> Unit) { - doAsync { - var result = "" - try { - result = Jsoup.connect(FbTab.PROFILE.url) - .cookie(FACEBOOK_COM, cookie) - .get().title() - L.d("Fetch username found", result) - } catch (e: Exception) { - if (e !is UnknownHostException) - L.e(e, "Fetch username failed") - } finally { - if (result.isBlank() && (name?.isNotBlank() ?: false)) { - callback(name!!) - return@doAsync + ReactiveNetwork.checkInternetConnectivity().subscribe { + yes, _ -> + if (!yes) return@subscribe callback("") + doAsync { + var result = "" + try { + result = Jsoup.connect(FbTab.PROFILE.url) + .cookie(FACEBOOK_COM, cookie) + .get().title() + L.d("Fetch username found", result) + } catch (e: Exception) { + if (e !is UnknownHostException) + e.logFrostAnswers("Fetch username failed") + } finally { + if (result.isBlank() && (name?.isNotBlank() ?: false)) { + callback(name!!) + return@doAsync + } + if (name != result) { + name = result + saveFbCookie(this@fetchUsername) + } + callback(result) } - if (name != result) { - name = result - saveFbCookie(this@fetchUsername) - } - callback(result) } + } }
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/UsernameFetcher.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/UsernameFetcher.kt index dfdfa027..cf6a4242 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/UsernameFetcher.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/UsernameFetcher.kt @@ -3,6 +3,7 @@ package com.pitchedapps.frost.facebook import com.pitchedapps.frost.dbflow.CookieModel import com.pitchedapps.frost.dbflow.saveFbCookie import com.pitchedapps.frost.utils.L +import com.pitchedapps.frost.utils.logFrostAnswers import io.reactivex.subjects.SingleSubject import org.jsoup.Jsoup import kotlin.concurrent.thread @@ -21,7 +22,7 @@ object UsernameFetcher { .get().title() L.d("User name found", name) } catch (e: Exception) { - L.e(e, "User name fetching failed") + e.logFrostAnswers("User name fetching failed") } finally { data.name = name saveFbCookie(data) 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 b9b35956..733bc151 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt @@ -6,6 +6,7 @@ import ca.allanwang.kau.utils.* import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs import java.io.FileNotFoundException +import java.util.* /** * Created by Allan Wang on 2017-05-31. @@ -16,7 +17,7 @@ enum class CssAssets(val folder: String = "themes") : InjectorContract { MATERIAL_LIGHT, MATERIAL_DARK, MATERIAL_AMOLED, MATERIAL_GLASS, CUSTOM, ROUND_ICONS("components") ; - var file = "${name.toLowerCase()}.compact.css" + var file = "${name.toLowerCase(Locale.CANADA)}.compact.css" var injector: JsInjector? = null override fun inject(webView: WebView, callback: ((String) -> Unit)?) { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt index d2201c52..27b0f92a 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt @@ -1,6 +1,9 @@ package com.pitchedapps.frost.injectors import android.webkit.WebView +import com.pitchedapps.frost.utils.L +import java.io.FileNotFoundException +import java.util.* /** * Created by Allan Wang on 2017-05-31. @@ -11,13 +14,18 @@ enum class JsAssets : InjectorContract { MENU, CLICK_A, CONTEXT_A, HEADER_BADGES, SEARCH, TEXTAREA_LISTENER, NOTIF_MSG ; - var file = "${name.toLowerCase()}.min.js" + var file = "${name.toLowerCase(Locale.CANADA)}.min.js" var injector: JsInjector? = null override fun inject(webView: WebView, callback: ((String) -> Unit)?) { if (injector == null) { - val content = webView.context.assets.open("js/$file").bufferedReader().use { it.readText() } - injector = JsBuilder().js(content).build() + try { + val content = webView.context.assets.open("js/$file").bufferedReader().use { it.readText() } + injector = JsBuilder().js(content).build() + } catch (e: FileNotFoundException) { + L.e(e, "JsAssets file not found") + injector = JsInjector(JsActions.EMPTY.function) + } } injector!!.inject(webView, callback) } 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 52a1a5f9..ef293220 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt @@ -21,7 +21,6 @@ import com.pitchedapps.frost.BuildConfig import com.pitchedapps.frost.R import com.pitchedapps.frost.activities.FrostWebActivity import com.pitchedapps.frost.dbflow.CookieModel -import com.pitchedapps.frost.dbflow.fetchUsername import com.pitchedapps.frost.facebook.formattedFbUrl import com.pitchedapps.frost.utils.ARG_USER_ID import com.pitchedapps.frost.utils.L @@ -77,39 +76,31 @@ data class NotificationContent(val data: CookieModel, val text: String, val timestamp: Long, val profileUrl: String) { - fun createNotification(context: Context, verifiedUser: Boolean = false) { - //in case we haven't found the name, we will try one more time before passing the notification - if (!verifiedUser && data.name?.isBlank() ?: true) { - data.fetchUsername { - data.name = it - createNotification(context, true) - } - } else { - val intent = Intent(context, FrostWebActivity::class.java) - intent.data = Uri.parse(href.formattedFbUrl) - intent.putExtra(ARG_USER_ID, data.id) - val group = "frost_${data.id}" - val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0) - val notifBuilder = context.frostNotification - .setContentTitle(title ?: context.string(R.string.frost_name)) - .setContentText(text) - .setContentIntent(pendingIntent) - .setCategory(Notification.CATEGORY_SOCIAL) - .setSubText(data.name) - .setGroup(group) + fun createNotification(context: Context) { + val intent = Intent(context, FrostWebActivity::class.java) + intent.data = Uri.parse(href.formattedFbUrl) + intent.putExtra(ARG_USER_ID, data.id) + val group = "frost_${data.id}" + val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0) + val notifBuilder = context.frostNotification + .setContentTitle(title ?: context.string(R.string.frost_name)) + .setContentText(text) + .setContentIntent(pendingIntent) + .setCategory(Notification.CATEGORY_SOCIAL) + .setSubText(data.name) + .setGroup(group) - if (timestamp != -1L) notifBuilder.setWhen(timestamp * 1000) - L.v("Notif load", this.toString()) - NotificationManagerCompat.from(context).notify(group, notifId, notifBuilder.withBigText.build().frostConfig()) + if (timestamp != -1L) notifBuilder.setWhen(timestamp * 1000) + L.v("Notif load", this.toString()) + NotificationManagerCompat.from(context).notify(group, notifId, notifBuilder.withBigText.build().frostConfig()) - if (profileUrl.isNotBlank()) { - context.runOnUiThread { - Glide.with(context) - .asBitmap() - .load(profileUrl) - .withRoundIcon() - .into(FrostNotificationTarget(context, notifId, group, notifBuilder)) - } + if (profileUrl.isNotBlank()) { + context.runOnUiThread { + Glide.with(context) + .asBitmap() + .load(profileUrl) + .withRoundIcon() + .into(FrostNotificationTarget(context, notifId, group, notifBuilder)) } } } 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 91c5ca23..a5b12bbc 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt @@ -132,6 +132,15 @@ fun frostAnswersCustom(name: String, vararg events: Pair<String, Any>) { } } +/** + * Helper method to quietly keep track of throwable issues + */ +fun Throwable?.logFrostAnswers(text: String) { + val msg = if (this == null) text else "$text: $message" + L.e(msg) + frostAnswersCustom("Errors", "text" to text, "message" to (this?.message ?: "NA")) +} + fun View.frostSnackbar(@StringRes text: Int, builder: Snackbar.() -> Unit = {}) { Snackbar.make(this, text, Snackbar.LENGTH_LONG).apply { builder() 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 index b4dc2294..e90fbd65 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABBinder.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABBinder.kt @@ -9,6 +9,7 @@ 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 @@ -52,9 +53,9 @@ abstract class IABBinder : FrostBilling { } override fun onDestroyBilling() { + activityRef.clear() bp?.release() bp = null - activityRef.clear() } override fun onBillingInitialized() = L.i("IAB initialized") @@ -90,7 +91,7 @@ abstract class IABBinder : FrostBilling { .putCustomAttribute("result", errorCode.toString()) .putSuccess(false)) } - L.e(error, "IAB error $errorCode") + error.logFrostAnswers("IAB error $errorCode") } override fun onActivityResultBilling(requestCode: Int, resultCode: Int, data: Intent?): Boolean diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/SearchWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/SearchWebView.kt index f63f4fdc..84b91f5e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/SearchWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/SearchWebView.kt @@ -123,7 +123,8 @@ class SearchWebView(context: Context, val contract: SearchContract) : WebView(co L.d("Search loaded successfully") } 1 -> { //something is not found in the search view; this is effectively useless - L.eThrow("Search subject error; reverting to full overlay") + L.e("Search subject error; reverting to full overlay") + //todo add a way to fetch the html? Prefs.searchBar = false searchSubject.onComplete() contract.searchOverlayDispose() diff --git a/app/src/main/res/xml/frost_changelog.xml b/app/src/main/res/xml/frost_changelog.xml index 8f0c90a8..3d349ec3 100644 --- a/app/src/main/res/xml/frost_changelog.xml +++ b/app/src/main/res/xml/frost_changelog.xml @@ -18,7 +18,7 @@ <item text="Add option to disable media loading on metered network" /> <item text="Fix menu section" /> <item text="Add more background setters to help transparent themes" /> - <item text="" /> + <item text="Fixed crash for users with non english characters" /> <item text="" /> <version title="v1.5.0"/> |