diff --git a/app/build.gradle b/app/build.gradle index 4695bd6..b4d4c64 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,6 @@ try { keystoreProperties['storePassword'] = "" } - android { configurations.all { resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1' @@ -101,6 +100,7 @@ dependencies { implementation 'com.android.billingclient:billing:1.2' implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1' implementation "androidx.core:core-ktx:1.1.0" + implementation 'androidx.browser:browser:1.0.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" def coroutines_version = "1.3.0-RC2" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" @@ -136,10 +136,10 @@ task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest']) { def kotlinDebugTree = fileTree(dir: "$project.buildDir/tmp/kotlin-classes/debug", excludes: fileFilter) def mainSrc = "$project.projectDir/src/main/java" - sourceDirectories = files([mainSrc]) - classDirectories = files([javaDebugTree, kotlinDebugTree]) - executionData = fileTree(dir: project.buildDir, includes: [ + sourceDirectories.setFrom(files([mainSrc])) + classDirectories.setFrom(files([javaDebugTree, kotlinDebugTree])) + executionData.setFrom(fileTree(dir: project.buildDir, includes: [ 'jacoco/testDebugUnitTest.exec', 'outputs/code-coverage/connected/*coverage.ec' - ]) + ])) } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index defe2b9..44868d3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,10 +18,6 @@ android:theme="@style/AppTheme" tools:ignore="AllowBackup" tools:targetApi="n"> - - + + diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/SupportActivity.kt b/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/SupportActivity.kt index 00985ec..9951497 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/SupportActivity.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/SupportActivity.kt @@ -1,21 +1,61 @@ package com.wbrawner.simplemarkdown.view.activity +import android.content.ActivityNotFoundException +import android.content.Intent +import android.net.Uri import android.os.Bundle -import android.util.Log +import android.view.MenuItem +import android.widget.Toast import androidx.appcompat.app.AppCompatActivity +import androidx.browser.customtabs.CustomTabsIntent import com.android.billingclient.api.* -import java.util.* +import com.google.android.material.button.MaterialButton +import com.wbrawner.simplemarkdown.R +import kotlinx.android.synthetic.main.activity_support.* + class SupportActivity : AppCompatActivity(), BillingClientStateListener, PurchasesUpdatedListener { private lateinit var billingClient: BillingClient override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + setContentView(R.layout.activity_support) + setSupportActionBar(toolbar) + setTitle(R.string.support_title) + supportActionBar?.setDisplayHomeAsUpEnabled(true) billingClient = BillingClient.newBuilder(applicationContext) .setListener(this) .build() billingClient.startConnection(this) + githubButton.setOnClickListener { + CustomTabsIntent.Builder() + .addDefaultShareMenuItem() + .build() + .launchUrl(this@SupportActivity, Uri.parse("https://github.com/wbrawner/SimpleMarkdown")) + } + rateButton.setOnClickListener { + val playStoreIntent = Intent(Intent.ACTION_VIEW) + .apply { + data = Uri.parse("market://details?id=${packageName}") + addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY or + Intent.FLAG_ACTIVITY_NEW_DOCUMENT or + Intent.FLAG_ACTIVITY_MULTIPLE_TASK) + } + try { + startActivity(playStoreIntent) + } catch (ignored: ActivityNotFoundException) { + playStoreIntent.data = Uri.parse("https://play.google.com/store/apps/details?id=${packageName}") + startActivity(playStoreIntent) + } + } + } + override fun onOptionsItemSelected(item: MenuItem): Boolean { + if (item.itemId == android.R.id.home) { + finish() + return true + } + return super.onOptionsItemSelected(item) } override fun onBillingSetupFinished(responseCode: Int) { @@ -23,36 +63,47 @@ class SupportActivity : AppCompatActivity(), BillingClientStateListener, Purchas return } - // The billing client is ready. You can query purchases here. - val skuList = ArrayList() - skuList.add("support_the_developer") - val params = SkuDetailsParams.newBuilder() - params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP) - billingClient.querySkuDetailsAsync(params.build()) { responseCode1, skuDetailsList -> + val skuDetails = SkuDetailsParams.newBuilder() + .setSkusList(listOf("support_the_developer", "tip_coffee", "tip_beer")) + .setType(BillingClient.SkuType.INAPP) + .build() + billingClient.querySkuDetailsAsync(skuDetails) { skuDetailsResponseCode, skuDetailsList -> // Process the result. - if (responseCode1 != BillingClient.BillingResponse.OK || skuDetailsList == null) { + if (skuDetailsResponseCode != BillingClient.BillingResponse.OK || skuDetailsList.isNullOrEmpty()) { return@querySkuDetailsAsync } - val skuDetails = skuDetailsList!!.get(0) - val sku = skuDetails.getSku() - val price = skuDetails.getPrice() - Log.d("SimpleMarkdown", - "Got product with sku: " + sku + " and price: " + price + " " + skuDetails.getPriceCurrencyCode()) - val flowParams = BillingFlowParams.newBuilder() - .setSkuDetails(skuDetails) - .build() - val responseCode2 = billingClient.launchBillingFlow(this, flowParams) + skuDetailsList.sortedBy { it.priceAmountMicros }.forEach { skuDetails -> + val supportButton = MaterialButton(this@SupportActivity) + supportButton.text = getString( + R.string.support_button_purchase, + skuDetails.title, + skuDetails.price + ) + supportButton.setOnClickListener { + val flowParams = BillingFlowParams.newBuilder() + .setSkuDetails(skuDetails) + .build() + billingClient.launchBillingFlow(this, flowParams) + } + supportButtons.addView(supportButton) + } } } override fun onBillingServiceDisconnected() { - // TODO: Set a flag and just try again later billingClient.startConnection(this) } override fun onPurchasesUpdated(responseCode: Int, purchases: List?) { - + purchases?.forEach { purchase -> + billingClient.consumeAsync(purchase.purchaseToken) { _, _ -> + Toast.makeText( + this@SupportActivity, + getString(R.string.support_thank_you), + Toast.LENGTH_SHORT + ).show() + } + } } - } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_favorite_black_24dp.xml b/app/src/main/res/drawable/ic_favorite_black_24dp.xml new file mode 100644 index 0000000..17cea92 --- /dev/null +++ b/app/src/main/res/drawable/ic_favorite_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_menu_black_24dp.xml b/app/src/main/res/drawable/ic_menu_black_24dp.xml new file mode 100644 index 0000000..bdceee4 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_support.xml b/app/src/main/res/layout/activity_support.xml new file mode 100644 index 0000000..e2d812b --- /dev/null +++ b/app/src/main/res/layout/activity_support.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 776578d..afeaf77 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -5,4 +5,7 @@ #d32f2f #FFFFFF #000000 + #24292e + #FFFFFFFF + #689f38 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c5d8808..499ba52 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2,8 +2,6 @@ Simple Markdown Markdown - ca-app-pub-3319579963502409~4576405307 - Settings Help Edit @@ -65,6 +63,20 @@ Would you like to save your changes? Discard Save as… + SimpleMarkdown is a personal project of mine that I develop and + maintain in my free time. I very much appreciate any and all forms of support, whether + that be assistance with designing the app or icons, adding translations for other + languages, contributing to the code, or giving me a tip. If you have any troubles with + SimpleMarkdown, please don\'t hesitate to get in touch, and if you haven\'t already, + please rate the app on the Play Store.\n\nAlso please keep in mind that the in-app + purchases for the tips won\'t unlock any additional functionality in the app. + SimpleMarkdown is and always will be completely free and open source! + View SimpleMarkdown on GitHub + Support SimpleMarkdown + %1$s – %2$s + Rate SimpleMarkdown + Thank you so much for your support! + Heart @string/pref_value_light @string/pref_value_dark diff --git a/build.gradle b/build.gradle index ca0c53d..b8fecd6 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:3.5.1' + classpath 'com.android.tools.build:gradle:3.5.2' classpath 'com.google.gms:google-services:4.3.2' classpath 'io.fabric.tools:gradle:1.31.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"