diff options
author | Allan Wang <me@allanwang.ca> | 2017-07-16 17:26:58 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-07-16 17:26:58 -0700 |
commit | d90cb9b61cd2e033b46f4780ad1340c5f35b7751 (patch) | |
tree | 0294ce22bacb463c9cc95de8dc5581c1bd59a108 /app/src/main/kotlin/com | |
parent | c3f1fc6a8b3216442a018bb04843dfa68d738918 (diff) | |
download | frost-d90cb9b61cd2e033b46f4780ad1340c5f35b7751.tar.gz frost-d90cb9b61cd2e033b46f4780ad1340c5f35b7751.tar.bz2 frost-d90cb9b61cd2e033b46f4780ad1340c5f35b7751.zip |
Add image viewing and downloading (#63)v1.3
* Commence aggressive image caching
* Add glide toggle and css url parsing
* Add image hook and refractor activities
* Update version analytics
* Implemented imageactivity but glide will not load
* Create working image loader
* Finalize image view
* Finalize image view logic
* Remove custom cache experiment
Diffstat (limited to 'app/src/main/kotlin/com')
34 files changed, 550 insertions, 74 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt index 4b62d244..3f5bdeda 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt @@ -10,6 +10,7 @@ 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.BuildConfig import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.utils.CrashReportingTree import com.pitchedapps.frost.utils.GlideApp diff --git a/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt index 122c571e..12cb955d 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt @@ -2,6 +2,9 @@ package com.pitchedapps.frost import android.os.Bundle import android.support.v7.app.AppCompatActivity +import com.pitchedapps.frost.activities.LoginActivity +import com.pitchedapps.frost.activities.MainActivity +import com.pitchedapps.frost.activities.SelectorActivity import com.pitchedapps.frost.dbflow.loadFbCookiesAsync import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.utils.L diff --git a/app/src/main/kotlin/com/pitchedapps/frost/AboutActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt index 6cab2a59..63ad8bae 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/AboutActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt @@ -1,4 +1,4 @@ -package com.pitchedapps.frost +package com.pitchedapps.frost.activities import android.support.constraint.ConstraintLayout import android.support.constraint.ConstraintSet @@ -20,6 +20,8 @@ import com.mikepenz.fastadapter.IItem import com.mikepenz.fastadapter.items.AbstractItem import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.mikepenz.iconics.typeface.IIcon +import com.pitchedapps.frost.BuildConfig +import com.pitchedapps.frost.R import com.pitchedapps.frost.utils.Prefs diff --git a/app/src/main/kotlin/com/pitchedapps/frost/BaseActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt index c2551125..fd020af1 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/BaseActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt @@ -1,7 +1,8 @@ -package com.pitchedapps.frost +package com.pitchedapps.frost.activities import android.os.Bundle import android.support.v7.app.AppCompatActivity +import com.pitchedapps.frost.R import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.materialDialogThemed import com.pitchedapps.frost.utils.setFrostTheme diff --git a/app/src/main/kotlin/com/pitchedapps/frost/FrostWebActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/FrostWebActivity.kt index 3e337813..1773471f 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/FrostWebActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/FrostWebActivity.kt @@ -1,4 +1,4 @@ -package com.pitchedapps.frost +package com.pitchedapps.frost.activities import android.os.Bundle import com.pitchedapps.frost.utils.Prefs diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt new file mode 100644 index 00000000..509ac2cb --- /dev/null +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt @@ -0,0 +1,297 @@ +package com.pitchedapps.frost.activities + +import android.animation.ValueAnimator +import android.annotation.SuppressLint +import android.content.Intent +import android.content.res.ColorStateList +import android.graphics.Bitmap +import android.graphics.Color +import android.graphics.drawable.Drawable +import android.net.Uri +import android.os.Bundle +import android.os.Environment +import android.support.design.widget.FloatingActionButton +import android.support.v4.content.FileProvider +import android.support.v7.app.AppCompatActivity +import android.view.View +import android.view.ViewGroup +import android.widget.ProgressBar +import android.widget.TextView +import ca.allanwang.kau.permissions.PERMISSION_WRITE_EXTERNAL_STORAGE +import ca.allanwang.kau.permissions.kauOnRequestPermissionsResult +import ca.allanwang.kau.permissions.kauRequestPermissions +import ca.allanwang.kau.utils.* +import com.bumptech.glide.request.target.BaseTarget +import com.bumptech.glide.request.target.SizeReadyCallback +import com.bumptech.glide.request.target.Target +import com.bumptech.glide.request.transition.Transition +import com.davemorrissey.labs.subscaleview.ImageSource +import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView +import com.mikepenz.google_material_typeface_library.GoogleMaterial +import com.mikepenz.iconics.typeface.IIcon +import com.pitchedapps.frost.BuildConfig +import com.pitchedapps.frost.R +import com.pitchedapps.frost.utils.* +import com.sothree.slidinguppanel.SlidingUpPanelLayout +import org.jetbrains.anko.doAsync +import org.jetbrains.anko.uiThread +import timber.log.Timber +import java.io.File +import java.io.IOException +import java.text.SimpleDateFormat +import java.util.* + +/** + * Created by Allan Wang on 2017-07-15. + */ +class ImageActivity : AppCompatActivity() { + + val progress: ProgressBar by bindView(R.id.image_progress) + val container: ViewGroup by bindView(R.id.image_container) + val panel: SlidingUpPanelLayout? by bindOptionalView(R.id.image_panel) + val photo: SubsamplingScaleImageView by bindView(R.id.image_photo) + val caption: TextView? by bindOptionalView(R.id.image_text) + val fab: FloatingActionButton by bindView(R.id.image_fab) + + /** + * Reference to the temporary file path + * Should be nonnull if the image is successfully loaded + * As this is temporary, the image is deleted upon exit + */ + internal var tempFilePath: String? = null + /** + * Reference to path for downloaded image + * Nonnull once the image is downloaded by the user + */ + internal var downloadPath: String? = null + /** + * Indicator for fab's click result + */ + internal var fabAction: FabStates = FabStates.NOTHING + set(value) { + if (field == value) return + field = value + value.update(fab) + } + + val imageUrl: String + get() = intent.extras.getString(ARG_IMAGE_URL) + + val text: String? + get() = intent.extras.getString(ARG_TEXT) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(if (!text.isNullOrBlank()) R.layout.activity_image else R.layout.activity_image_textless) + container.setBackgroundColor(Prefs.bgColor.withMinAlpha(222)) + caption?.setTextColor(Prefs.textColor) + caption?.setBackgroundColor(Prefs.bgColor.colorToForeground(0.1f).withAlpha(255)) + caption?.text = text + progress.tint(Prefs.accentColor) + panel?.addPanelSlideListener(object : SlidingUpPanelLayout.SimplePanelSlideListener() { + + override fun onPanelSlide(panel: View, slideOffset: Float) { + if (slideOffset == 0f && !fab.isShown) fab.show() + else if (slideOffset != 0f && fab.isShown) fab.hide() + caption?.alpha = slideOffset / 2 + 0.5f + } + + }) + fab.setOnClickListener { fabAction.onClick(this) } + photo.setOnImageEventListener(object : SubsamplingScaleImageView.DefaultOnImageEventListener() { + override fun onImageLoadError(e: Exception) { + L.e(e, "Image load error") + imageCallback(null, false) + } + }) + GlideApp.with(this).asBitmap().load(imageUrl).into(PhotoTarget(this::imageCallback)) + } + + /** + * Callback to add image to view + * [resource] is guaranteed to be nonnull when [success] is true + * and null when it is false + */ + private fun imageCallback(resource: Bitmap?, success: Boolean) { + if (progress.isVisible) progress.fadeOut() + if (success) { + saveTempImage(resource!!, { + if (it == null) { + imageCallback(null, false) + } else { + photo.setImage(ImageSource.uri(it)) + fabAction = FabStates.DOWNLOAD + photo.animate().alpha(1f).scaleX(1f).scaleY(1f).withEndAction { fab.show() }.start() + } + }) + } else { + fabAction = FabStates.ERROR + fab.show() + } + } + + /** + * Bitmap load handler + */ + class PhotoTarget(val callback: (resource: Bitmap?, success: Boolean) -> Unit) : BaseTarget<Bitmap>() { + + override fun removeCallback(cb: SizeReadyCallback?) {} + + override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) = callback(resource, true) + + override fun onLoadFailed(errorDrawable: Drawable?) = callback(null, false) + + override fun getSize(cb: SizeReadyCallback) = cb.onSizeReady(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) + + } + + private fun saveTempImage(resource: Bitmap, callback: (uri: Uri?) -> Unit) { + var photoFile: File? = null + try { + photoFile = createImageFile() + } catch (ignored: IOException) { + } finally { + if (photoFile == null) { + callback(null) + } else { + tempFilePath = photoFile.absolutePath + Timber.d("Temp image path $tempFilePath") + // File created; proceed with request + val photoURI = FileProvider.getUriForFile(this, + BuildConfig.APPLICATION_ID + ".provider", + photoFile) + photoFile.outputStream().use { resource.compress(Bitmap.CompressFormat.PNG, 100, it) } + callback(photoURI) + } + } + } + + @Suppress("SIMPLE_DATE_FORMAT") + @Throws(IOException::class) + private fun createImageFile(): File { + // Create an image file name + @SuppressLint("SimpleDateFormat") + val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date()) + val imageFileName = "Frost_" + timeStamp + "_" + val storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES) + return File.createTempFile( + imageFileName, /* prefix */ + ".png", /* suffix */ + storageDir /* directory */ + ) + } + + internal fun downloadImage() { + kauRequestPermissions(PERMISSION_WRITE_EXTERNAL_STORAGE) { + granted, _ -> + if (granted) { + doAsync { + val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date()) + val imageFileName = "Frost_" + timeStamp + "_" + val storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + val frostDir = File(storageDir, "Frost") + if (!frostDir.exists()) frostDir.mkdirs() + val destination = File.createTempFile(imageFileName, ".png", frostDir) + downloadPath = destination.absolutePath + var success = true + try { + File(tempFilePath).copyTo(destination, true) + } catch (e: Exception) { + success = false + } finally { + uiThread { + snackbar(if (success) R.string.image_download_success else R.string.image_download_fail) + if (success) { + deleteTempFile() + fabAction = FabStates.SHARE + } + } + } + } + } + } + } + + internal fun deleteTempFile() { + if (tempFilePath != null) { + File(tempFilePath!!).delete() + tempFilePath = null + } + } + + override fun onDestroy() { + deleteTempFile() + super.onDestroy() + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + kauOnRequestPermissionsResult(permissions, grantResults) + } +} + +internal enum class FabStates(val iicon: IIcon, val iconColor: Int = Prefs.textColor, val backgroundTint: Int = Prefs.accentBackgroundColor.withAlpha(255)) { + ERROR(GoogleMaterial.Icon.gmd_error, Color.WHITE, Color.RED) { + override fun onClick(activity: ImageActivity) { + //todo add something + } + }, + NOTHING(GoogleMaterial.Icon.gmd_adjust) { + override fun onClick(activity: ImageActivity) {} + }, + DOWNLOAD(GoogleMaterial.Icon.gmd_file_download) { + override fun onClick(activity: ImageActivity) { + activity.downloadImage() + } + }, + SHARE(GoogleMaterial.Icon.gmd_share) { + override fun onClick(activity: ImageActivity) { + try { + val photoURI = FileProvider.getUriForFile(activity, + BuildConfig.APPLICATION_ID + ".provider", + File(activity.downloadPath)) + val intent = Intent(Intent.ACTION_SEND).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK + putExtra(Intent.EXTRA_STREAM, photoURI) + type = "image/png" + } + activity.startActivity(intent) + } catch (e: Exception) { + L.e(e, "Image share failed"); + activity.snackbar(R.string.image_share_failed) + } + } + }; + + /** + * Change the fab look + * If it's in view, give it some animations + */ + fun update(fab: FloatingActionButton) { + if (!fab.isShown) { + fab.setIcon(iicon, color = iconColor) + fab.backgroundTintList = ColorStateList.valueOf(backgroundTint) + } else { + var switched = false + ValueAnimator.ofFloat(1.0f, 0.0f, 1.0f).apply { + duration = 500L + addUpdateListener { + val x = it.animatedValue as Float + val scale = x * 0.3f + 0.7f + fab.scaleX = scale + fab.scaleY = scale + fab.imageAlpha = (x * 255).toInt() + if (it.animatedFraction > 0.5f && !switched) { + switched = true + fab.setIcon(iicon, color = iconColor) + fab.backgroundTintList = ColorStateList.valueOf(backgroundTint) + } + } + start() + } + } + } + + abstract fun onClick(activity: ImageActivity) + +}
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/LoginActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt index a27a1ee2..e4897be5 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/LoginActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt @@ -1,4 +1,4 @@ -package com.pitchedapps.frost +package com.pitchedapps.frost.activities import android.graphics.drawable.Drawable import android.os.Bundle @@ -16,6 +16,7 @@ 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 import com.pitchedapps.frost.dbflow.loadFbCookiesAsync diff --git a/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt index f9a597db..ba76e594 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt @@ -1,4 +1,4 @@ -package com.pitchedapps.frost +package com.pitchedapps.frost.activities import android.app.AlarmManager import android.app.PendingIntent @@ -39,6 +39,8 @@ import com.mikepenz.google_material_typeface_library.GoogleMaterial import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.materialdrawer.AccountHeader import com.mikepenz.materialdrawer.Drawer +import com.pitchedapps.frost.BuildConfig +import com.pitchedapps.frost.R import com.pitchedapps.frost.contracts.ActivityWebContract import com.pitchedapps.frost.contracts.FileChooserContract import com.pitchedapps.frost.contracts.FileChooserDelegate @@ -107,7 +109,15 @@ class MainActivity : BaseActivity(), FrostWebViewSearch.SearchContract, super.onCreate(savedInstanceState) if (BuildConfig.VERSION_CODE > Prefs.versionCode) { Prefs.versionCode = BuildConfig.VERSION_CODE - if (!BuildConfig.DEBUG) showChangelog(R.xml.changelog, Prefs.textColor) { theme() } + if (!BuildConfig.DEBUG) { + showChangelog(R.xml.changelog, Prefs.textColor) { theme() } + frostAnswersCustom("Version") { + putCustomAttribute("Version code", BuildConfig.VERSION_CODE) + putCustomAttribute("Version name", BuildConfig.VERSION_NAME) + putCustomAttribute("Build type", BuildConfig.BUILD_TYPE) + putCustomAttribute("Frost id", Prefs.frostId) + } + } } setContentView(R.layout.activity_main) setSupportActionBar(toolbar) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/SelectorActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt index 103ae227..ff87f448 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/SelectorActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SelectorActivity.kt @@ -1,4 +1,4 @@ -package com.pitchedapps.frost +package com.pitchedapps.frost.activities import android.os.Bundle import android.support.constraint.ConstraintLayout @@ -10,6 +10,7 @@ import ca.allanwang.kau.utils.bindView import com.mikepenz.fastadapter.FastAdapter import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter import com.mikepenz.fastadapter.listeners.ClickEventHook +import com.pitchedapps.frost.R import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.utils.cookies import com.pitchedapps.frost.utils.launchNewTask diff --git a/app/src/main/kotlin/com/pitchedapps/frost/SettingsActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt index e0be330d..b3b3bd7c 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/SettingsActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt @@ -1,4 +1,4 @@ -package com.pitchedapps.frost +package com.pitchedapps.frost.activities import android.content.Intent import android.os.Bundle @@ -13,6 +13,8 @@ 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.settings.* import com.pitchedapps.frost.utils.* import com.pitchedapps.frost.utils.iab.* diff --git a/app/src/main/kotlin/com/pitchedapps/frost/WebOverlayActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt index 6c1fb5bd..f03c653c 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/WebOverlayActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt @@ -1,4 +1,4 @@ -package com.pitchedapps.frost +package com.pitchedapps.frost.activities import android.content.Intent import android.net.Uri @@ -18,6 +18,7 @@ import ca.allanwang.kau.swipe.kauSwipeOnPostCreate 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.R import com.pitchedapps.frost.contracts.ActivityWebContract import com.pitchedapps.frost.contracts.FileChooserContract import com.pitchedapps.frost.contracts.FileChooserDelegate diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbConst.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbConst.kt index e5216881..4d5127c5 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbConst.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbConst.kt @@ -8,6 +8,6 @@ const val FACEBOOK_COM = "facebook.com" const val FB_URL_BASE = "https://m.facebook.com/" fun PROFILE_PICTURE_URL(id: Long) = "https://graph.facebook.com/$id/picture?type=large" -const val USER_AGENT_BASIC_FULL = "Mozilla/5.0 (Linux; Android 4.4.2; en-us; SAMSUNG SM-G900T Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.6 Chrome/28.0.1500.94 Mobile Safari/537.36" +const val USER_AGENT_FULL = "Mozilla/5.0 (Linux; Android 4.4.2; en-us; SAMSUNG SM-G900T Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.6 Chrome/28.0.1500.94 Mobile Safari/537.36" const val USER_AGENT_BASIC = "Mozilla/5.0 (Linux; U; Android 2.3.3; en-gb; Nexus S Build/GRI20) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1" const val USER_AGENT_MESSENGER = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbUrlFormatter.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbUrlFormatter.kt index e53bb202..622be067 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbUrlFormatter.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbUrlFormatter.kt @@ -14,10 +14,10 @@ class FbUrlFormatter(url: String) { init { var cleanedUrl = url - discardable.forEach { cleanedUrl = cleanedUrl.replace(it, "") } + discardable.forEach { cleanedUrl = cleanedUrl.replace(it, "", true) } val changed = cleanedUrl != url //note that discardables strip away the first ? - decoder.forEach { (k, v) -> cleanedUrl = cleanedUrl.replace(k, v) } - val qm = cleanedUrl.indexOf(if (changed)"&" else "?") + decoder.forEach { (k, v) -> cleanedUrl = cleanedUrl.replace(k, v, true) } + val qm = cleanedUrl.indexOf(if (changed) "&" else "?") if (qm > -1) { cleanedUrl.substring(qm + 1).split("&").forEach { val p = it.split("=") @@ -72,7 +72,15 @@ class FbUrlFormatter(url: String) { "%60" to "`", "%3B" to ";", "%2F" to "/", "%3F" to "?", "%3A" to ":", "%40" to "@", "%3D" to "=", "%26" to "&", "%24" to "$", "%2B" to "+", "%22" to "\"", "%2C" to ",", - "%20" to " " + "%20" to " ", + //css + "\\3C " to "<", "\\3E " to ">", "\\23 " to "#", "\\25 " to "%", + "\\7B " to "{", "\\7D " to "}", "\\7C " to "|", "\\5C " to "\\", + "\\5E " to "^", "\\7E " to "~", "\\5B " to "[", "\\5D " to "]", + "\\60 " to "`", "\\3B " to ";", "\\2F " to "/", "\\3F " to "?", + "\\3A " to ":", "\\40 " to "@", "\\3D " to "=", "\\26 " to "&", + "\\24 " to "$", "\\2B " to "+", "\\22 " to "\"", "\\2C " to ",", + "\\20 " to " " ) } }
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt index 87afc434..239f5842 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt @@ -7,7 +7,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import ca.allanwang.kau.utils.withArguments -import com.pitchedapps.frost.MainActivity +import com.pitchedapps.frost.activities.MainActivity import com.pitchedapps.frost.facebook.FbTab import com.pitchedapps.frost.facebook.FeedSort import com.pitchedapps.frost.utils.Prefs 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 7b60a718..737b86ab 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt @@ -17,7 +17,7 @@ import ca.allanwang.kau.utils.string import com.bumptech.glide.request.target.SimpleTarget import com.bumptech.glide.request.transition.Transition import com.pitchedapps.frost.BuildConfig -import com.pitchedapps.frost.FrostWebActivity +import com.pitchedapps.frost.activities.FrostWebActivity import com.pitchedapps.frost.R import com.pitchedapps.frost.dbflow.CookieModel import com.pitchedapps.frost.dbflow.fetchUsername 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 e05d0dd3..e814e1ac 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt @@ -5,9 +5,9 @@ import ca.allanwang.kau.kpref.activity.items.KPrefColorPicker import ca.allanwang.kau.kpref.activity.items.KPrefSeekbar import ca.allanwang.kau.ui.views.RippleCanvas import ca.allanwang.kau.utils.string -import com.pitchedapps.frost.MainActivity +import com.pitchedapps.frost.activities.MainActivity import com.pitchedapps.frost.R -import com.pitchedapps.frost.SettingsActivity +import com.pitchedapps.frost.activities.SettingsActivity import com.pitchedapps.frost.injectors.CssAssets import com.pitchedapps.frost.utils.* import com.pitchedapps.frost.utils.iab.IS_FROST_PRO diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt index 7ce546b3..e7cf3598 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt @@ -1,9 +1,9 @@ package com.pitchedapps.frost.settings import ca.allanwang.kau.kpref.activity.KPrefAdapterBuilder -import com.pitchedapps.frost.MainActivity +import com.pitchedapps.frost.activities.MainActivity import com.pitchedapps.frost.R -import com.pitchedapps.frost.SettingsActivity +import com.pitchedapps.frost.activities.SettingsActivity import com.pitchedapps.frost.utils.Prefs /** diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt index 86bd356b..236d19f9 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt @@ -1,9 +1,9 @@ package com.pitchedapps.frost.settings import ca.allanwang.kau.kpref.activity.KPrefAdapterBuilder -import com.pitchedapps.frost.MainActivity +import com.pitchedapps.frost.activities.MainActivity import com.pitchedapps.frost.R -import com.pitchedapps.frost.SettingsActivity +import com.pitchedapps.frost.activities.SettingsActivity import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.Showcase @@ -20,10 +20,14 @@ fun SettingsActivity.getExperimentalPrefs(): KPrefAdapterBuilder.() -> Unit = { descRes = R.string.experimental_by_default_desc } + // Experimental content starts here ------------------ + checkbox(R.string.search_bar, { Prefs.searchBar }, { Prefs.searchBar = it; setResult(MainActivity.REQUEST_SEARCH) }) { descRes = R.string.search_bar_desc } + // Experimental content ends here -------------------- + checkbox(R.string.verbose_logging, { Prefs.verboseLogging }, { Prefs.verboseLogging = it }) { descRes = R.string.verbose_logging_desc } 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 29256950..689e6bdb 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt @@ -2,9 +2,9 @@ package com.pitchedapps.frost.settings import ca.allanwang.kau.kpref.activity.KPrefAdapterBuilder import ca.allanwang.kau.utils.string -import com.pitchedapps.frost.MainActivity +import com.pitchedapps.frost.activities.MainActivity import com.pitchedapps.frost.R -import com.pitchedapps.frost.SettingsActivity +import com.pitchedapps.frost.activities.SettingsActivity import com.pitchedapps.frost.facebook.FeedSort import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.materialDialogThemed diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt index b6105054..59ebf700 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Notifications.kt @@ -4,7 +4,7 @@ import ca.allanwang.kau.kpref.activity.KPrefAdapterBuilder import ca.allanwang.kau.utils.minuteToText import ca.allanwang.kau.utils.snackbar import com.pitchedapps.frost.R -import com.pitchedapps.frost.SettingsActivity +import com.pitchedapps.frost.activities.SettingsActivity import com.pitchedapps.frost.services.fetchNotifications import com.pitchedapps.frost.services.scheduleNotifications import com.pitchedapps.frost.utils.Prefs 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 d2e04898..f8c7af56 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt @@ -4,6 +4,7 @@ import ca.allanwang.kau.kotlin.lazyResettable import ca.allanwang.kau.kpref.KPref import ca.allanwang.kau.kpref.StringSet import ca.allanwang.kau.kpref.kpref +import ca.allanwang.kau.utils.colorToForeground import ca.allanwang.kau.utils.isColorVisibleOn import com.pitchedapps.frost.facebook.FeedSort import com.pitchedapps.frost.injectors.InjectorContract @@ -57,9 +58,24 @@ object Prefs : KPref() { val iconColor: Int get() = t.iconColor + /** + * Ensures that the color is visible against the background + */ val accentColor: Int get() = if (headerColor.isColorVisibleOn(bgColor, 100)) headerColor else textColor + /** + * Ensures that the color is visible against both the foreground and background + */ + val accentBackgroundColor: Int + get() { + if (headerColor.isColorVisibleOn(textColor, 100)) { + if (headerColor.isColorVisibleOn(bgColor, 100)) return headerColor + else return headerColor.colorToForeground(0.2f) + } + return bgColor.colorToForeground(0.2f) + } + val themeInjector: InjectorContract get() = t.injector 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 9a599945..c0db8308 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt @@ -8,19 +8,27 @@ import android.support.annotation.StringRes import android.support.design.internal.SnackbarContentLayout import android.support.design.widget.Snackbar import android.support.v7.widget.Toolbar +import android.util.Log import android.view.View import android.widget.FrameLayout import android.widget.TextView import ca.allanwang.kau.utils.* import com.afollestad.materialdialogs.MaterialDialog +import com.bumptech.glide.GlideBuilder import com.bumptech.glide.RequestBuilder +import com.bumptech.glide.annotation.GlideExtension import com.bumptech.glide.annotation.GlideModule import com.bumptech.glide.load.resource.bitmap.CircleCrop import com.bumptech.glide.module.AppGlideModule import com.bumptech.glide.request.RequestOptions import com.crashlytics.android.answers.Answers import com.crashlytics.android.answers.CustomEvent -import com.pitchedapps.frost.* +import com.pitchedapps.frost.BuildConfig +import com.pitchedapps.frost.R +import com.pitchedapps.frost.activities.ImageActivity +import com.pitchedapps.frost.activities.LoginActivity +import com.pitchedapps.frost.activities.SelectorActivity +import com.pitchedapps.frost.activities.WebOverlayActivity import com.pitchedapps.frost.dbflow.CookieModel import com.pitchedapps.frost.facebook.FbTab import com.pitchedapps.frost.facebook.formattedFbUrl @@ -31,6 +39,8 @@ import com.pitchedapps.frost.facebook.formattedFbUrl const val EXTRA_COOKIES = "extra_cookies" const val ARG_URL = "arg_url" const val ARG_USER_ID = "arg_user_id" +const val ARG_IMAGE_URL = "arg_image_url" +const val ARG_TEXT = "arg_text" @GlideModule class FrostGlideModule : AppGlideModule() @@ -59,6 +69,13 @@ fun Context.launchWebOverlay(url: String) { }) } +fun Context.launchImageActivity(imageUrl: String, text: String?) { + startActivity(ImageActivity::class.java, intentBuilder = { + putExtra(ARG_IMAGE_URL, imageUrl) + putExtra(ARG_TEXT, text) + }) +} + fun WebOverlayActivity.url(): String { return intent.extras?.getString(ARG_URL) ?: FbTab.FEED.url } @@ -131,4 +148,4 @@ fun Activity.frostNavigationBar() { navigationBarColor = if (Prefs.tintNavBar) Prefs.headerColor else Color.BLACK } -fun <T> RequestBuilder<T>.withRoundIcon() = apply(RequestOptions().transform(CircleCrop())) +fun <T> RequestBuilder<T>.withRoundIcon() = apply(RequestOptions().transform(CircleCrop()))
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt index 67c20a5a..17ea46a3 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt @@ -4,7 +4,8 @@ import android.content.Context import ca.allanwang.kau.utils.copyToClipboard import ca.allanwang.kau.utils.shareText import ca.allanwang.kau.utils.string -import com.pitchedapps.frost.MainActivity +import ca.allanwang.kau.utils.toast +import com.pitchedapps.frost.activities.MainActivity import com.pitchedapps.frost.R /** @@ -18,7 +19,10 @@ fun Context.showWebContextMenu(wc: WebContext) { materialDialogThemed { title(title) - items(WebContextType.values.map { this@showWebContextMenu.string(it.textId) }) + items(WebContextType.values.map { + if (it == WebContextType.COPY_TEXT && wc.text == null) return@map null + this@showWebContextMenu.string(it.textId) + }.filterNotNull()) itemsCallback { _, _, position, _ -> WebContextType[position].onClick(this@showWebContextMenu, wc) @@ -30,11 +34,11 @@ fun Context.showWebContextMenu(wc: WebContext) { } } -class WebContext(val url: String, val text: String) +class WebContext(val url: String, val text: String?) enum class WebContextType(val textId: Int, val onClick: (c: Context, wc: WebContext) -> Unit) { COPY_LINK(R.string.copy_link, { c, wc -> c.copyToClipboard(wc.url) }), - COPY_TEXT(R.string.copy_text, { c, wc -> c.copyToClipboard(wc.text) }), + COPY_TEXT(R.string.copy_text, { c, wc -> if (wc.text != null) c.copyToClipboard(wc.text) else c.toast(R.string.no_text) }), SHARE_LINK(R.string.share_link, { c, wc -> c.shareText(wc.url) }) ; diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IAB.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IAB.kt index 58c748c2..964e771c 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IAB.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IAB.kt @@ -9,7 +9,7 @@ import ca.allanwang.kau.utils.snackbar import com.crashlytics.android.answers.PurchaseEvent import com.pitchedapps.frost.BuildConfig import com.pitchedapps.frost.R -import com.pitchedapps.frost.SettingsActivity +import com.pitchedapps.frost.activities.SettingsActivity import com.pitchedapps.frost.utils.* /** 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 index 4f65b7f8..fae2f6bb 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABDialogs.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABDialogs.kt @@ -4,9 +4,9 @@ import android.app.Activity import ca.allanwang.kau.utils.restart import ca.allanwang.kau.utils.startPlayStoreLink import ca.allanwang.kau.utils.string -import com.pitchedapps.frost.MainActivity +import com.pitchedapps.frost.activities.MainActivity import com.pitchedapps.frost.R -import com.pitchedapps.frost.SettingsActivity +import com.pitchedapps.frost.activities.SettingsActivity import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.materialDialogThemed diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/BaseWebViewClient.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/BaseWebViewClient.kt new file mode 100644 index 00000000..09241254 --- /dev/null +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/BaseWebViewClient.kt @@ -0,0 +1,16 @@ +package com.pitchedapps.frost.web + +import android.webkit.WebResourceRequest +import android.webkit.WebResourceResponse +import android.webkit.WebView +import android.webkit.WebViewClient + +/** + * Created by Allan Wang on 2017-07-13. + */ +open class BaseWebViewClient : WebViewClient() { + + override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? + = shouldFrostInterceptRequest(view, request) + +}
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClient.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClient.kt index aab3a165..4df6d6a7 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClient.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClient.kt @@ -1,9 +1,10 @@ package com.pitchedapps.frost.web import android.net.Uri -import android.os.Message -import android.view.View -import android.webkit.* +import android.webkit.ConsoleMessage +import android.webkit.ValueCallback +import android.webkit.WebChromeClient +import android.webkit.WebView import ca.allanwang.kau.utils.snackbar import com.pitchedapps.frost.contracts.ActivityWebContract import com.pitchedapps.frost.utils.L @@ -20,9 +21,16 @@ class FrostChromeClient(webCore: FrostWebViewCore) : WebChromeClient() { val titleObservable: BehaviorSubject<String> = webCore.titleObservable val activityContract = (webCore.context as? ActivityWebContract) + companion object { + val consoleBlacklist = setOf( + "edge-chat" + ) + } + override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean { + if (consoleBlacklist.any { consoleMessage.message().contains(it) }) return true L.i("Chrome Console ${consoleMessage.lineNumber()}: ${consoleMessage.message()}") - return super.onConsoleMessage(consoleMessage) + return true } override fun onReceivedTitle(view: WebView, title: String) { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt index 3340e7d2..3f976fb8 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt @@ -2,8 +2,9 @@ package com.pitchedapps.frost.web import android.content.Context import android.webkit.JavascriptInterface -import ca.allanwang.kau.logging.KL -import com.pitchedapps.frost.MainActivity +import ca.allanwang.kau.utils.startActivity +import com.pitchedapps.frost.activities.ImageActivity +import com.pitchedapps.frost.activities.MainActivity import com.pitchedapps.frost.dbflow.CookieModel import com.pitchedapps.frost.facebook.formattedFbUrl import com.pitchedapps.frost.utils.* @@ -13,12 +14,18 @@ import io.reactivex.subjects.Subject /** * Created by Allan Wang on 2017-06-01. */ -class FrostJSI(val context: Context, val webView: FrostWebViewCore) { +class FrostJSI(val webView: FrostWebViewCore) { - val headerObservable: Subject<String>? = (context as? MainActivity)?.headerBadgeObservable + val context: Context + get() = webView.context + + val activity: MainActivity? + get() = (context as? MainActivity) + + val headerObservable: Subject<String>? = activity?.headerBadgeObservable val cookies: ArrayList<CookieModel> - get() = (context as? MainActivity)?.cookies() ?: arrayListOf() + get() = activity?.cookies() ?: arrayListOf() @JavascriptInterface fun loadUrl(url: String) { @@ -35,8 +42,8 @@ class FrostJSI(val context: Context, val webView: FrostWebViewCore) { } @JavascriptInterface - fun contextMenu(url: String, text: String) { - webView.post { webView.context.showWebContextMenu(WebContext(url.formattedFbUrl, text)) } + fun contextMenu(url: String, text: String?) { + webView.post { context.showWebContextMenu(WebContext(url.formattedFbUrl, text)) } } /** @@ -45,7 +52,7 @@ class FrostJSI(val context: Context, val webView: FrostWebViewCore) { */ @JavascriptInterface fun longClick(start: Boolean) { - (webView.context as? MainActivity)?.viewPager?.enableSwipe = !start + activity?.viewPager?.enableSwipe = !start } @JavascriptInterface @@ -53,6 +60,14 @@ class FrostJSI(val context: Context, val webView: FrostWebViewCore) { context.launchLogin(cookies, true) } + /** + * Launch image overlay + */ + @JavascriptInterface + fun loadImage(imageUrl: String, text: String?) { + context.launchImageActivity(imageUrl, text) + } + @JavascriptInterface fun emit(flag: Int) { webView.post { webView.frostWebClient.emit(flag) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt new file mode 100644 index 00000000..45dc83aa --- /dev/null +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt @@ -0,0 +1,67 @@ +package com.pitchedapps.frost.web + +import android.graphics.Bitmap.CompressFormat +import android.webkit.WebResourceRequest +import android.webkit.WebResourceResponse +import android.webkit.WebView +import ca.allanwang.kau.utils.use +import com.pitchedapps.frost.utils.GlideApp +import com.pitchedapps.frost.utils.L +import com.pitchedapps.frost.utils.Prefs +import okhttp3.HttpUrl +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.InputStream + + +/** + * Created by Allan Wang on 2017-07-13. + * + * Handler to decide when a request should be done by us + * This is the crux of Frost's optimizations for the web browser + */ +val blankResource: WebResourceResponse by lazy { WebResourceResponse("text/plain", "utf-8", ByteArrayInputStream("".toByteArray())) } + +//these hosts will redirect to a blank resource +val blacklistHost: Set<String> by lazy { + setOf( + "edge-chat.facebook.com" + ) +} + +//these hosts will return null and skip logging +val whitelistHost: Set<String> by lazy { + setOf( + "static.xx.fbcdn.net", + "m.facebook.com", + "touch.facebook.com" + ) +} + +//these hosts will skip ad inspection +//this list does not have to include anything from the two above +val adWhitelistHost: Set<String> by lazy { + setOf( + "scontent-sea1-1.xx.fbcdn.net" + ) +} + +var adblock: Set<String>? = null + +fun shouldFrostInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? { + val httpUrl = HttpUrl.parse(request.url?.toString() ?: return null) ?: return null + val host = httpUrl.host() + val url = httpUrl.toString() + if (blacklistHost.contains(host)) return blankResource + if (whitelistHost.contains(host)) return null + if (!adWhitelistHost.contains(host)) { + if (adblock == null) adblock = view.context.assets.open("adblock.txt").bufferedReader().use { it.readLines().toSet() } + if (adblock?.any { url.contains(it) } ?: false) return blankResource + } + L.v("Intercept Request ${host} ${url}") + return null +} + +fun WebResourceResponse?.filterCss(request: WebResourceRequest): WebResourceResponse? + = this ?: if (request.url.path.endsWith(".css")) blankResource else null + diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt index 7c0a6597..e7dae22a 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt @@ -69,7 +69,7 @@ class FrostWebView @JvmOverloads constructor( frostWebClient = baseEnum?.webClient?.invoke(this) ?: FrostWebViewClient(this) webViewClient = frostWebClient webChromeClient = FrostChromeClient(this) - addJavascriptInterface(FrostJSI(context, this), "Frost") + addJavascriptInterface(FrostJSI(this), "Frost") setBackgroundColor(Color.TRANSPARENT) } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt index 5e5dc597..5b2b4bfd 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt @@ -4,10 +4,9 @@ import android.content.Context import android.graphics.Bitmap import android.webkit.WebResourceRequest import android.webkit.WebView -import android.webkit.WebViewClient -import com.pitchedapps.frost.LoginActivity -import com.pitchedapps.frost.MainActivity -import com.pitchedapps.frost.SelectorActivity +import com.pitchedapps.frost.activities.LoginActivity +import com.pitchedapps.frost.activities.MainActivity +import com.pitchedapps.frost.activities.SelectorActivity import com.pitchedapps.frost.facebook.FACEBOOK_COM import com.pitchedapps.frost.facebook.FbCookie import com.pitchedapps.frost.injectors.* @@ -17,7 +16,7 @@ import io.reactivex.subjects.Subject /** * Created by Allan Wang on 2017-05-31. */ -open class FrostWebViewClient(val webCore: FrostWebViewCore) : WebViewClient() { +open class FrostWebViewClient(val webCore: FrostWebViewCore) : BaseWebViewClient() { val refreshObservable: Subject<Boolean> = webCore.refreshObservable @@ -97,15 +96,9 @@ open class FrostWebViewClient(val webCore: FrostWebViewCore) : WebViewClient() { return super.shouldOverrideUrlLoading(view, request) } - override fun onPageCommitVisible(view: WebView?, url: String?) { - L.d("ASDF PCV") - super.onPageCommitVisible(view, url) - } - -// override fun onLoadResource(view: WebView, url: String) { -// L.v("Load resource $url") -// super.onLoadResource(view, url) +// override fun onPageCommitVisible(view: WebView?, url: String?) { +// L.d("ASDF PCV") +// super.onPageCommitVisible(view, url) // } - }
\ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt index 1e023dca..d96fba55 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt @@ -72,7 +72,7 @@ class FrostWebViewCore @JvmOverloads constructor( dispose = refreshObservable.subscribeOn(AndroidSchedulers.mainThread()).subscribe { if (it) { loading = true - if (isVisible()) fadeOut(duration = 200L) + if (isVisible) fadeOut(duration = 200L) } else if (loading) { dispose?.dispose() if (animate && Prefs.animate) circularReveal(offset = 150L) @@ -148,11 +148,12 @@ class FrostWebViewCore @JvmOverloads constructor( if (scrollY > 10000) { scrollTo(0, 0) } else { - val animator = ValueAnimator.ofInt(scrollY, 0) - animator.duration = Math.min(scrollY, 500).toLong() - animator.interpolator = DecelerateInterpolator() - animator.addUpdateListener { scrollY = it.animatedValue as Int } - animator.start() + ValueAnimator.ofInt(scrollY, 0).apply { + duration = Math.min(scrollY, 500).toLong() + interpolator = DecelerateInterpolator() + addUpdateListener { scrollY = it.animatedValue as Int } + start() + } } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewSearch.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewSearch.kt index b3b1cfe5..bcadf32a 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewSearch.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewSearch.kt @@ -3,9 +3,7 @@ package com.pitchedapps.frost.web import android.annotation.SuppressLint import android.content.Context import android.view.View -import android.webkit.JavascriptInterface -import android.webkit.WebView -import android.webkit.WebViewClient +import android.webkit.* import ca.allanwang.kau.searchview.SearchItem import ca.allanwang.kau.utils.gone import com.pitchedapps.frost.facebook.FbTab @@ -56,7 +54,8 @@ class FrostWebViewSearch(context: Context, val contract: SearchContract) : WebVi settings.javaScriptEnabled = true settings.userAgentString = USER_AGENT_BASIC setLayerType(View.LAYER_TYPE_HARDWARE, null) - webViewClient = FrostWebViewClientSearch() + webViewClient = SearchWebViewClient() + webChromeClient = SearchChromeClient() addJavascriptInterface(SearchJSI(), "Frost") searchSubject.debounce(300, TimeUnit.MILLISECONDS).subscribeOn(Schedulers.newThread()) .map { @@ -111,13 +110,22 @@ class FrostWebViewSearch(context: Context, val contract: SearchContract) : WebVi * * Barebones client that does what [FrostWebViewSearch] needs */ - inner class FrostWebViewClientSearch : WebViewClient() { + inner class SearchWebViewClient : BaseWebViewClient() { override fun onPageFinished(view: WebView, url: String) { super.onPageFinished(view, url) L.i("Search Page finished $url") view.jsInject(JsAssets.SEARCH) } + + override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? + = super.shouldInterceptRequest(view, request).filterCss(request) + } + + class SearchChromeClient : WebChromeClient() { + + //mute console + override fun onConsoleMessage(consoleMessage: ConsoleMessage) = true } inner class SearchJSI { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt index 38d4ad8c..d7a2db0a 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt @@ -66,7 +66,7 @@ class LoginWebView @JvmOverloads constructor( } - inner class LoginClient : WebViewClient() { + inner class LoginClient : BaseWebViewClient() { override fun onPageFinished(view: WebView, url: String) { super.onPageFinished(view, url) @@ -88,7 +88,7 @@ class LoginWebView @JvmOverloads constructor( inner class LoginChromeClient : WebChromeClient() { override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean { L.d("Login Console ${consoleMessage.lineNumber()}: ${consoleMessage.message()}") - return super.onConsoleMessage(consoleMessage) + return true } override fun onProgressChanged(view: WebView, newProgress: Int) { |