From afe7437e0a0f6c315d383e0b6133b13a461c92af Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Sun, 7 Jan 2018 04:44:18 -0500 Subject: Enhancement/debug (#605) * Finalize debugger * Add video logging --- .../pitchedapps/frost/activities/DebugActivity.kt | 35 +++++++++++--- .../frost/activities/SettingsActivity.kt | 2 +- .../pitchedapps/frost/debugger/OfflineWebsite.kt | 25 +++++----- .../frost/fragments/RecyclerFragmentBase.kt | 2 +- .../frost/services/FrostNotifications.kt | 2 +- .../kotlin/com/pitchedapps/frost/settings/Debug.kt | 2 +- .../kotlin/com/pitchedapps/frost/utils/Utils.kt | 17 +++++++ .../com/pitchedapps/frost/views/FrostVideoView.kt | 3 ++ .../com/pitchedapps/frost/web/DebugWebView.kt | 56 ++++++++++++++++++++-- .../pitchedapps/frost/web/FrostWebViewClients.kt | 7 --- 10 files changed, 118 insertions(+), 33 deletions(-) (limited to 'app/src') diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/DebugActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/DebugActivity.kt index b6becf90..685e6532 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/DebugActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/DebugActivity.kt @@ -1,6 +1,7 @@ package com.pitchedapps.frost.activities import android.app.Activity +import android.content.Context import android.content.Intent import android.content.res.ColorStateList import android.os.Bundle @@ -15,13 +16,15 @@ import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.pitchedapps.frost.R import com.pitchedapps.frost.facebook.FbItem import com.pitchedapps.frost.utils.Prefs +import com.pitchedapps.frost.utils.createFreshDir import com.pitchedapps.frost.utils.setFrostColors import com.pitchedapps.frost.web.DebugWebView +import java.io.File /** * Created by Allan Wang on 05/01/18. */ -class DebugActivity : KauBaseActivity(), SwipeRefreshLayout.OnRefreshListener { +class DebugActivity : KauBaseActivity() { private val toolbar: Toolbar by bindView(R.id.toolbar) private val web: DebugWebView by bindView(R.id.debug_webview) @@ -30,30 +33,48 @@ class DebugActivity : KauBaseActivity(), SwipeRefreshLayout.OnRefreshListener { companion object { const val RESULT_URL = "extra_result_url" + fun baseDir(context: Context) = File(context.externalCacheDir, "offline_debug") } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_debug) setSupportActionBar(toolbar) + supportActionBar?.apply { + setDisplayHomeAsUpEnabled(true) + setDisplayShowHomeEnabled(true) + } setTitle(R.string.debug_frost) + setFrostColors { toolbar(toolbar) } web.loadUrl(FbItem.FEED.url) web.onPageFinished = { swipeRefresh.isRefreshing = false } + + swipeRefresh.setOnRefreshListener(web::reload) + fab.visible().setIcon(GoogleMaterial.Icon.gmd_bug_report, Prefs.iconColor) fab.backgroundTintList = ColorStateList.valueOf(Prefs.accentColor) fab.setOnClickListener { - val intent = Intent() - intent.putExtra(RESULT_URL, web.url) - setResult(Activity.RESULT_OK, intent) - finish() + fab.hide() + + val parent = baseDir(this) + parent.createFreshDir() + val file = File(parent, "screenshot.png") + web.getScreenshot(file) { + val intent = Intent() + intent.putExtra(RESULT_URL, web.url) + setResult(Activity.RESULT_OK, intent) + finish() + } } + } - override fun onRefresh() { - web.reload() + override fun onSupportNavigateUp(): Boolean { + finish() + return true } override fun onResume() { 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 93d303ab..2de7a843 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt @@ -51,7 +51,7 @@ class SettingsActivity : KPrefActivity(), FrostBilling by IabSettings() { } ACTIVITY_REQUEST_DEBUG -> { val url = data?.extras?.getString(DebugActivity.RESULT_URL) - if (url?.isNotBlank() == true) + if (resultCode == Activity.RESULT_OK && url?.isNotBlank() == true) sendDebug(url) return } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/debugger/OfflineWebsite.kt b/app/src/main/kotlin/com/pitchedapps/frost/debugger/OfflineWebsite.kt index 434f1bae..791e6a69 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/debugger/OfflineWebsite.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/debugger/OfflineWebsite.kt @@ -6,6 +6,8 @@ import com.pitchedapps.frost.facebook.USER_AGENT_BASIC import com.pitchedapps.frost.facebook.get import com.pitchedapps.frost.facebook.requests.call import com.pitchedapps.frost.facebook.requests.zip +import com.pitchedapps.frost.utils.createFreshDir +import com.pitchedapps.frost.utils.createFreshFile import com.pitchedapps.frost.utils.frostJsoup import okhttp3.Request import okhttp3.ResponseBody @@ -71,24 +73,19 @@ class OfflineWebsite(private val url: String, reset() L.v { "Saving $url to ${baseDir.absolutePath}" } - if (baseDir.exists() && !baseDir.deleteRecursively()) { - L.e { "Could not clean directory" } - return callback(false) - } - if (!baseDir.mkdirs()) { + if (!baseDir.exists() && !baseDir.mkdirs()) { L.e { "Could not make directory" } return callback(false) } - if (!mainFile.createNewFile()) { L.e { "Could not create ${mainFile.absolutePath}" } return callback(false) } - if (!assetDir.mkdirs()) { + if (!assetDir.createFreshDir()) { L.e { "Could not create ${assetDir.absolutePath}" } return callback(false) } @@ -149,7 +146,7 @@ class OfflineWebsite(private val url: String, fun zip(name: String): Boolean { try { val zip = File(baseDir, "$name.zip") - if (zip.exists() && (!zip.delete() || !zip.createNewFile())) { + if (!zip.createFreshFile()) { L.e { "Failed to create zip at ${zip.absolutePath}" } return false } @@ -157,6 +154,7 @@ class OfflineWebsite(private val url: String, ZipOutputStream(FileOutputStream(zip)).use { out -> fun File.zip(name: String = this.name) { + if (!isFile) return inputStream().use { file -> out.putNextEntry(ZipEntry(name)) file.copyTo(out) @@ -165,13 +163,14 @@ class OfflineWebsite(private val url: String, delete() } - mainFile.zip() + baseDir.listFiles({ _, n -> n != "$name.zip" }).forEach { it.zip() } assetDir.listFiles().forEach { it.zip("assets/${it.name}") } } return true } catch (e: Exception) { + L.e { "Zip failed: ${e.message}" } return false } } @@ -275,11 +274,16 @@ class OfflineWebsite(private val url: String, val index = atomicInt.getAndIncrement() + + var newUrl = "a${index}_$candidate" + /** * This is primarily for zipping up and sending via emails * As .js files typically aren't allowed, we'll simply make everything txt files */ - val newUrl = "a${index}_$candidate.txt" + if (newUrl.endsWith(".js")) + newUrl = "$newUrl.txt" + urlMapper.put(this, newUrl) return newUrl } @@ -296,7 +300,6 @@ class OfflineWebsite(private val url: String, atomicInt.set(0) fileQueue.clear() cssQueue.clear() - baseDir.deleteRecursively() } fun cancel() { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragmentBase.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragmentBase.kt index 1a0c3b25..cdeaa3c1 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragmentBase.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/RecyclerFragmentBase.kt @@ -106,7 +106,7 @@ abstract class FrostParserFragment> : RecyclerFragme progress(60) val response = parser.parse(cookie, doc) if (response == null) { - L.eThrow("RecyclerFragment failed for ${baseEnum.name}") + L.i { "RecyclerFragment failed for ${baseEnum.name}" } return@doAsync callback(false) } progress(80) 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 5e08b363..50392dea 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt @@ -145,7 +145,7 @@ enum class NotificationType( */ fun fetch(context: Context, data: CookieModel) { val response = parser.parse(data.cookie) - ?: return L.eThrow("$name notification data not found") + ?: return L.v { "$name notification data not found" } val notifs = response.data.getUnreadNotifications(data) if (notifs.isEmpty()) return var notifCount = 0 diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt index 76c6e5a4..3e795e80 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Debug.kt @@ -49,7 +49,7 @@ fun SettingsActivity.sendDebug(urlOrig: String) { } val downloader = OfflineWebsite(url, FbCookie.webCookie ?: "", - File(externalCacheDir, "offline_debug")) + DebugActivity.baseDir(this)) val md = materialDialog { title(R.string.parsing_data) 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 bd9c1f99..1fb41dca 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt @@ -322,4 +322,21 @@ fun Element.first(vararg select: String): Element? { if (e.size > 0) return e.first() } return null +} + +fun File.createFreshFile(): Boolean { + if (exists()) { + if (!delete()) return false + } else { + val parent = parentFile + if (!parent.exists() && !parent.mkdirs()) + return false + } + return createNewFile() +} + +fun File.createFreshDir(): Boolean { + if (exists() && !deleteRecursively()) + return false + return mkdirs() } \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoView.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoView.kt index 6f1c0fe4..c45bf23d 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/FrostVideoView.kt @@ -17,6 +17,7 @@ import ca.allanwang.kau.utils.toast import com.devbrackets.android.exomedia.ui.widget.VideoView import com.pitchedapps.frost.R import com.pitchedapps.frost.utils.L +import com.pitchedapps.frost.utils.Prefs /** * Created by Allan Wang on 2017-10-13. @@ -131,6 +132,8 @@ class FrostVideoView @JvmOverloads constructor( if (isExpanded) showControls() } setOnErrorListener { + if (Prefs.analytics) + L.e(it) { "Failed to load video $videoUri" } toast(R.string.video_load_failed, Toast.LENGTH_SHORT) destroy() true 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 3cc10236..7fd2286c 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/DebugWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/DebugWebView.kt @@ -2,22 +2,24 @@ package com.pitchedapps.frost.web import android.annotation.SuppressLint import android.content.Context +import android.graphics.Bitmap import android.graphics.Color import android.util.AttributeSet import android.view.View -import android.webkit.CookieManager -import android.webkit.WebResourceRequest import android.webkit.WebView -import com.pitchedapps.frost.facebook.FB_USER_MATCHER import com.pitchedapps.frost.facebook.USER_AGENT_BASIC -import com.pitchedapps.frost.facebook.get +import com.pitchedapps.frost.injectors.CssAssets import com.pitchedapps.frost.injectors.CssHider 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.doAsync import org.jetbrains.anko.uiThread +import org.jetbrains.anko.withAlpha +import java.io.File /** * Created by Allan Wang on 2018-01-05. @@ -40,6 +42,31 @@ class DebugWebView @JvmOverloads constructor( settings.userAgentString = USER_AGENT_BASIC setLayerType(View.LAYER_TYPE_HARDWARE, null) webViewClient = DebugClient() + isDrawingCacheEnabled = true + } + + fun getScreenshot(output: File, callback: (Boolean) -> Unit) { + + if (!output.createFreshFile()) { + L.e { "Failed to create ${output.absolutePath} for debug screenshot" } + return callback(false) + } + doAsync { + var valid = true + try { + output.outputStream().use { + drawingCache.compress(Bitmap.CompressFormat.PNG, 100, it) + } + L.d { "Created screenshot at ${output.absolutePath}" } + } catch (e: Exception) { + L.e { "An error occurred ${e.message}" } + valid = false + } finally { + uiThread { + callback(valid) + } + } + } } private inner class DebugClient : BaseWebViewClient() { @@ -49,6 +76,27 @@ class DebugWebView @JvmOverloads constructor( onPageFinished(url) } + private fun injectBackgroundColor() { + setBackgroundColor( + if (url.isFacebookUrl) Prefs.bgColor.withAlpha(255) + else Color.WHITE) + } + + + override fun onPageCommitVisible(view: WebView, url: String?) { + super.onPageCommitVisible(view, url) + injectBackgroundColor() + if (url.isFacebookUrl) + view.jsInject( + 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), + Prefs.themeInjector, + CssHider.NON_RECENT.maybe((url?.contains("?sk=h_chr") ?: false) + && Prefs.aggressiveRecents)) + } } } \ No newline at end of file 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 9e5f4996..e23ec0f8 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt @@ -53,13 +53,6 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() { refresh.onNext(true) } - fun launchLogin(c: Context) { - if (c is MainActivity && c.cookies().isNotEmpty()) - c.launchNewTask(c.cookies()) - else - c.launchNewTask() - } - private fun injectBackgroundColor() { web.setBackgroundColor( when { -- cgit v1.2.3