From 5d9a3fd7fb8f2f9d0f592c89446824980c9841c6 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Mon, 14 Aug 2017 20:48:39 -0700 Subject: v1.4.5 (#174) * Update/kau (#125) * Update logger * Clean imports and bring back reactive libs * Update dependencies and make billing async * Misc (#128) * Update null * Attempt to improve transparent theme backgrounds * Update menu * Move injections to visible method and reduce offset * Update searchview and logging * Clean temp strings and add network states * Move console blacklist to web state * Change some logs to info * Move glide loader to onCreate (#135) * Remove commit number increments (#139) * 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 * Move network checker to io thread (#150) * Update dependency * Blank * Feature/jsoup debugger (#152) * Create debugger * Update debugger content * Create debugging logic * Finalize and test debugger * Add reload listener * Fix/pro crash without play store (#155) * Update changelog * Check if iab service exists * Add checker before launching play store request * Separate strings * Enhancement/message notifications (#157) * Map message notifs to the headless html extractor * Update strings * Bring im notifs out of alpha * Update changelog * Remove confirmation dialog (#159) * Separate message notifications and add click intents (#171) * Separate message notifications and add click intent for group notifications * Add comments and finalize * Feature/scroll down on message thread (#172) * Add hook for scroll * Update changelog * Add custom navdrawer layout (#173) * Add faq for auto play * Update changelog * Fix page banner bg (#163) --- .../kotlin/com/pitchedapps/frost/settings/Debug.kt | 151 +++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt (limited to 'app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt') diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt new file mode 100644 index 00000000..f8dc81d1 --- /dev/null +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt @@ -0,0 +1,151 @@ +package com.pitchedapps.frost.settings + +import android.content.Context +import android.support.annotation.UiThread +import ca.allanwang.kau.email.sendEmail +import ca.allanwang.kau.kpref.activity.KPrefAdapterBuilder +import ca.allanwang.kau.utils.string +import com.afollestad.materialdialogs.MaterialDialog +import com.pitchedapps.frost.R +import com.pitchedapps.frost.activities.SettingsActivity +import com.pitchedapps.frost.facebook.FACEBOOK_COM +import com.pitchedapps.frost.facebook.FbCookie +import com.pitchedapps.frost.facebook.FbItem +import com.pitchedapps.frost.facebook.USER_AGENT_BASIC +import com.pitchedapps.frost.injectors.InjectorContract +import com.pitchedapps.frost.injectors.JsActions +import com.pitchedapps.frost.utils.L +import com.pitchedapps.frost.utils.cleanHtml +import com.pitchedapps.frost.utils.materialDialogThemed +import com.pitchedapps.frost.web.launchHeadlessHtmlExtractor +import com.pitchedapps.frost.web.query +import io.reactivex.disposables.Disposable +import org.jetbrains.anko.AnkoAsyncContext +import org.jetbrains.anko.doAsync +import org.jetbrains.anko.runOnUiThread +import org.jetbrains.anko.uiThread +import org.jsoup.Jsoup +import org.jsoup.nodes.Document + +/** + * Created by Allan Wang on 2017-06-30. + * + * A sub pref section that is enabled through a hidden preference + * Each category will load a page, extract the contents, remove private info, and create a report + */ +fun SettingsActivity.getDebugPrefs(): KPrefAdapterBuilder.() -> Unit = { + + plainText(R.string.experimental_disclaimer) { + descRes = R.string.debug_disclaimer_info + } + + Debugger.values().forEach { + plainText(it.data.titleId) { + iicon = it.data.icon + onClick = { itemView, _, _ -> it.debug(itemView.context); true } + } + } + +} + +private enum class Debugger(val data: FbItem, val injector: InjectorContract?, vararg query: String) { + NOTIFICATIONS(FbItem.NOTIFICATIONS, null, "#notifications_list"), + SEARCH(FbItem.SEARCH, JsActions.FETCH_BODY); + + val query = if (query.isNotEmpty()) arrayOf(*query, "#root", "main", "body") else emptyArray() + + fun debug(context: Context) { + val dialog = context.materialDialogThemed { + title("Debugging") + progress(true, 0) + canceledOnTouchOutside(false) + positiveText(R.string.kau_cancel) + onPositive { dialog, _ -> dialog.cancel() } + } + if (injector != null) dialog.extractHtml(injector) + else dialog.debugAsync { + loadJsoup() + } + } + + fun MaterialDialog.debugAsync(task: AnkoAsyncContext.() -> Unit) { + doAsync({ t: Throwable -> + val msg = t.message + L.e("Debugger failed: $msg") + context.runOnUiThread { + cancel() + context.materialDialogThemed { + title(R.string.debug_incomplete) + if (msg != null) content(msg) + } + } + }, task) + } + + /** + * Wait for html to be returned from headless webview + * + * from [debug] to [simplifyJsoup] if [query] is not empty, or [createReport] otherwise + */ + @UiThread + private fun MaterialDialog.extractHtml(injector: InjectorContract) { + setContent("Fetching webpage") + var disposable: Disposable? = null + setOnCancelListener { disposable?.dispose() } + context.launchHeadlessHtmlExtractor(data.url, injector) { + disposable = it.subscribe { + (html, errorRes) -> + debugAsync { + if (errorRes == -1) { + L.i("Debug report successful", html) + if (query.isNotEmpty()) simplifyJsoup(Jsoup.parseBodyFragment(html)) + else createReport(html) + } else { + throw Throwable(context.string(errorRes)) + } + } + } + } + } + + /** + * Get data directly from the link and search for our queries, returning the outerHTML + * of the first query found + * + * from [debug] to [simplifyJsoup] + */ + private fun AnkoAsyncContext.loadJsoup() { + uiThread { + it.setContent("Load Jsoup") + it.setOnCancelListener(null) + it.debugAsync { + val connection = Jsoup.connect(data.url).cookie(FACEBOOK_COM, FbCookie.webCookie).userAgent(USER_AGENT_BASIC) + val doc = connection.get() + simplifyJsoup(doc) + } + } + } + + /** + * Takes snippet of given document that matches the first query in the [query] items + * before sending it to [createReport] + */ + private fun AnkoAsyncContext.simplifyJsoup(doc: Document) { + weakRef.get() ?: return + val q = query.first { doc.select(it).isNotEmpty() } + createReport(doc.select(q).outerHtml()) + } + + private fun AnkoAsyncContext.createReport(html: String) { + val cleanHtml = html.cleanHtml() + uiThread { + val c = it.context + it.dismiss() + c.sendEmail(c.string(R.string.dev_email), + "${c.string(R.string.debug_report_email_title)} $name") { + addItem("Query List", query.contentToString()) + footer = cleanHtml + } + } + } +} \ No newline at end of file -- cgit v1.2.3