Merge branch 'support-simplemarkdown' into 'master'
Support SimpleMarkdown See merge request billybrawner/SimpleMarkdown!5
This commit is contained in:
commit
e7fe9918cf
23 changed files with 431 additions and 121 deletions
|
@ -17,7 +17,6 @@ try {
|
|||
keystoreProperties['storePassword'] = ""
|
||||
}
|
||||
|
||||
|
||||
android {
|
||||
configurations.all {
|
||||
resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1'
|
||||
|
@ -88,27 +87,25 @@ dependencies {
|
|||
androidTestUtil "androidx.test:orchestrator:$android_test"
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.preference:preference:1.1.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'com.google.android.material:material:1.0.0'
|
||||
implementation 'com.google.android.material:material:1.1.0-beta01'
|
||||
implementation 'androidx.legacy:legacy-support-v13:1.0.0'
|
||||
implementation 'com.commonsware.cwac:anddown:0.3.0'
|
||||
implementation 'com.google.dagger:dagger:2.22.1'
|
||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.22.1'
|
||||
kapt 'com.google.dagger:dagger-android-processor:2.22.1'
|
||||
kapt 'com.google.dagger:dagger-compiler:2.22.1'
|
||||
implementation 'com.google.firebase:firebase-core:17.1.0'
|
||||
implementation 'com.google.firebase:firebase-core:17.2.1'
|
||||
implementation 'com.android.billingclient:billing:1.2'
|
||||
implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
|
||||
implementation "androidx.core:core-ktx:1.0.2"
|
||||
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"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||
|
||||
def lifecycle_version = "2.0.0"
|
||||
def lifecycle_version = "2.1.0"
|
||||
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
||||
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
|
||||
kapt "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
|
||||
implementation 'eu.crydee:syllable-counter:4.0.2'
|
||||
}
|
||||
|
||||
|
@ -136,10 +133,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'
|
||||
])
|
||||
]))
|
||||
}
|
||||
|
|
|
@ -18,10 +18,6 @@
|
|||
android:theme="@style/AppTheme"
|
||||
tools:ignore="AllowBackup"
|
||||
tools:targetApi="n">
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.ads.APPLICATION_ID"
|
||||
android:value="@string/admob_app_id" />
|
||||
|
||||
<activity
|
||||
android:name=".view.activity.SplashActivity"
|
||||
android:theme="@style/AppTheme.Splash"
|
||||
|
@ -68,6 +64,8 @@
|
|||
android:value=".view.activity.MainActivity" />
|
||||
</activity>
|
||||
|
||||
<activity android:name=".view.activity.SupportActivity" />
|
||||
|
||||
<meta-data
|
||||
android:name="firebase_crashlytics_collection_enabled"
|
||||
android:value="false" />
|
||||
|
|
|
@ -2,12 +2,17 @@ package com.wbrawner.simplemarkdown
|
|||
|
||||
import android.app.Application
|
||||
import android.os.StrictMode
|
||||
import com.wbrawner.simplemarkdown.utility.CrashlyticsErrorHandler
|
||||
import com.wbrawner.simplemarkdown.utility.ErrorHandler
|
||||
import com.wbrawner.simplemarkdown.viewmodel.MarkdownViewModelFactory
|
||||
|
||||
class MarkdownApplication : Application() {
|
||||
val viewModelFactory: MarkdownViewModelFactory by lazy {
|
||||
MarkdownViewModelFactory()
|
||||
}
|
||||
val errorHandler: ErrorHandler by lazy {
|
||||
CrashlyticsErrorHandler()
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
if (BuildConfig.DEBUG) {
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
package com.wbrawner.simplemarkdown.utility
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.crashlytics.android.Crashlytics
|
||||
import io.fabric.sdk.android.BuildConfig
|
||||
import com.wbrawner.simplemarkdown.BuildConfig
|
||||
import io.fabric.sdk.android.Fabric
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
interface ErrorHandler {
|
||||
fun init(context: Context)
|
||||
fun reportException(t: Throwable)
|
||||
fun reportException(t: Throwable, message: String? = null)
|
||||
}
|
||||
|
||||
class CrashlyticsErrorHandler : ErrorHandler {
|
||||
|
@ -20,8 +21,13 @@ class CrashlyticsErrorHandler : ErrorHandler {
|
|||
}
|
||||
}
|
||||
|
||||
override fun reportException(t: Throwable) {
|
||||
if (!isInitialized.get() || BuildConfig.DEBUG) return
|
||||
override fun reportException(t: Throwable, message: String?) {
|
||||
@Suppress("ConstantConditionIf")
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.e("CrashlyticsErrorHandler", "Caught exception: $message", t)
|
||||
return
|
||||
}
|
||||
if (!isInitialized.get()) return
|
||||
Crashlytics.logException(t)
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@ import android.content.res.Configuration
|
|||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.preference.PreferenceManager
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
|
@ -20,25 +19,19 @@ import androidx.core.app.ActivityCompat
|
|||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.wbrawner.simplemarkdown.MarkdownApplication
|
||||
import com.wbrawner.simplemarkdown.R
|
||||
import com.wbrawner.simplemarkdown.utility.ErrorHandler
|
||||
import com.wbrawner.simplemarkdown.utility.getName
|
||||
import com.wbrawner.simplemarkdown.utility.readAssetToString
|
||||
import com.wbrawner.simplemarkdown.utility.toHtml
|
||||
import com.wbrawner.simplemarkdown.view.adapter.EditPagerAdapter
|
||||
import com.wbrawner.simplemarkdown.view.fragment.MainMenuFragment
|
||||
import com.wbrawner.simplemarkdown.viewmodel.MarkdownViewModel
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.coroutines.*
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import javax.inject.Inject
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class MainActivity : AppCompatActivity(), ActivityCompat.OnRequestPermissionsResultCallback, CoroutineScope {
|
||||
|
||||
@Inject
|
||||
lateinit var errorHandler: ErrorHandler
|
||||
private var shouldAutoSave = true
|
||||
override val coroutineContext: CoroutineContext = Dispatchers.Main
|
||||
private lateinit var viewModel: MarkdownViewModel
|
||||
|
@ -47,6 +40,8 @@ class MainActivity : AppCompatActivity(), ActivityCompat.OnRequestPermissionsRes
|
|||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
setSupportActionBar(toolbar)
|
||||
supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_menu_black_24dp)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
window.decorView.apply {
|
||||
systemUiVisibility = (
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
|
@ -89,7 +84,7 @@ class MainActivity : AppCompatActivity(), ActivityCompat.OnRequestPermissionsRes
|
|||
// The user has left the app, with autosave enabled, and we don't already have a
|
||||
// Uri for them or for some reason we were unable to save to the original Uri. In
|
||||
// this case, we need to just save to internal file storage so that we can recover
|
||||
val fileUri = Uri.fromFile(File(filesDir, viewModel.fileName.value))
|
||||
val fileUri = Uri.fromFile(File(filesDir, viewModel.fileName.value!!))
|
||||
if (viewModel.save(this@MainActivity, fileUri)) {
|
||||
fileUri
|
||||
} else {
|
||||
|
@ -118,6 +113,13 @@ class MainActivity : AppCompatActivity(), ActivityCompat.OnRequestPermissionsRes
|
|||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
MainMenuFragment()
|
||||
.apply {
|
||||
errorHandler = (application as MarkdownApplication).errorHandler
|
||||
}
|
||||
.show(supportFragmentManager, null)
|
||||
}
|
||||
R.id.action_save -> {
|
||||
launch {
|
||||
if (!viewModel.save(this@MainActivity)) {
|
||||
|
@ -149,50 +151,10 @@ class MainActivity : AppCompatActivity(), ActivityCompat.OnRequestPermissionsRes
|
|||
item.isChecked = !item.isChecked
|
||||
pager!!.setSwipeLocked(item.isChecked)
|
||||
}
|
||||
R.id.action_help -> showInfoActivity(R.id.action_help)
|
||||
R.id.action_settings -> {
|
||||
val settingsIntent = Intent(this@MainActivity, SettingsActivity::class.java)
|
||||
startActivityForResult(settingsIntent, REQUEST_DARK_MODE)
|
||||
}
|
||||
R.id.action_libraries -> showInfoActivity(R.id.action_libraries)
|
||||
R.id.action_privacy -> showInfoActivity(R.id.action_privacy)
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun showInfoActivity(action: Int) {
|
||||
val infoIntent = Intent(this@MainActivity, MarkdownInfoActivity::class.java)
|
||||
var fileName = ""
|
||||
var title = ""
|
||||
when (action) {
|
||||
R.id.action_help -> {
|
||||
fileName = "Cheatsheet.md"
|
||||
title = getString(R.string.action_help)
|
||||
}
|
||||
R.id.action_libraries -> {
|
||||
fileName = "Libraries.md"
|
||||
title = getString(R.string.action_libraries)
|
||||
}
|
||||
R.id.action_privacy -> {
|
||||
fileName = "Privacy Policy.md"
|
||||
title = getString(R.string.action_privacy)
|
||||
}
|
||||
}
|
||||
infoIntent.putExtra("title", title)
|
||||
launch {
|
||||
try {
|
||||
val html = assets?.readAssetToString(fileName)
|
||||
?.toHtml()
|
||||
?: throw RuntimeException("Unable to open stream to $fileName")
|
||||
infoIntent.putExtra("html", html)
|
||||
startActivity(infoIntent)
|
||||
} catch (e: Exception) {
|
||||
errorHandler.reportException(e)
|
||||
Toast.makeText(this@MainActivity, R.string.file_load_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<String>,
|
||||
|
@ -244,7 +206,6 @@ class MainActivity : AppCompatActivity(), ActivityCompat.OnRequestPermissionsRes
|
|||
viewModel.save(this@MainActivity, data.data)
|
||||
}
|
||||
}
|
||||
REQUEST_DARK_MODE -> recreate()
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
|
|
|
@ -1,21 +1,69 @@
|
|||
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.view.View
|
||||
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)
|
||||
window.decorView.apply {
|
||||
systemUiVisibility = (
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
)
|
||||
}
|
||||
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 +71,47 @@ class SupportActivity : AppCompatActivity(), BillingClientStateListener, Purchas
|
|||
return
|
||||
}
|
||||
|
||||
// The billing client is ready. You can query purchases here.
|
||||
val skuList = ArrayList<String>()
|
||||
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<Purchase>?) {
|
||||
|
||||
purchases?.forEach { purchase ->
|
||||
billingClient.consumeAsync(purchase.purchaseToken) { _, _ ->
|
||||
Toast.makeText(
|
||||
this@SupportActivity,
|
||||
getString(R.string.support_thank_you),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package com.wbrawner.simplemarkdown.view.fragment
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import com.wbrawner.simplemarkdown.R
|
||||
import com.wbrawner.simplemarkdown.utility.ErrorHandler
|
||||
import com.wbrawner.simplemarkdown.utility.readAssetToString
|
||||
import com.wbrawner.simplemarkdown.utility.toHtml
|
||||
import com.wbrawner.simplemarkdown.view.activity.MainActivity
|
||||
import com.wbrawner.simplemarkdown.view.activity.MarkdownInfoActivity
|
||||
import com.wbrawner.simplemarkdown.view.activity.SettingsActivity
|
||||
import com.wbrawner.simplemarkdown.view.activity.SupportActivity
|
||||
import kotlinx.android.synthetic.main.fragment_menu_main.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class MainMenuFragment : BottomSheetDialogFragment(), CoroutineScope {
|
||||
override val coroutineContext: CoroutineContext = Dispatchers.Main
|
||||
lateinit var errorHandler: ErrorHandler
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? = inflater.inflate(R.layout.fragment_menu_main, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
mainMenuNavigationView.setNavigationItemSelectedListener {
|
||||
when (it.itemId) {
|
||||
R.id.action_help -> showInfoActivity(context, R.id.action_help)
|
||||
R.id.action_settings -> {
|
||||
val settingsIntent = Intent(context, SettingsActivity::class.java)
|
||||
startActivityForResult(settingsIntent, MainActivity.REQUEST_DARK_MODE)
|
||||
}
|
||||
R.id.action_libraries -> showInfoActivity(context, R.id.action_libraries)
|
||||
R.id.action_privacy -> showInfoActivity(context, R.id.action_privacy)
|
||||
R.id.action_support -> Intent(context, SupportActivity::class.java)
|
||||
.apply {
|
||||
startActivity(this)
|
||||
dialog?.dismiss()
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (requestCode == MainActivity.REQUEST_DARK_MODE) {
|
||||
activity?.recreate()
|
||||
dialog?.dismiss()
|
||||
return
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
|
||||
private fun showInfoActivity(context: Context?, action: Int) {
|
||||
val infoIntent = Intent(context, MarkdownInfoActivity::class.java)
|
||||
var fileName = ""
|
||||
var title = ""
|
||||
when (action) {
|
||||
R.id.action_help -> {
|
||||
fileName = "Cheatsheet.md"
|
||||
title = getString(R.string.action_help)
|
||||
}
|
||||
R.id.action_libraries -> {
|
||||
fileName = "Libraries.md"
|
||||
title = getString(R.string.action_libraries)
|
||||
}
|
||||
R.id.action_privacy -> {
|
||||
fileName = "Privacy Policy.md"
|
||||
title = getString(R.string.action_privacy)
|
||||
}
|
||||
}
|
||||
infoIntent.putExtra("title", title)
|
||||
launch {
|
||||
// TODO: Refactor this to have the info activity load the markdown instead of doing
|
||||
// it here
|
||||
try {
|
||||
val html = context?.assets?.readAssetToString(fileName)
|
||||
?.toHtml()
|
||||
?: throw RuntimeException("Unable to open stream to $fileName")
|
||||
infoIntent.putExtra("html", html)
|
||||
startActivity(infoIntent, null)
|
||||
} catch (e: Exception) {
|
||||
errorHandler.reportException(e)
|
||||
Toast.makeText(context, R.string.file_load_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
dialog?.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
9
app/src/main/res/drawable/ic_eye_black_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_eye_black_24dp.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z" />
|
||||
</vector>
|
9
app/src/main/res/drawable/ic_favorite_black_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_favorite_black_24dp.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z" />
|
||||
</vector>
|
9
app/src/main/res/drawable/ic_help_black_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_help_black_24dp.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,19h-2v-2h2v2zM15.07,11.25l-0.9,0.92C13.45,12.9 13,13.5 13,15h-2v-0.5c0,-1.1 0.45,-2.1 1.17,-2.83l1.24,-1.26c0.37,-0.36 0.59,-0.86 0.59,-1.41 0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2L8,9c0,-2.21 1.79,-4 4,-4s4,1.79 4,4c0,0.88 -0.36,1.68 -0.93,2.25z" />
|
||||
</vector>
|
9
app/src/main/res/drawable/ic_info_black_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_info_black_24dp.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z" />
|
||||
</vector>
|
9
app/src/main/res/drawable/ic_menu_black_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_menu_black_24dp.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="@color/colorOnBackground"
|
||||
android:pathData="M3,18h18v-2L3,16v2zM3,13h18v-2L3,11v2zM3,6v2h18L21,6L3,6z" />
|
||||
</vector>
|
9
app/src/main/res/drawable/ic_settings_black_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_settings_black_24dp.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M19.1,12.9a2.8,2.8 0,0 0,0.1 -0.9,2.8 2.8,0 0,0 -0.1,-0.9l2.1,-1.6a0.7,0.7 0,0 0,0.1 -0.6L19.4,5.5a0.7,0.7 0,0 0,-0.6 -0.2l-2.4,1a6.5,6.5 0,0 0,-1.6 -0.9l-0.4,-2.6a0.5,0.5 0,0 0,-0.5 -0.4H10.1a0.5,0.5 0,0 0,-0.5 0.4L9.3,5.4a5.6,5.6 0,0 0,-1.7 0.9l-2.4,-1a0.4,0.4 0,0 0,-0.5 0.2l-2,3.4c-0.1,0.2 0,0.4 0.2,0.6l2,1.6a2.8,2.8 0,0 0,-0.1 0.9,2.8 2.8,0 0,0 0.1,0.9L2.8,14.5a0.7,0.7 0,0 0,-0.1 0.6l1.9,3.4a0.7,0.7 0,0 0,0.6 0.2l2.4,-1a6.5,6.5 0,0 0,1.6 0.9l0.4,2.6a0.5,0.5 0,0 0,0.5 0.4h3.8a0.5,0.5 0,0 0,0.5 -0.4l0.3,-2.6a5.6,5.6 0,0 0,1.7 -0.9l2.4,1a0.4,0.4 0,0 0,0.5 -0.2l2,-3.4c0.1,-0.2 0,-0.4 -0.2,-0.6ZM12,15.6A3.6,3.6 0,1 1,15.6 12,3.6 3.6,0 0,1 12,15.6Z" />
|
||||
</vector>
|
91
app/src/main/res/layout/activity_support.xml
Normal file
91
app/src/main/res/layout/activity_support.xml
Normal file
|
@ -0,0 +1,91 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/bottomSheet"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/heartIcon"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:src="@drawable/ic_favorite_black_24dp"
|
||||
android:tint="@color/colorAccent"
|
||||
android:contentDescription="@string/description_heart"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/supportInfoText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:text="@string/support_info"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/colorOnBackground"
|
||||
app:layout_constraintTop_toBottomOf="@+id/heartIcon" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/githubButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:backgroundTint="@color/colorBackgroundGitHub"
|
||||
android:textColor="@color/colorWhite"
|
||||
android:text="@string/action_view_github"
|
||||
app:layout_constraintTop_toBottomOf="@+id/supportInfoText" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/rateButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:backgroundTint="@color/colorBackgroundPlayStore"
|
||||
android:textColor="@color/colorWhite"
|
||||
android:text="@string/action_rate"
|
||||
app:layout_constraintTop_toBottomOf="@+id/githubButton" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/supportButtons"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintTop_toBottomOf="@+id/rateButton" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/bottomSheet"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:translationY="16dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="4dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:background="@color/colorBackground" />
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
7
app/src/main/res/layout/fragment_menu_main.xml
Normal file
7
app/src/main/res/layout/fragment_menu_main.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.navigation.NavigationView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/mainMenuNavigationView"
|
||||
app:menu="@menu/menu_main" />
|
|
@ -25,20 +25,4 @@
|
|||
android:checkable="true"
|
||||
android:title="@string/action_lock_swipe"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:title="@string/action_settings"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/action_help"
|
||||
android:title="@string/action_help"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/action_libraries"
|
||||
android:title="@string/action_libraries"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/action_privacy"
|
||||
android:title="@string/action_privacy"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
33
app/src/main/res/menu/menu_main.xml
Normal file
33
app/src/main/res/menu/menu_main.xml
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<group android:id="@+id/mainGroup">
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:title="@string/action_settings"
|
||||
android:icon="@drawable/ic_settings_black_24dp"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/action_support"
|
||||
android:title="@string/support_title"
|
||||
android:icon="@drawable/ic_favorite_black_24dp"
|
||||
app:showAsAction="never" />
|
||||
</group>
|
||||
<group android:id="@+id/addtionalInfoGroup">
|
||||
<item
|
||||
android:id="@+id/action_help"
|
||||
android:title="@string/action_help"
|
||||
android:icon="@drawable/ic_help_black_24dp"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/action_libraries"
|
||||
android:title="@string/action_libraries"
|
||||
android:icon="@drawable/ic_info_black_24dp"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/action_privacy"
|
||||
android:title="@string/action_privacy"
|
||||
android:icon="@drawable/ic_eye_black_24dp"
|
||||
app:showAsAction="never" />
|
||||
</group>
|
||||
</menu>
|
|
@ -1,6 +1,6 @@
|
|||
<resources>
|
||||
|
||||
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
|
||||
<style name="AppTheme" parent="Theme.MaterialComponents.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
|
|
|
@ -5,4 +5,7 @@
|
|||
<color name="colorAccent">#d32f2f</color>
|
||||
<color name="colorBackground">#FFFFFF</color>
|
||||
<color name="colorOnBackground">#000000</color>
|
||||
<color name="colorBackgroundGitHub">#24292e</color>
|
||||
<color name="colorWhite">#FFFFFFFF</color>
|
||||
<color name="colorBackgroundPlayStore">#689f38</color>
|
||||
</resources>
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
<string name="app_name">Simple Markdown</string>
|
||||
<string name="app_name_short">Markdown</string>
|
||||
|
||||
<string name="admob_app_id">ca-app-pub-3319579963502409~4576405307</string>
|
||||
|
||||
<string name="action_settings">Settings</string>
|
||||
<string name="action_help">Help</string>
|
||||
<string name="action_edit">Edit</string>
|
||||
|
@ -65,6 +63,20 @@
|
|||
<string name="prompt_save_changes">Would you like to save your changes?</string>
|
||||
<string name="action_discard">Discard</string>
|
||||
<string name="action_save_as">Save as…</string>
|
||||
<string name="support_info">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!</string>
|
||||
<string name="action_view_github">View SimpleMarkdown on GitHub</string>
|
||||
<string name="support_title">Support SimpleMarkdown</string>
|
||||
<string name="support_button_purchase">%1$s – %2$s</string>
|
||||
<string name="action_rate">Rate SimpleMarkdown</string>
|
||||
<string name="support_thank_you">Thank you so much for your support!</string>
|
||||
<string name="description_heart">Heart</string>
|
||||
<string-array name="pref_entries_dark_mode">
|
||||
<item>@string/pref_value_light</item>
|
||||
<item>@string/pref_value_dark</item>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.31'
|
||||
ext.kotlin_version = '1.3.50'
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
|
@ -10,9 +10,9 @@ buildscript {
|
|||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.2'
|
||||
classpath 'com.google.gms:google-services:4.2.0'
|
||||
classpath 'io.fabric.tools:gradle:1.26.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"
|
||||
}
|
||||
}
|
||||
|
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
|||
#Fri May 17 18:03:51 MST 2019
|
||||
#Wed Nov 06 17:12:14 CST 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
||||
|
|
Loading…
Reference in a new issue