Split overflow menu into navigation menu
I also removed Dagger since it wasn't really being used, and fixed the CrashlyticsErrorHandler as I had previously imported the incorrect BuildConfig class.
This commit is contained in:
parent
3eb9dfcab1
commit
241f0868cd
14 changed files with 205 additions and 75 deletions
|
@ -88,14 +88,11 @@ dependencies {
|
|||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
|
||||
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.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.23.1'
|
||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.23.1'
|
||||
kapt 'com.google.dagger:dagger-android-processor:2.22.1'
|
||||
kapt 'com.google.dagger:dagger-compiler:2.23.1'
|
||||
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'
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.content.Intent
|
|||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.browser.customtabs.CustomTabsIntent
|
||||
|
@ -21,6 +22,13 @@ class SupportActivity : AppCompatActivity(), BillingClientStateListener, Purchas
|
|||
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)
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
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)
|
||||
dialog?.dismiss()
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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_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_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>
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:padding="16dp"
|
||||
|
|
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>
|
Loading…
Reference in a new issue