aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/kotlin/com/pitchedapps
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/kotlin/com/pitchedapps')
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt1
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt35
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/ImagePickerActivity.kt12
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt7
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt31
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/contracts/FileChooser.kt42
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt6
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt6
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt6
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt4
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt22
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABBinder.kt103
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABDialogs.kt11
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt3
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt27
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt7
20 files changed, 210 insertions, 121 deletions
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 b21cc3ab..80d2aa48 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/AboutActivity.kt
@@ -40,6 +40,7 @@ class AboutActivity : AboutActivityBase(null, {
val include = arrayOf(
"AboutLibraries",
"AndroidIconics",
+ "androidin_appbillingv3",
"androidslidinguppanel",
"Crashlytics",
"dbflow",
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 79d9f782..a7c59deb 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt
@@ -15,6 +15,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.ProgressBar
import android.widget.TextView
+import ca.allanwang.kau.email.sendEmail
import ca.allanwang.kau.permissions.PERMISSION_WRITE_EXTERNAL_STORAGE
import ca.allanwang.kau.permissions.kauOnRequestPermissionsResult
import ca.allanwang.kau.permissions.kauRequestPermissions
@@ -30,10 +31,7 @@ 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.ARG_IMAGE_URL
-import com.pitchedapps.frost.utils.ARG_TEXT
-import com.pitchedapps.frost.utils.L
-import com.pitchedapps.frost.utils.Prefs
+import com.pitchedapps.frost.utils.*
import com.sothree.slidinguppanel.SlidingUpPanelLayout
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread
@@ -194,6 +192,7 @@ class ImageActivity : AppCompatActivity() {
var success = true
try {
File(tempFilePath).copyTo(destination, true)
+ scanFile(destination)
} catch (e: Exception) {
success = false
} finally {
@@ -201,10 +200,7 @@ class ImageActivity : AppCompatActivity() {
uiThread {
val text = if (success) R.string.image_download_success else R.string.image_download_fail
snackbar(text)
- if (success) {
- deleteTempFile()
- fabAction = FabStates.SHARE
- }
+ if (success) fabAction = FabStates.SHARE
}
}
}
@@ -212,6 +208,17 @@ class ImageActivity : AppCompatActivity() {
}
}
+ /**
+ * See <a href="https://developer.android.com/training/camera/photobasics.html#TaskGallery">Docs</a>
+ */
+ internal fun scanFile(file: File) {
+ if (!file.exists()) return
+ val mediaScanIntent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
+ val contentUri = Uri.fromFile(file)
+ mediaScanIntent.data = contentUri
+ this.sendBroadcast(mediaScanIntent)
+ }
+
internal fun deleteTempFile() {
if (tempFilePath != null) {
File(tempFilePath!!).delete()
@@ -233,7 +240,17 @@ class ImageActivity : AppCompatActivity() {
internal enum class FabStates(val iicon: IIcon, val iconColor: Int = Prefs.iconColor, val backgroundTint: Int = Prefs.iconBackgroundColor.withAlpha(255)) {
ERROR(GoogleMaterial.Icon.gmd_error, Color.WHITE, Color.RED) {
override fun onClick(activity: ImageActivity) {
- //todo add something
+ activity.materialDialogThemed {
+ title(R.string.kau_error)
+ content(R.string.bad_image_overlay)
+ positiveText(R.string.kau_yes)
+ onPositive { _, _ ->
+ activity.sendEmail(R.string.dev_email, R.string.debug_image_link_subject) {
+ addItem("Url", activity.imageUrl)
+ }
+ }
+ negativeText(R.string.kau_no)
+ }
}
},
NOTHING(GoogleMaterial.Icon.gmd_adjust) {
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImagePickerActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImagePickerActivity.kt
new file mode 100644
index 00000000..f18d358e
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImagePickerActivity.kt
@@ -0,0 +1,12 @@
+package com.pitchedapps.frost.activities
+
+import android.content.res.ColorStateList
+import android.os.Bundle
+import ca.allanwang.kau.imagepicker.ImagePickerActivityBase
+import ca.allanwang.kau.imagepicker.ImagePickerActivityOverlayBase
+import com.pitchedapps.frost.utils.Prefs
+
+/**
+ * Created by Allan Wang on 2017-07-23.
+ */
+class ImagePickerActivity : ImagePickerActivityOverlayBase() \ No newline at end of file
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 e4897be5..2dccbeb5 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt
@@ -106,7 +106,7 @@ class LoginActivity : BaseActivity() {
fun loadProfile(id: Long) {
- Glide.with(this@LoginActivity).load(PROFILE_PICTURE_URL(id)).withRoundIcon().listener(object : RequestListener<Drawable> {
+ Glide.with(profile).load(PROFILE_PICTURE_URL(id)).withRoundIcon().listener(object : RequestListener<Drawable> {
override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
profileObservable.onSuccess(true)
return false
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt
index a45bd033..978659db 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt
@@ -1,12 +1,12 @@
package com.pitchedapps.frost.activities
+import android.annotation.SuppressLint
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.drawable.ColorDrawable
import android.net.Uri
-import android.os.Build
import android.os.Bundle
import android.support.annotation.StringRes
import android.support.design.widget.AppBarLayout
@@ -392,9 +392,10 @@ class MainActivity : BaseActivity(), SearchWebView.SearchContract,
}
override fun openFileChooser(filePathCallback: ValueCallback<Array<Uri>>, fileChooserParams: WebChromeClient.FileChooserParams) {
- openFileChooser(this, filePathCallback, fileChooserParams)
+ openImagePicker(filePathCallback, fileChooserParams)
}
+ @SuppressLint("NewApi")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (onActivityResultWeb(requestCode, resultCode, data)) return
super.onActivityResult(requestCode, resultCode, data)
@@ -405,7 +406,7 @@ class MainActivity : BaseActivity(), SearchWebView.SearchContract,
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
val pending = PendingIntent.getActivity(this, 666, intent, PendingIntent.FLAG_CANCEL_CURRENT)
val alarm = getSystemService(Context.ALARM_SERVICE) as AlarmManager
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
+ if (buildIsMarshmallowAndUp)
alarm.setExactAndAllowWhileIdle(AlarmManager.RTC, System.currentTimeMillis() + 100, pending)
else
alarm.setExact(AlarmManager.RTC, System.currentTimeMillis() + 100, pending)
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 a7ca6ce5..d073050b 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt
@@ -1,9 +1,11 @@
package com.pitchedapps.frost.activities
+import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
+import ca.allanwang.kau.about.kauLaunchAbout
import ca.allanwang.kau.changelog.showChangelog
import ca.allanwang.kau.kpref.activity.CoreAttributeContract
import ca.allanwang.kau.kpref.activity.KPrefActivity
@@ -27,11 +29,12 @@ import com.pitchedapps.frost.utils.iab.IS_FROST_PRO
*/
class SettingsActivity : KPrefActivity(), FrostBilling by IABSettings() {
+ var resultFlag = Activity.RESULT_CANCELED
+
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- if (!onActivityResultBilling(requestCode, resultCode, data)) {
+ if (!onActivityResultBilling(requestCode, resultCode, data))
super.onActivityResult(requestCode, resultCode, data)
- adapter.notifyDataSetChanged()
- }
+ adapter.notifyDataSetChanged()
}
override fun kPrefCoreAttributes(): CoreAttributeContract.() -> Unit = {
@@ -65,15 +68,15 @@ class SettingsActivity : KPrefActivity(), FrostBilling by IABSettings() {
iicon = CommunityMaterial.Icon.cmd_flask_outline
}
- plainText(R.string.restore_purchases) {
- descRes = R.string.restore_purchases_desc
- iicon = GoogleMaterial.Icon.gmd_refresh
- onClick = { _, _, _ -> restorePurchases(false); true }
+ plainText(R.string.get_pro) {
+ descRes = R.string.get_pro_desc
+ iicon = GoogleMaterial.Icon.gmd_star
+ onClick = { _, _, _ -> restorePurchases(); true }
}
plainText(R.string.about_frost) {
iicon = GoogleMaterial.Icon.gmd_info
- onClick = { _, _, _ -> startActivity(AboutActivity::class.java, transition = true); true }
+ onClick = { _, _, _ -> kauLaunchAbout(AboutActivity::class.java); true }
}
if (BuildConfig.DEBUG) {
@@ -87,7 +90,7 @@ class SettingsActivity : KPrefActivity(), FrostBilling by IABSettings() {
}
fun shouldRestartMain() {
- setResult(MainActivity.REQUEST_RESTART)
+ setFrostResult(MainActivity.REQUEST_RESTART)
}
override fun onCreate(savedInstanceState: Bundle?) {
@@ -107,10 +110,14 @@ class SettingsActivity : KPrefActivity(), FrostBilling by IABSettings() {
}
override fun onBackPressed() {
- if (!super.backPress())
+ if (!super.backPress()) {
+ setResult(resultFlag)
finishSlideOut()
+ }
}
+
+
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_settings, menu)
toolbar.tint(Prefs.iconColor)
@@ -135,6 +142,10 @@ class SettingsActivity : KPrefActivity(), FrostBilling by IABSettings() {
return true
}
+ fun setFrostResult(flag: Int) {
+ resultFlag = resultFlag and flag
+ }
+
override fun onDestroy() {
onDestroyBilling()
super.onDestroy()
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt
index f03c653c..13d72ffe 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/WebOverlayActivity.kt
@@ -126,7 +126,7 @@ open class WebOverlayActivity : AppCompatActivity(),
}
override fun openFileChooser(filePathCallback: ValueCallback<Array<Uri>>, fileChooserParams: WebChromeClient.FileChooserParams) {
- openFileChooser(this, filePathCallback, fileChooserParams)
+ openImagePicker(filePathCallback, fileChooserParams)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/contracts/FileChooser.kt b/app/src/main/kotlin/com/pitchedapps/frost/contracts/FileChooser.kt
index 5b2cfa49..bd31d6ce 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/contracts/FileChooser.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/contracts/FileChooser.kt
@@ -5,14 +5,16 @@ import android.content.Intent
import android.net.Uri
import android.webkit.ValueCallback
import android.webkit.WebChromeClient
-import ca.allanwang.kau.permissions.PERMISSION_READ_EXTERNAL_STORAGE
-import ca.allanwang.kau.permissions.kauRequestPermissions
+import ca.allanwang.kau.imagepicker.kauLaunchImagePicker
+import ca.allanwang.kau.imagepicker.kauOnImagePickerResult
+import com.pitchedapps.frost.activities.ImagePickerActivity
import com.pitchedapps.frost.utils.L
+import java.io.File
/**
* Created by Allan Wang on 2017-07-04.
*/
-const val FILE_CHOOSER_REQUEST = 67
+const val IMAGE_CHOOSER_REQUEST = 67
interface FileChooserActivityContract {
fun openFileChooser(filePathCallback: ValueCallback<Array<Uri>>, fileChooserParams: WebChromeClient.FileChooserParams)
@@ -20,35 +22,27 @@ interface FileChooserActivityContract {
interface FileChooserContract {
var filePathCallback: ValueCallback<Array<Uri>>?
- fun openFileChooser(activity: Activity, filePathCallback: ValueCallback<Array<Uri>>, fileChooserParams: WebChromeClient.FileChooserParams)
- fun onActivityResultWeb(requestCode: Int, resultCode: Int, intent: Intent?): Boolean
+ fun Activity.openImagePicker(filePathCallback: ValueCallback<Array<Uri>>, fileChooserParams: WebChromeClient.FileChooserParams)
+ fun Activity.onActivityResultWeb(requestCode: Int, resultCode: Int, intent: Intent?): Boolean
}
class FileChooserDelegate : FileChooserContract {
override var filePathCallback: ValueCallback<Array<Uri>>? = null
- override fun openFileChooser(activity: Activity, filePathCallback: ValueCallback<Array<Uri>>, fileChooserParams: WebChromeClient.FileChooserParams) {
- activity.kauRequestPermissions(PERMISSION_READ_EXTERNAL_STORAGE) {
- granted, _ ->
- if (!granted) return@kauRequestPermissions
- val contentSelectionIntent = Intent(Intent.ACTION_GET_CONTENT)
- contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE)
- contentSelectionIntent.type = fileChooserParams.acceptTypes?.joinToString(separator = "|") ?: "*/*"
- activity.startActivityForResult(contentSelectionIntent, FILE_CHOOSER_REQUEST)
- this.filePathCallback?.onReceiveValue(null)
- this.filePathCallback = filePathCallback
- }
+ override fun Activity.openImagePicker(filePathCallback: ValueCallback<Array<Uri>>, fileChooserParams: WebChromeClient.FileChooserParams) {
+ this@FileChooserDelegate.filePathCallback = filePathCallback
+ kauLaunchImagePicker(ImagePickerActivity::class.java, IMAGE_CHOOSER_REQUEST)
}
- override fun onActivityResultWeb(requestCode: Int, resultCode: Int, intent: Intent?): Boolean {
- L.d("On activity results web $requestCode")
- if (requestCode != FILE_CHOOSER_REQUEST) return false
- var results: Uri? = null
-
- if (resultCode == Activity.RESULT_OK && intent != null) results = Uri.parse(intent.dataString)
- L.d("Callback received; ${filePathCallback != null}")
- filePathCallback?.onReceiveValue(if (results == null) null else arrayOf(results))
+ override fun Activity.onActivityResultWeb(requestCode: Int, resultCode: Int, intent: Intent?): Boolean {
+ L.d("FileChooser On activity results web $requestCode")
+ if (requestCode != IMAGE_CHOOSER_REQUEST) return false
+ val results = kauOnImagePickerResult(resultCode, intent).map { it.uri }.toTypedArray()
+ L.d("FileChooser result ${results.contentToString()}")
+ //proper path content://com.android.providers.media.documents/document/image%3A36341
+ L.d("FileChooser Callback received; ${filePathCallback != null}")
+ filePathCallback?.onReceiveValue(results)
filePathCallback = null
return true
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt
index e8a3128d..a926c8ac 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt
@@ -8,7 +8,7 @@ import android.webkit.WebView
* List of elements to hide
*/
enum class CssHider(vararg val items: String) : InjectorContract {
- CORE("[data-sigil=m_login_upsell]"),
+ CORE("[data-sigil=m_login_upsell]", "role=progressbar"),
HEADER("#header[data-sigil=MTopBlueBarHeader]", "#header-notices", "[data-sigil*=m-promo-jewel-header]"),
ADS(
"article[data-xt*=sponsor]",
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 d38270f7..9c9754bb 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt
@@ -108,7 +108,7 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = {
checkbox(R.string.rounded_icons, { Prefs.showRoundedIcons }, {
Prefs.showRoundedIcons = it
- setResult(MainActivity.REQUEST_REFRESH)
+ setFrostResult(MainActivity.REQUEST_REFRESH)
}) {
descRes = R.string.rounded_icons_desc
}
@@ -116,7 +116,7 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = {
checkbox(R.string.tint_nav, { Prefs.tintNavBar }, {
Prefs.tintNavBar = it
frostNavigationBar()
- setResult(MainActivity.REQUEST_NAV)
+ setFrostResult(MainActivity.REQUEST_NAV)
}) {
descRes = R.string.tint_nav_desc
}
@@ -124,5 +124,5 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = {
list.add(KPrefTextSeekbar(
KPrefSeekbar.KPrefSeekbarBuilder(
globalOptions,
- R.string.web_text_scaling, { Prefs.webTextScaling }, { Prefs.webTextScaling = it; setResult(MainActivity.REQUEST_WEB_ZOOM) })))
+ R.string.web_text_scaling, { Prefs.webTextScaling }, { Prefs.webTextScaling = it; setFrostResult(MainActivity.REQUEST_WEB_ZOOM) })))
} \ No newline at end of file
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 00ff00c3..2af67602 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Behaviour.kt
@@ -15,7 +15,7 @@ fun SettingsActivity.getBehaviourPrefs(): KPrefAdapterBuilder.() -> Unit = {
descRes = R.string.fancy_animations_desc
}
- checkbox(R.string.overlay_swipe, { Prefs.overlayEnabled }, { Prefs.overlayEnabled = it; setResult(MainActivity.REQUEST_REFRESH) }) {
+ checkbox(R.string.overlay_swipe, { Prefs.overlayEnabled }, { Prefs.overlayEnabled = it; setFrostResult(MainActivity.REQUEST_REFRESH) }) {
descRes = R.string.overlay_swipe_desc
}
@@ -27,6 +27,10 @@ fun SettingsActivity.getBehaviourPrefs(): KPrefAdapterBuilder.() -> Unit = {
descRes = R.string.viewpager_swipe_desc
}
+ checkbox(R.string.search_bar, { Prefs.searchBar }, { Prefs.searchBar = it; setFrostResult(MainActivity.REQUEST_SEARCH) }) {
+ descRes = R.string.search_bar_desc
+ }
+
checkbox(R.string.exit_confirmation, { Prefs.exitConfirmation }, { Prefs.exitConfirmation = it }) {
descRes = R.string.exit_confirmation_desc
}
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 c780948d..05a852ee 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Experimental.kt
@@ -22,9 +22,7 @@ fun SettingsActivity.getExperimentalPrefs(): KPrefAdapterBuilder.() -> Unit = {
// 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 --------------------
@@ -36,7 +34,7 @@ fun SettingsActivity.getExperimentalPrefs(): KPrefAdapterBuilder.() -> Unit = {
descRes = R.string.restart_frost_desc
onClick = {
_, _, _ ->
- setResult(MainActivity.REQUEST_RESTART_APPLICATION)
+ setFrostResult(MainActivity.REQUEST_RESTART_APPLICATION)
finish()
true
}
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 9b214c26..a80642bb 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Feed.kt
@@ -39,7 +39,7 @@ fun SettingsActivity.getFeedPrefs(): KPrefAdapterBuilder.() -> Unit = {
checkbox(R.string.suggested_friends, { Prefs.showSuggestedFriends }, {
Prefs.showSuggestedFriends = it
- setResult(MainActivity.REQUEST_REFRESH)
+ setFrostResult(MainActivity.REQUEST_REFRESH)
}) {
descRes = R.string.suggested_friends_desc
dependsOnPro()
@@ -47,7 +47,7 @@ fun SettingsActivity.getFeedPrefs(): KPrefAdapterBuilder.() -> Unit = {
checkbox(R.string.facebook_ads, { Prefs.showFacebookAds }, {
Prefs.showFacebookAds = it
- setResult(MainActivity.REQUEST_REFRESH)
+ setFrostResult(MainActivity.REQUEST_REFRESH)
}) {
descRes = R.string.facebook_ads_desc
dependsOnPro()
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 63e57554..a20e755f 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt
@@ -119,7 +119,7 @@ object Prefs : KPref() {
var analytics: Boolean by kpref("analytics", true)
- var searchBar: Boolean by kpref("search_bar", Showcase.experimentalDefault)
+ var searchBar: Boolean by kpref("search_bar", true)
var overlayEnabled: Boolean by kpref("overlay_enabled", true)
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 40de99bf..ea66030f 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt
@@ -1,12 +1,14 @@
package com.pitchedapps.frost.utils
import android.content.Context
+import ca.allanwang.kau.email.sendEmail
import ca.allanwang.kau.utils.copyToClipboard
import ca.allanwang.kau.utils.shareText
import ca.allanwang.kau.utils.string
import ca.allanwang.kau.utils.toast
import com.pitchedapps.frost.R
import com.pitchedapps.frost.activities.MainActivity
+import com.pitchedapps.frost.facebook.formattedFbUrl
/**
* Created by Allan Wang on 2017-07-07.
@@ -34,12 +36,28 @@ fun Context.showWebContextMenu(wc: WebContext) {
}
}
-class WebContext(val url: String, val text: String?)
+class WebContext(val unformattedUrl: String, val text: String?) {
+ val url = unformattedUrl.formattedFbUrl
+}
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 -> 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) })
+ SHARE_LINK(R.string.share_link, { c, wc -> c.shareText(wc.url) }),
+ DEBUG_LINK(R.string.debug_link, { c, wc ->
+ c.materialDialogThemed {
+ title(R.string.debug_link)
+ content(R.string.debug_link_desc)
+ positiveText(R.string.kau_ok)
+ onPositive { _, _ ->
+ c.sendEmail(R.string.dev_email, R.string.debug_link_subject) {
+ message = c.string(R.string.debug_link_content)
+ addItem("Unformatted url", wc.unformattedUrl)
+ addItem("Formatted url", wc.url)
+ }
+ }
+ }
+ })
;
companion object {
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 53d3e058..ab9e37d1 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,8 +9,6 @@ import com.pitchedapps.frost.BuildConfig
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.Prefs
import com.pitchedapps.frost.utils.frostAnswers
-import org.jetbrains.anko.doAsync
-import org.jetbrains.anko.uiThread
/**
* Created by Allan Wang on 2017-07-22.
@@ -24,18 +22,18 @@ interface FrostBilling : BillingProcessor.IBillingHandler {
fun Activity.onCreateBilling()
fun onDestroyBilling()
fun purchasePro()
- fun restorePurchases(once: Boolean)
+ fun restorePurchases()
fun onActivityResultBilling(requestCode: Int, resultCode: Int, data: Intent?): Boolean
}
-open class IABBinder : FrostBilling {
+abstract class IABBinder : FrostBilling {
var bp: BillingProcessor? = null
var activity: Activity? = null
override fun Activity.onCreateBilling() {
- bp = BillingProcessor.newBillingProcessor(this, PUBLIC_BILLING_KEY, this@IABBinder)
activity = this
+ bp = BillingProcessor.newBillingProcessor(this, PUBLIC_BILLING_KEY, this@IABBinder)
bp!!.initialize()
}
@@ -45,15 +43,11 @@ open class IABBinder : FrostBilling {
activity = null
}
- override fun onBillingInitialized() {
- L.d("IAB initialized")
- }
+ override fun onBillingInitialized() = L.d("IAB initialized")
- override fun onPurchaseHistoryRestored() {
- L.d("IAB restored")
- }
+ override fun onPurchaseHistoryRestored() = L.d("IAB restored")
- override fun onProductPurchased(productId: String, details: TransactionDetails) {
+ override fun onProductPurchased(productId: String, details: TransactionDetails?) {
L.d("IAB $productId purchased")
frostAnswers {
logPurchase(PurchaseEvent()
@@ -63,7 +57,7 @@ open class IABBinder : FrostBilling {
}
}
- override fun onBillingError(errorCode: Int, error: Throwable) {
+ override fun onBillingError(errorCode: Int, error: Throwable?) {
frostAnswers {
logPurchase(PurchaseEvent()
.putCustomAttribute("result", errorCode.toString())
@@ -76,64 +70,81 @@ open class IABBinder : FrostBilling {
= bp?.handleActivityResult(requestCode, resultCode, data) ?: false
override fun purchasePro() {
- if (bp == null) return
+ if (bp == null) {
+ frostAnswers {
+ logPurchase(PurchaseEvent()
+ .putCustomAttribute("result", "null bp")
+ .putSuccess(false))
+ }
+ L.eThrow("IAB null bp on purchase attempt")
+ return
+ }
if (!bp!!.isOneTimePurchaseSupported)
activity!!.playStorePurchaseUnsupported()
else
bp!!.purchase(activity, FROST_PRO)
}
- override fun restorePurchases(once: Boolean) {
- if (bp == null) return
- doAsync {
- bp?.loadOwnedPurchasesFromGoogle()
- if (bp?.isPurchased(FROST_PRO) ?: false) {
- uiThread {
- if (Prefs.pro) activity!!.playStoreNoLongerPro()
- else if (!once) purchasePro()
- if (once) onDestroyBilling()
- }
- } else {
- uiThread {
- if (!Prefs.pro) activity!!.playStoreFoundPro()
- else if (!once) activity!!.purchaseRestored()
- if (once) onDestroyBilling()
- }
- }
- }
- }
}
class IABSettings : IABBinder() {
- override fun onBillingInitialized() {
- super.onBillingInitialized()
-
- }
-
- override fun onPurchaseHistoryRestored() {
- super.onPurchaseHistoryRestored()
- }
-
- override fun onProductPurchased(productId: String, details: TransactionDetails) {
+ override fun onProductPurchased(productId: String, details: TransactionDetails?) {
super.onProductPurchased(productId, details)
+ activity?.playStorePurchasedSuccessfully(productId)
}
- override fun onBillingError(errorCode: Int, error: Throwable) {
+ override fun onBillingError(errorCode: Int, error: Throwable?) {
super.onBillingError(errorCode, error)
activity?.playStoreGenericError(null)
}
+
+ /**
+ * Attempts to get pro, or launch purchase flow if user doesn't have it
+ */
+ override fun restorePurchases() {
+ if (bp == null) return
+ val load = bp!!.loadOwnedPurchasesFromGoogle()
+ L.d("IAB settings load from google $load")
+ if (!bp!!.isPurchased(FROST_PRO)) {
+ if (Prefs.pro) activity!!.playStoreNoLongerPro()
+ else purchasePro()
+ } else {
+ if (!Prefs.pro) activity!!.playStoreFoundPro()
+ else activity!!.purchaseRestored()
+ }
+ }
}
class IABMain : IABBinder() {
override fun onBillingInitialized() {
super.onBillingInitialized()
- restorePurchases(true)
+ restorePurchases()
}
override fun onPurchaseHistoryRestored() {
super.onPurchaseHistoryRestored()
- restorePurchases(true)
+ restorePurchases()
+ }
+
+ private var restored = false
+
+ /**
+ * Checks for pro and only does so once
+ * A null check is added but it should never happen
+ * given that this is only called with bp is ready
+ */
+ override fun restorePurchases() {
+ if (restored || bp == null) return
+ restored = true
+ val load = bp!!.loadOwnedPurchasesFromGoogle()
+ L.d("IAB main load from google $load")
+ if (!bp!!.isPurchased(FROST_PRO)) {
+ if (Prefs.pro) activity!!.playStoreNoLongerPro()
+ } else {
+ if (!Prefs.pro) activity!!.playStoreFoundPro()
+ }
+ onDestroyBilling()
}
} \ No newline at end of file
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 4f750b6b..d2f22829 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,11 +4,13 @@ import android.app.Activity
import ca.allanwang.kau.utils.restart
import ca.allanwang.kau.utils.startPlayStoreLink
import ca.allanwang.kau.utils.string
+import com.crashlytics.android.answers.PurchaseEvent
import com.pitchedapps.frost.R
import com.pitchedapps.frost.activities.MainActivity
import com.pitchedapps.frost.activities.SettingsActivity
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.Prefs
+import com.pitchedapps.frost.utils.frostAnswers
import com.pitchedapps.frost.utils.materialDialogThemed
/**
@@ -16,7 +18,7 @@ import com.pitchedapps.frost.utils.materialDialogThemed
*/
private fun playStoreLog(text: String) {
- L.e(Throwable(text), "Play Store Exception")
+ L.e(Throwable(text), "IAB Play Store Exception")
}
/**
@@ -31,7 +33,12 @@ private fun Activity.playRestart() {
fun Activity.playStoreNoLongerPro() {
Prefs.pro = false
- playStoreLog("No Longer Pro")
+ L.d("IAB No longer pro")
+ frostAnswers {
+ logPurchase(PurchaseEvent()
+ .putCustomAttribute("result", "no longer pro")
+ .putSuccess(false))
+ }
materialDialogThemed {
title(R.string.uh_oh)
content(R.string.play_store_not_pro)
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 13f1ac90..912a957e 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt
@@ -41,7 +41,8 @@ class FrostJSI(val webView: FrostWebViewCore) {
@JavascriptInterface
fun contextMenu(url: String, text: String?) {
- webView.post { context.showWebContextMenu(WebContext(url.formattedFbUrl, text)) }
+ //url will be formatted through webcontext
+ webView.post { context.showWebContextMenu(WebContext(url, text)) }
}
/**
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 89eef258..7d5282d8 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt
@@ -1,6 +1,8 @@
package com.pitchedapps.frost.web
+import android.content.ActivityNotFoundException
import android.content.Context
+import android.content.Intent
import android.graphics.Bitmap
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
@@ -9,6 +11,7 @@ import android.webkit.WebViewClient
import com.pitchedapps.frost.activities.LoginActivity
import com.pitchedapps.frost.activities.MainActivity
import com.pitchedapps.frost.activities.SelectorActivity
+import com.pitchedapps.frost.activities.WebOverlayActivity
import com.pitchedapps.frost.facebook.FACEBOOK_COM
import com.pitchedapps.frost.facebook.FB_URL_BASE
import com.pitchedapps.frost.facebook.FbCookie
@@ -40,8 +43,9 @@ open class FrostWebViewClient(val webCore: FrostWebViewCore) : BaseWebViewClient
val refreshObservable: Subject<Boolean> = webCore.refreshObservable
- override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
+ override fun onPageStarted(view: WebView, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
+ if (url == null) return
L.i("FWV Loading $url")
// L.v("Cookies ${CookieManager.getInstance().getCookie(url)}")
refreshObservable.onNext(true)
@@ -57,8 +61,9 @@ open class FrostWebViewClient(val webCore: FrostWebViewCore) : BaseWebViewClient
c.launchNewTask(LoginActivity::class.java)
}
- override fun onPageFinished(view: WebView, url: String) {
+ override fun onPageFinished(view: WebView, url: String?) {
super.onPageFinished(view, url)
+ if (url == null) return
L.i("Page finished $url")
if (!url.contains(FACEBOOK_COM)) {
refreshObservable.onNext(false)
@@ -103,9 +108,11 @@ open class FrostWebViewClient(val webCore: FrostWebViewCore) : BaseWebViewClient
/**
* Helper to format the request and launch it
* returns true to override the url
+ * returns false if we are already in an overlaying activity
*/
private fun launchRequest(request: WebResourceRequest): Boolean {
L.d("Launching Url", request.url.toString())
+ if (webCore.context is WebOverlayActivity) return false
webCore.context.launchWebOverlay(request.url.toString())
return true
}
@@ -124,6 +131,13 @@ open class FrostWebViewClient(val webCore: FrostWebViewCore) : BaseWebViewClient
if (path.startsWith("/composer/")) return launchRequest(request)
if (request.url.toString().contains("scontent-sea1-1.xx.fbcdn.net") && (path.endsWith(".jpg") || path.endsWith(".png")))
return launchImage(request)
+ if (!request.url.toString().contains(FACEBOOK_COM)) {
+ val intent = Intent(Intent.ACTION_VIEW, request.url)
+ if (intent.resolveActivity(view.context.packageManager) != null) {
+ view.context.startActivity(Intent(Intent.ACTION_VIEW, request.url))
+ return true
+ }
+ }
return super.shouldOverrideUrlLoading(view, request)
}
@@ -142,8 +156,9 @@ class FrostWebViewClientMenu(webCore: FrostWebViewCore) : FrostWebViewClient(web
else -> false
}
- override fun onPageFinished(view: WebView, url: String) {
+ override fun onPageFinished(view: WebView, url: String?) {
super.onPageFinished(view, url)
+ if (url == null) return
if (url.shouldInjectMenu) jsInject(JsAssets.MENU)
}
@@ -163,13 +178,15 @@ class FrostWebViewClientMenu(webCore: FrostWebViewCore) : FrostWebViewClient(web
*/
class HeadlessWebViewClient(val tag: String, val postInjection: InjectorContract) : BaseWebViewClient() {
- override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
+ override fun onPageStarted(view: WebView, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
+ if (url == null) return
L.d("Headless Page $tag Started", url)
}
- override fun onPageFinished(view: WebView, url: String) {
+ override fun onPageFinished(view: WebView, url: String?) {
super.onPageFinished(view, url)
+ if (url == null) return
L.d("Headless Page $tag Finished", url)
postInjection.inject(view)
}
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 b23d898e..b178f66c 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt
@@ -24,10 +24,7 @@ import io.reactivex.subjects.Subject
/**
* Created by Allan Wang on 2017-05-29.
- *
*/
-
-
class LoginWebView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : WebView(context, attrs, defStyleAttr) {
@@ -71,9 +68,9 @@ class LoginWebView @JvmOverloads constructor(
inner class LoginClient : BaseWebViewClient() {
- override fun onPageFinished(view: WebView, url: String) {
+ override fun onPageFinished(view: WebView, url: String?) {
super.onPageFinished(view, url)
- if (!url.contains(FACEBOOK_COM)) {
+ if (url == null || !url.contains(FACEBOOK_COM)) {
view.frostSnackbar(R.string.no_longer_facebook)
loadLogin()
return