aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2017-08-09 20:44:24 -0700
committerGitHub <noreply@github.com>2017-08-09 20:44:24 -0700
commit8a4b0795415f0fa2c5cdcf9ef86a2c44da6b178e (patch)
tree9d832e964c58795578436c1c188ae864e012cf9c
parent51ad3227b1a2d48b7d5c85965d9c3d5a9c4789a4 (diff)
downloadfrost-8a4b0795415f0fa2c5cdcf9ef86a2c44da6b178e.tar.gz
frost-8a4b0795415f0fa2c5cdcf9ef86a2c44da6b178e.tar.bz2
frost-8a4b0795415f0fa2c5cdcf9ef86a2c44da6b178e.zip
Fix/misc (#140)
* Add canadian locale to toLowerCase * Add try catch to JsAssets * Disable error throwing for bad search subject * Log more throwables quietly * Check internet connection before fetching username * Remove name check in frost notifications * Add activity lifecycle logger * Add rxjava to lib showcase
-rw-r--r--app/build.gradle2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt22
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt4
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt6
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/dbflow/CookiesDb.kt45
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/UsernameFetcher.kt3
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt3
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt14
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt55
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt9
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABBinder.kt5
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/SearchWebView.kt3
-rw-r--r--app/src/main/res/xml/frost_changelog.xml2
14 files changed, 106 insertions, 69 deletions
diff --git a/app/build.gradle b/app/build.gradle
index d12abcb6..704e5285 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -27,7 +27,7 @@ android {
}
defaultConfig {
- applicationId "${project.APP_GROUP}." + project.APP_ID.toLowerCase()
+ applicationId "${project.APP_GROUP}." + project.APP_ID.toLowerCase(Locale.CANADA)
minSdkVersion Integer.parseInt(project.MIN_SDK)
targetSdkVersion Integer.parseInt(project.TARGET_SDK)
versionCode androidGitVersion.code()
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"/>