mirror of
https://github.com/afollestad/nock-nock.git
synced 2025-09-04 00:28:08 +00:00
This commit is contained in:
parent
84eb0b30e1
commit
de36a2f5e6
32 changed files with 517 additions and 115 deletions
|
@ -27,6 +27,7 @@ dependencies {
|
|||
implementation 'androidx.appcompat:appcompat:' + versions.androidxCore
|
||||
implementation 'androidx.recyclerview:recyclerview:' + versions.androidxRecyclerView
|
||||
implementation 'com.google.android.material:material:' + versions.googleMaterial
|
||||
implementation 'androidx.browser:browser:' + versions.androidxBrowser
|
||||
|
||||
kapt 'androidx.lifecycle:lifecycle-compiler:' + versions.lifecycle
|
||||
|
||||
|
|
|
@ -18,9 +18,18 @@ package com.afollestad.nocknock
|
|||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.app.Application.ActivityLifecycleCallbacks
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.AttrRes
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.browser.customtabs.CustomTabsIntent
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY
|
||||
import androidx.core.text.HtmlCompat.fromHtml
|
||||
import com.afollestad.materialdialogs.utils.MDUtil.resolveColor
|
||||
import com.afollestad.nocknock.utilities.ui.toast
|
||||
|
||||
typealias ActivityLifeChange = (activity: Activity, resumed: Boolean) -> Unit
|
||||
|
||||
|
@ -50,3 +59,53 @@ fun Application.onActivityLifeChange(cb: ActivityLifeChange) {
|
|||
}
|
||||
|
||||
fun String.toHtml() = fromHtml(this, FROM_HTML_MODE_LEGACY)
|
||||
|
||||
fun String.toUri() = Uri.parse(this)!!
|
||||
|
||||
fun Activity.setStatusBarColor(
|
||||
@ColorRes res: Int? = null,
|
||||
@AttrRes attr: Int? = null
|
||||
) {
|
||||
require(res != null || attr != null) { "Must specify at least one arg." }
|
||||
if (res != null) {
|
||||
val color = ContextCompat.getColor(this, res)
|
||||
window.statusBarColor = color
|
||||
} else if (attr != null) {
|
||||
val color = resolveColor(this, attr = attr)
|
||||
window.statusBarColor = color
|
||||
}
|
||||
}
|
||||
|
||||
fun Activity.viewUrl(url: String) {
|
||||
val customTabsIntent = CustomTabsIntent.Builder()
|
||||
.apply {
|
||||
setToolbarColor(resolveColor(this@viewUrl, attr = R.attr.colorPrimary))
|
||||
}
|
||||
.build()
|
||||
try {
|
||||
customTabsIntent.launchUrl(this, url.toUri())
|
||||
} catch (_: ActivityNotFoundException) {
|
||||
toast(R.string.install_web_browser)
|
||||
}
|
||||
}
|
||||
|
||||
fun Activity.viewUrlWithApp(
|
||||
url: String,
|
||||
pkg: String
|
||||
) {
|
||||
val intent = Intent(Intent.ACTION_VIEW).apply {
|
||||
data = url.toUri()
|
||||
}
|
||||
val resInfo = packageManager.queryIntentActivities(intent, 0)
|
||||
for (info in resInfo) {
|
||||
if (info.activityInfo.packageName.toLowerCase().contains(pkg) ||
|
||||
info.activityInfo.name.toLowerCase().contains(pkg)
|
||||
) {
|
||||
startActivity(intent.apply {
|
||||
setPackage(info.activityInfo.packageName)
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
viewUrl(url)
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ package com.afollestad.nocknock
|
|||
import android.app.Application
|
||||
import com.afollestad.nocknock.engine.engineModule
|
||||
import com.afollestad.nocknock.koin.mainModule
|
||||
import com.afollestad.nocknock.koin.prefModule
|
||||
import com.afollestad.nocknock.koin.viewModelModule
|
||||
import com.afollestad.nocknock.notifications.NockNotificationManager
|
||||
import com.afollestad.nocknock.notifications.notificationsModule
|
||||
|
@ -42,6 +43,7 @@ class NockNockApp : Application() {
|
|||
}
|
||||
|
||||
val modules = listOf(
|
||||
prefModule,
|
||||
mainModule,
|
||||
engineModule,
|
||||
commonModule,
|
||||
|
|
|
@ -37,7 +37,7 @@ typealias Listener = (model: Site, longClick: Boolean) -> Unit
|
|||
/** @author Aidan Follestad (@afollestad) */
|
||||
class SiteViewHolder constructor(
|
||||
itemView: View,
|
||||
private val adapter: ServerAdapter
|
||||
private val adapter: SiteAdapter
|
||||
) : RecyclerView.ViewHolder(itemView), View.OnLongClickListener {
|
||||
|
||||
init {
|
||||
|
@ -94,7 +94,7 @@ class SiteViewHolder constructor(
|
|||
}
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class ServerAdapter(private val listener: Listener) : RecyclerView.Adapter<SiteViewHolder>() {
|
||||
class SiteAdapter(private val listener: Listener) : RecyclerView.Adapter<SiteViewHolder>() {
|
||||
|
||||
private var models = mutableListOf<Site>()
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ class StatusUpdateIntentReceiver(
|
|||
private var callback: SiteCallback?
|
||||
) : LifecycleObserver {
|
||||
|
||||
internal val intentReceiver = object : BroadcastReceiver() {
|
||||
private val intentReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(
|
||||
context: Context,
|
||||
intent: Intent
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.afollestad.nocknock.koin
|
||||
|
||||
import com.afollestad.rxkprefs.RxkPrefs
|
||||
import com.afollestad.rxkprefs.rxkPrefs
|
||||
import org.koin.dsl.module.module
|
||||
|
||||
const val PREF_DARK_MODE = "dark_mode"
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
val prefModule = module {
|
||||
|
||||
single { rxkPrefs(get(), "settings") }
|
||||
|
||||
factory(name = PREF_DARK_MODE) {
|
||||
get<RxkPrefs>().boolean(PREF_DARK_MODE, false)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.afollestad.nocknock.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.afollestad.nocknock.R
|
||||
import com.afollestad.nocknock.koin.PREF_DARK_MODE
|
||||
import com.afollestad.nocknock.utilities.rx.attachLifecycle
|
||||
import com.afollestad.rxkprefs.Pref
|
||||
import org.koin.android.ext.android.inject
|
||||
import timber.log.Timber.d as log
|
||||
|
||||
/** @author Aidan Follestad (afollestad) */
|
||||
abstract class DarkModeSwitchActivity : AppCompatActivity() {
|
||||
|
||||
private var isDarkModeEnabled: Boolean = false
|
||||
private val darkModePref by inject<Pref<Boolean>>(name = PREF_DARK_MODE)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
isDarkModeEnabled = darkModePref.get()
|
||||
setTheme(themeRes())
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
darkModePref.observe()
|
||||
.filter { it != isDarkModeEnabled }
|
||||
.subscribe {
|
||||
log("Theme changed, recreating Activity.")
|
||||
recreate()
|
||||
}
|
||||
.attachLifecycle(this)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
}
|
||||
|
||||
private fun themeRes() = if (darkModePref.get()) {
|
||||
R.style.AppTheme_Dark
|
||||
} else {
|
||||
R.style.AppTheme
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ import android.widget.ArrayAdapter
|
|||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.afollestad.nocknock.R
|
||||
import com.afollestad.nocknock.data.model.ValidationMode
|
||||
import com.afollestad.nocknock.setStatusBarColor
|
||||
import com.afollestad.nocknock.viewcomponents.ext.conceal
|
||||
import com.afollestad.nocknock.viewcomponents.ext.onLayout
|
||||
import com.afollestad.nocknock.viewcomponents.livedata.attachLiveData
|
||||
|
@ -38,11 +39,12 @@ import kotlinx.android.synthetic.main.activity_addsite.responseValidationSearchT
|
|||
import kotlinx.android.synthetic.main.activity_addsite.rootView
|
||||
import kotlinx.android.synthetic.main.activity_addsite.scriptInputLayout
|
||||
import kotlinx.android.synthetic.main.activity_addsite.textUrlWarning
|
||||
import kotlinx.android.synthetic.main.activity_addsite.toolbar
|
||||
import kotlinx.android.synthetic.main.activity_addsite.validationModeDescription
|
||||
import kotlinx.android.synthetic.main.include_app_bar.toolbar
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import kotlin.math.max
|
||||
import kotlin.properties.Delegates.notNull
|
||||
import kotlinx.android.synthetic.main.include_app_bar.toolbar_title as toolbarTitle
|
||||
|
||||
const val KEY_FAB_X = "fab_x"
|
||||
const val KEY_FAB_Y = "fab_y"
|
||||
|
@ -62,6 +64,7 @@ class AddSiteActivity : AppCompatActivity() {
|
|||
@SuppressLint("SetTextI18n")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setStatusBarColor(res = R.color.inkColorDark)
|
||||
setContentView(R.layout.activity_addsite)
|
||||
setupUi(savedInstanceState)
|
||||
|
||||
|
@ -133,7 +136,11 @@ class AddSiteActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
private fun setupUi(savedInstanceState: Bundle?) {
|
||||
toolbar.setNavigationOnClickListener { closeActivityWithReveal() }
|
||||
toolbarTitle.setText(R.string.add_site)
|
||||
toolbar.run {
|
||||
setNavigationIcon(R.drawable.ic_action_close)
|
||||
setNavigationOnClickListener { closeActivityWithReveal() }
|
||||
}
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
rootView.conceal()
|
||||
|
|
|
@ -18,6 +18,8 @@ package com.afollestad.nocknock.ui.addsite
|
|||
import android.view.ViewAnimationUtils.createCircularReveal
|
||||
import android.view.animation.AccelerateInterpolator
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import com.afollestad.nocknock.R
|
||||
import com.afollestad.nocknock.setStatusBarColor
|
||||
import com.afollestad.nocknock.utilities.ext.onEnd
|
||||
import com.afollestad.nocknock.viewcomponents.ext.conceal
|
||||
import com.afollestad.nocknock.viewcomponents.ext.show
|
||||
|
@ -40,6 +42,7 @@ internal fun AddSiteActivity.closeActivityWithReveal() {
|
|||
if (isClosing) {
|
||||
return
|
||||
}
|
||||
setStatusBarColor(attr = R.attr.colorPrimary)
|
||||
isClosing = true
|
||||
createCircularReveal(rootView, revealCx, revealCy, revealRadius, 0f)
|
||||
.apply {
|
||||
|
|
|
@ -17,38 +17,45 @@ package com.afollestad.nocknock.ui.main
|
|||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.DividerItemDecoration.VERTICAL
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.list.listItems
|
||||
import com.afollestad.materialdialogs.list.listItemsSingleChoice
|
||||
import com.afollestad.nocknock.R
|
||||
import com.afollestad.nocknock.adapter.ServerAdapter
|
||||
import com.afollestad.nocknock.adapter.SiteAdapter
|
||||
import com.afollestad.nocknock.broadcasts.StatusUpdateIntentReceiver
|
||||
import com.afollestad.nocknock.data.model.Site
|
||||
import com.afollestad.nocknock.dialogs.AboutDialog
|
||||
import com.afollestad.nocknock.koin.PREF_DARK_MODE
|
||||
import com.afollestad.nocknock.notifications.NockNotificationManager
|
||||
import com.afollestad.nocknock.ui.DarkModeSwitchActivity
|
||||
import com.afollestad.nocknock.utilities.providers.IntentProvider
|
||||
import com.afollestad.nocknock.utilities.ui.toast
|
||||
import com.afollestad.nocknock.viewUrl
|
||||
import com.afollestad.nocknock.viewUrlWithApp
|
||||
import com.afollestad.nocknock.viewcomponents.ext.showOrHide
|
||||
import com.afollestad.rxkprefs.Pref
|
||||
import kotlinx.android.synthetic.main.activity_main.fab
|
||||
import kotlinx.android.synthetic.main.activity_main.list
|
||||
import kotlinx.android.synthetic.main.activity_main.loadingProgress
|
||||
import kotlinx.android.synthetic.main.activity_main.toolbar
|
||||
import kotlinx.android.synthetic.main.include_app_bar.toolbar
|
||||
import kotlinx.android.synthetic.main.include_empty_view.emptyText
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class MainActivity : AppCompatActivity() {
|
||||
class MainActivity : DarkModeSwitchActivity() {
|
||||
|
||||
private val notificationManager by inject<NockNotificationManager>()
|
||||
private val intentProvider by inject<IntentProvider>()
|
||||
private val darkModePref by inject<Pref<Boolean>>(name = PREF_DARK_MODE)
|
||||
|
||||
internal val viewModel by viewModel<MainViewModel>()
|
||||
|
||||
private lateinit var adapter: ServerAdapter
|
||||
private lateinit var siteAdapter: SiteAdapter
|
||||
|
||||
private val statusUpdateReceiver by lazy {
|
||||
StatusUpdateIntentReceiver(application, intentProvider) {
|
||||
|
@ -70,7 +77,7 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
viewModel.onSites()
|
||||
.observe(this, Observer {
|
||||
adapter.set(it)
|
||||
siteAdapter.set(it)
|
||||
emptyText.showOrHide(it.isEmpty())
|
||||
})
|
||||
loadingProgress.observe(this, viewModel.onIsLoading())
|
||||
|
@ -79,20 +86,27 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
private fun setupUi() {
|
||||
toolbar.inflateMenu(R.menu.menu_main)
|
||||
toolbar.setOnMenuItemClickListener { item ->
|
||||
if (item.itemId == R.id.about) {
|
||||
AboutDialog.show(this)
|
||||
toolbar.run {
|
||||
inflateMenu(R.menu.menu_main)
|
||||
menu.findItem(R.id.dark_mode)
|
||||
.isChecked = darkModePref.get()
|
||||
setOnMenuItemClickListener { item ->
|
||||
when (item.itemId) {
|
||||
R.id.about -> AboutDialog.show(this@MainActivity)
|
||||
R.id.dark_mode -> darkModePref.set(!darkModePref.get())
|
||||
R.id.support_me -> supportMe()
|
||||
}
|
||||
return@setOnMenuItemClickListener true
|
||||
}
|
||||
return@setOnMenuItemClickListener true
|
||||
}
|
||||
|
||||
adapter = ServerAdapter(this::onSiteSelected)
|
||||
|
||||
list.layoutManager = LinearLayoutManager(this)
|
||||
list.adapter = adapter
|
||||
list.addItemDecoration(DividerItemDecoration(this, VERTICAL))
|
||||
siteAdapter = SiteAdapter(this::onSiteSelected)
|
||||
|
||||
list.run {
|
||||
layoutManager = LinearLayoutManager(this@MainActivity)
|
||||
adapter = siteAdapter
|
||||
addItemDecoration(DividerItemDecoration(this@MainActivity, VERTICAL))
|
||||
}
|
||||
fab.setOnClickListener { addSite() }
|
||||
}
|
||||
|
||||
|
@ -119,4 +133,20 @@ class MainActivity : AppCompatActivity() {
|
|||
viewSite(model)
|
||||
}
|
||||
}
|
||||
|
||||
private fun supportMe() {
|
||||
MaterialDialog(this).show {
|
||||
title(R.string.support_me)
|
||||
message(R.string.support_me_message, html = true, lineHeightMultiplier = 1.4f)
|
||||
listItemsSingleChoice(R.array.donation_options) { _, index, _ ->
|
||||
when (index) {
|
||||
0 -> viewUrl("https://paypal.me/AidanFollestad")
|
||||
1 -> viewUrlWithApp("https://cash.me/\$afollestad", pkg = "com.squareup.cash")
|
||||
2 -> viewUrlWithApp("https://venmo.com/afollestad", pkg = "com.venmo")
|
||||
}
|
||||
toast(R.string.thank_you)
|
||||
}
|
||||
positiveButton(R.string.next)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,10 +25,11 @@ import com.afollestad.nocknock.R
|
|||
import com.afollestad.nocknock.broadcasts.StatusUpdateIntentReceiver
|
||||
import com.afollestad.nocknock.data.model.Site
|
||||
import com.afollestad.nocknock.data.model.ValidationMode
|
||||
import com.afollestad.nocknock.setStatusBarColor
|
||||
import com.afollestad.nocknock.utilities.providers.IntentProvider
|
||||
import com.afollestad.nocknock.viewcomponents.livedata.attachLiveData
|
||||
import com.afollestad.nocknock.viewcomponents.ext.dimenFloat
|
||||
import com.afollestad.nocknock.viewcomponents.ext.onScroll
|
||||
import com.afollestad.nocknock.viewcomponents.livedata.attachLiveData
|
||||
import com.afollestad.nocknock.viewcomponents.livedata.toViewError
|
||||
import com.afollestad.nocknock.viewcomponents.livedata.toViewText
|
||||
import com.afollestad.nocknock.viewcomponents.livedata.toViewVisibility
|
||||
|
@ -47,10 +48,11 @@ import kotlinx.android.synthetic.main.activity_viewsite.scrollView
|
|||
import kotlinx.android.synthetic.main.activity_viewsite.textLastCheckResult
|
||||
import kotlinx.android.synthetic.main.activity_viewsite.textNextCheck
|
||||
import kotlinx.android.synthetic.main.activity_viewsite.textUrlWarning
|
||||
import kotlinx.android.synthetic.main.activity_viewsite.toolbar
|
||||
import kotlinx.android.synthetic.main.activity_viewsite.validationModeDescription
|
||||
import kotlinx.android.synthetic.main.include_app_bar.toolbar
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import kotlinx.android.synthetic.main.include_app_bar.toolbar_title as toolbarTitle
|
||||
|
||||
/** @author Aidan Follestad (@afollestad) */
|
||||
class ViewSiteActivity : AppCompatActivity() {
|
||||
|
@ -67,6 +69,7 @@ class ViewSiteActivity : AppCompatActivity() {
|
|||
@SuppressLint("SetTextI18n")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setStatusBarColor(res = R.color.inkColorDark)
|
||||
setContentView(R.layout.activity_viewsite)
|
||||
setupUi()
|
||||
|
||||
|
@ -156,7 +159,9 @@ class ViewSiteActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
private fun setupUi() {
|
||||
toolbarTitle.setText(R.string.add_site)
|
||||
toolbar.run {
|
||||
setNavigationIcon(R.drawable.ic_action_close)
|
||||
setNavigationOnClickListener { finish() }
|
||||
inflateMenu(R.menu.menu_viewsite)
|
||||
menu.findItem(R.id.refresh)
|
||||
|
|
|
@ -22,7 +22,7 @@ import com.afollestad.nocknock.data.model.Status
|
|||
import com.afollestad.nocknock.data.model.isPending
|
||||
import com.afollestad.nocknock.toHtml
|
||||
import com.afollestad.nocknock.utilities.ext.animateRotation
|
||||
import kotlinx.android.synthetic.main.activity_viewsite.toolbar
|
||||
import kotlinx.android.synthetic.main.include_app_bar.toolbar
|
||||
|
||||
const val KEY_SITE = "site_model"
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<size android:height="1dp"/>
|
||||
<solid android:color="@color/dividerColor"/>
|
||||
<solid android:color="?dividerColor"/>
|
||||
</shape>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -15,15 +14,7 @@
|
|||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/FlatToolbarTheme"
|
||||
app:navigationIcon="@drawable/ic_action_close"
|
||||
app:title="@string/add_site"
|
||||
app:titleTextColor="#FFFFFF"
|
||||
/>
|
||||
<include layout="@layout/include_app_bar"/>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
|
@ -86,8 +77,8 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/list_text_spacing"
|
||||
android:visibility="gone"
|
||||
android:text="@string/warning_http_url"
|
||||
android:visibility="gone"
|
||||
style="@style/NockText.Footnote"
|
||||
/>
|
||||
|
||||
|
@ -157,7 +148,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/content_inset"
|
||||
android:layout_marginTop="@dimen/content_inset_half"
|
||||
android:background="@color/colorPrimaryDark"
|
||||
android:background="@color/inkColorDark"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
|
|
|
@ -15,13 +15,7 @@
|
|||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/MainToolbarTheme"
|
||||
style="@style/MainToolbarStyle"
|
||||
/>
|
||||
<include layout="@layout/include_app_bar"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/list"
|
||||
|
@ -34,18 +28,23 @@
|
|||
|
||||
<include layout="@layout/include_empty_view"/>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|bottom"
|
||||
android:layout_margin="@dimen/content_inset"
|
||||
android:src="@drawable/ic_add"
|
||||
app:backgroundTint="?colorAccent"
|
||||
app:elevation="@dimen/fab_elevation"
|
||||
app:fabSize="normal"
|
||||
app:pressedTranslationZ="@dimen/fab_elevation_pressed"
|
||||
app:rippleColor="#40ffffff"
|
||||
android:layout_marginBottom="@dimen/content_inset"
|
||||
android:layout_marginEnd="@dimen/content_inset_more"
|
||||
android:minHeight="64dp"
|
||||
android:paddingBottom="@dimen/content_inset_half"
|
||||
android:paddingEnd="@dimen/content_inset"
|
||||
android:paddingStart="@dimen/content_inset"
|
||||
android:paddingTop="@dimen/content_inset_half"
|
||||
android:text="@string/add_site"
|
||||
app:cornerRadius="32dp"
|
||||
app:icon="@drawable/ic_add"
|
||||
app:iconTint="#fff"
|
||||
style="@style/Widget.MaterialComponents.Button.Icon"
|
||||
/>
|
||||
|
||||
<com.afollestad.nocknock.viewcomponents.LoadingIndicatorFrame
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -15,17 +14,7 @@
|
|||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<!-- Background is applied again here so programmatic elevation works -->
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?colorPrimary"
|
||||
android:theme="@style/FlatToolbarTheme"
|
||||
app:navigationIcon="@drawable/ic_action_close"
|
||||
app:title="@string/view_site"
|
||||
app:titleTextColor="?android:textColorPrimary"
|
||||
/>
|
||||
<include layout="@layout/include_app_bar"/>
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/scrollView"
|
||||
|
@ -187,7 +176,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/content_inset"
|
||||
android:layout_marginTop="@dimen/content_inset_half"
|
||||
android:background="@color/colorPrimaryDark"
|
||||
android:background="@color/inkColorDark"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
|
|
30
app/src/main/res/layout/include_app_bar.xml
Normal file
30
app/src/main/res/layout/include_app_bar.xml
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/app_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?colorPrimary"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center"
|
||||
tools:ignore="Overdraw"
|
||||
>
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?actionBarSize"
|
||||
android:elevation="0dp"
|
||||
/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/toolbar_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?actionBarSize"
|
||||
android:gravity="center"
|
||||
android:text="@string/app_name"
|
||||
android:textAppearance="@style/AppTheme.TextAppearance.Title"
|
||||
/>
|
||||
|
||||
</FrameLayout>
|
|
@ -3,4 +3,11 @@
|
|||
<item
|
||||
android:id="@+id/about"
|
||||
android:title="@string/about"/>
|
||||
<item
|
||||
android:id="@+id/dark_mode"
|
||||
android:checkable="true"
|
||||
android:title="@string/dark_mode"/>
|
||||
<item
|
||||
android:id="@+id/support_me"
|
||||
android:title="@string/support_me"/>
|
||||
</menu>
|
||||
|
|
8
app/src/main/res/values-v21/styles_parent.xml
Normal file
8
app/src/main/res/values-v21/styles_parent.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="AppThemeParent.Ink" parent="AppThemeParent.Dark">
|
||||
<item name="android:navigationBarColor">@color/inkColorDark</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
9
app/src/main/res/values-v23/styles.xml
Normal file
9
app/src/main/res/values-v23/styles.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="AppTheme" parent="AppThemeParent">
|
||||
<item name="android:statusBarColor">@color/colorPrimary_lightTheme</item>
|
||||
<item name="android:windowLightStatusBar">true</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
20
app/src/main/res/values-v27/styles.xml
Normal file
20
app/src/main/res/values-v27/styles.xml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="AppTheme" parent="AppThemeParent">
|
||||
<item name="android:statusBarColor">@color/colorPrimary_lightTheme</item>
|
||||
<item name="android:windowLightStatusBar">true</item>
|
||||
|
||||
<item name="android:navigationBarColor">@color/colorPrimaryDark_lightTheme</item>
|
||||
<item name="android:windowLightNavigationBar">true</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.Dark" parent="AppThemeParent.Dark">
|
||||
<item name="android:statusBarColor">@color/colorPrimary_darkTheme</item>
|
||||
<item name="android:windowLightStatusBar">false</item>
|
||||
|
||||
<item name="android:navigationBarColor">@color/colorPrimaryDark_darkTheme</item>
|
||||
<item name="android:windowLightNavigationBar">false</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -12,4 +12,10 @@
|
|||
<item>JavaScript Evaluation</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="donation_options">
|
||||
<item>via PayPal</item>
|
||||
<item>via Cash App</item>
|
||||
<item>via Venmo</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
||||
|
|
8
app/src/main/res/values/attrs.xml
Normal file
8
app/src/main/res/values/attrs.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<attr format="color" name="toolbarTitleColor"/>
|
||||
<attr format="color" name="dividerColor"/>
|
||||
<attr format="color" name="iconColor"/>
|
||||
|
||||
</resources>
|
|
@ -1,10 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<color name="colorPrimary">#455A64</color>
|
||||
<color name="colorPrimaryDark">#37474F</color>
|
||||
<color name="colorPrimary_lightTheme">#FFFFFF</color>
|
||||
<color name="colorPrimaryDark_lightTheme">#F5F5F5</color>
|
||||
|
||||
<color name="colorPrimary_darkTheme">#212121</color>
|
||||
<color name="colorPrimaryDark_darkTheme">#212121</color>
|
||||
|
||||
<color name="inkColor">#455A64</color>
|
||||
<color name="inkColorDark">#37474F</color>
|
||||
<color name="colorAccent">#FF6E40</color>
|
||||
|
||||
<color name="dividerColor">#EEEEEE</color>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
<a href=\'https://www.linkedin.com/in/afollestad\'>LinkedIn</a>
|
||||
<br/><br/><i>Nock Nock is open source! Check out the <a href=\'https://github.com/afollestad/nock-nock\'>GitHub page</a>!</i>
|
||||
<br/>Icon by <a href=\'https://plus.google.com/+KevinAguilarC\'>Kevin Aguilar</a> of <b>221 Pixels</b>.
|
||||
]]></string>
|
||||
]]></string>
|
||||
<string name="dark_mode">Dark Mode</string>
|
||||
|
||||
<string name="dismiss">Dismiss</string>
|
||||
<string name="add_site">Add Site</string>
|
||||
|
@ -74,4 +75,15 @@
|
|||
exception to pass custom error messages to Nock Nock.
|
||||
</string>
|
||||
|
||||
<string name="support_me">Donate</string>
|
||||
<string name="support_me_message"><![CDATA[
|
||||
<b>MNML</b> was created and is maintained by one person. Donations are <b>much</b>
|
||||
appreciated and encourage continued support.
|
||||
]]></string>
|
||||
<string name="thank_you">Thank you very much!</string>
|
||||
<string name="next">Next</string>
|
||||
|
||||
<string name="install_video_viewer">Please install a video viewer app, such as Google Photos.</string>
|
||||
<string name="install_web_browser">Please install a web browser app, such as Google Chrome.</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -1,27 +1,14 @@
|
|||
<resources>
|
||||
|
||||
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<style name="AppTheme" parent="AppThemeParent"/>
|
||||
|
||||
<style name="AppTheme.Dark" parent="AppThemeParent.Dark"/>
|
||||
|
||||
<style name="AppTheme.Ink" parent="AppThemeParent.Ink">
|
||||
<item name="colorPrimary">@color/inkColor</item>
|
||||
<item name="colorPrimaryDark">@color/inkColorDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
<item name="colorButtonNormal">@color/colorPrimaryDark</item>
|
||||
|
||||
<item name="android:listDivider">@drawable/divider</item>
|
||||
|
||||
<item name="android:textColorPrimary">#212121</item>
|
||||
<item name="android:textColorSecondary">#727272</item>
|
||||
|
||||
<item name="md_corner_radius">16dp</item>
|
||||
<item name="md_font_title">@font/lato_black</item>
|
||||
<item name="md_font_body">@font/lato</item>
|
||||
<item name="md_font_button">@font/lato_bold</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.Ink" parent="Theme.MaterialComponents.NoActionBar">
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
<item name="colorButtonNormal">@color/colorPrimaryDark</item>
|
||||
<item name="colorButtonNormal">@color/inkColor</item>
|
||||
|
||||
<item name="android:listDivider">@drawable/divider</item>
|
||||
|
||||
|
@ -37,28 +24,6 @@
|
|||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
</style>
|
||||
|
||||
<style name="MainToolbarTheme" parent="@style/Theme.MaterialComponents">
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
<item name="android:fontFamily">@font/lato_black</item>
|
||||
</style>
|
||||
|
||||
<style name="MainToolbarStyle" parent="@style/Widget.MaterialComponents.Toolbar">
|
||||
<item name="android:background">?colorPrimary</item>
|
||||
<item name="android:elevation">@dimen/default_elevation</item>
|
||||
<item name="title">@string/app_name</item>
|
||||
<item name="titleTextColor">#FFFFFF</item>
|
||||
<item name="popupTheme">@style/Theme.MaterialComponents.Light.DarkActionBar</item>
|
||||
</style>
|
||||
|
||||
<style name="FlatToolbarTheme" parent="@style/Theme.MaterialComponents">
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
<item name="android:fontFamily">@font/lato_black</item>
|
||||
</style>
|
||||
|
||||
<style name="AccentButton" parent="Widget.MaterialComponents.Button">
|
||||
<item name="android:textColor">#fff</item>
|
||||
<item name="backgroundTint">@color/colorAccent</item>
|
||||
|
@ -67,7 +32,7 @@
|
|||
|
||||
<style name="PrimaryDarkButton" parent="Widget.MaterialComponents.Button">
|
||||
<item name="android:textColor">#fff</item>
|
||||
<item name="backgroundTint">@color/colorPrimaryDark</item>
|
||||
<item name="backgroundTint">@color/inkColorDark</item>
|
||||
<item name="android:fontFamily">@font/lato</item>
|
||||
</style>
|
||||
|
||||
|
|
48
app/src/main/res/values/styles_parents.xml
Normal file
48
app/src/main/res/values/styles_parents.xml
Normal file
|
@ -0,0 +1,48 @@
|
|||
<resources>
|
||||
|
||||
<style name="AppThemeParent" parent="Theme.MaterialComponents.Light.NoActionBar">
|
||||
<item name="colorPrimary">@color/colorPrimary_lightTheme</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark_lightTheme</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
<item name="colorButtonNormal">@color/inkColorDark</item>
|
||||
|
||||
<item name="toolbarTitleColor">#000000</item>
|
||||
<item name="dividerColor">#1f000000</item>
|
||||
<item name="iconColor">#000000</item>
|
||||
|
||||
<item name="android:windowBackground">@color/colorPrimary_lightTheme</item>
|
||||
<item name="android:listDivider">@drawable/divider</item>
|
||||
|
||||
<item name="android:statusBarColor">#E5E5E5</item>
|
||||
|
||||
<item name="md_corner_radius">16dp</item>
|
||||
<item name="md_font_title">@font/lato_bold</item>
|
||||
<item name="md_font_body">@font/lato</item>
|
||||
<item name="md_font_button">@font/lato_bold</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeParent.Dark" parent="Theme.MaterialComponents.NoActionBar">
|
||||
<item name="colorPrimary">@color/colorPrimary_darkTheme</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark_darkTheme</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
<item name="colorButtonNormal">@color/inkColorDark</item>
|
||||
|
||||
<item name="toolbarTitleColor">#ffffff</item>
|
||||
<item name="dividerColor">#1fffffff</item>
|
||||
<item name="iconColor">#FFFFFF</item>
|
||||
|
||||
<item name="android:windowBackground">@color/colorPrimary_darkTheme</item>
|
||||
<item name="android:listDivider">@drawable/divider</item>
|
||||
|
||||
<item name="android:statusBarColor">@color/colorPrimary_darkTheme</item>
|
||||
<item name="android:navigationBarColor">@color/colorPrimaryDark_darkTheme</item>
|
||||
|
||||
<item name="md_corner_radius">16dp</item>
|
||||
<item name="md_font_title">@font/lato_bold</item>
|
||||
<item name="md_font_body">@font/lato</item>
|
||||
<item name="md_font_button">@font/lato_bold</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeParent.Ink" parent="AppThemeParent.Dark"/>
|
||||
|
||||
</resources>
|
9
app/src/main/res/values/styles_text.xml
Normal file
9
app/src/main/res/values/styles_text.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<resources>
|
||||
|
||||
<style name="AppTheme.TextAppearance.Title" parent="TextAppearance.MaterialComponents.Headline6">
|
||||
<item name="fontFamily">@font/lato_bold</item>
|
||||
<item name="android:fontFamily">@font/lato_bold</item>
|
||||
<item name="android:textColor">?toolbarTitleColor</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -29,6 +29,8 @@ dependencies {
|
|||
implementation 'org.koin:koin-android:' + versions.koin
|
||||
implementation 'org.mozilla:rhino:' + versions.rhino
|
||||
|
||||
api 'com.afollestad:rxkprefs:' + versions.rxkPrefs
|
||||
|
||||
testImplementation 'junit:junit:' + versions.junit
|
||||
testImplementation 'com.google.truth:truth:' + versions.truth
|
||||
testImplementation 'androidx.arch.core:core-testing:' + versions.archTesting
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
@file:Suppress("unused")
|
||||
|
||||
package com.afollestad.nocknock.utilities.rx
|
||||
|
||||
import androidx.lifecycle.Lifecycle.Event.ON_DESTROY
|
||||
import androidx.lifecycle.Lifecycle.State.DESTROYED
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.OnLifecycleEvent
|
||||
import io.reactivex.disposables.Disposable
|
||||
|
||||
/** @author Aidan Follestad (afollestad) */
|
||||
class LifecycleAwareDisposable(
|
||||
private val disposable: Disposable
|
||||
) : LifecycleObserver {
|
||||
|
||||
@OnLifecycleEvent(ON_DESTROY)
|
||||
fun dispose() = disposable.dispose()
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps [disposable] so that it is disposed of when the receiving [LifecycleOwner]
|
||||
* is destroyed.
|
||||
*
|
||||
* @author Aidan Follestad (afollestad)
|
||||
*/
|
||||
fun LifecycleOwner.ownRx(disposable: Disposable) {
|
||||
if (this.lifecycle.currentState == DESTROYED) {
|
||||
disposable.dispose()
|
||||
return
|
||||
}
|
||||
this.lifecycle.addObserver(LifecycleAwareDisposable(disposable))
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches the receiving [Disposable] so that it is disposed of when [lifecycleOwner]
|
||||
* is destroyed.
|
||||
*
|
||||
* @author Aidan Follestad (afollestad)
|
||||
*/
|
||||
fun Disposable.attachLifecycle(lifecycleOwner: LifecycleOwner) {
|
||||
lifecycleOwner.ownRx(this)
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Designed and developed by Aidan Follestad (@afollestad)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.afollestad.nocknock.utilities.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.Toast
|
||||
|
||||
private var toast: Toast? = null
|
||||
|
||||
/** Shows a toast in the receiving context, cancelling any previous. */
|
||||
fun Context.toast(message: Int) {
|
||||
toast?.cancel()
|
||||
toast = Toast.makeText(this, message, Toast.LENGTH_LONG)
|
||||
.apply {
|
||||
show()
|
||||
}
|
||||
}
|
|
@ -1,39 +1,51 @@
|
|||
ext.versions = [
|
||||
// Project
|
||||
minSdk : 21,
|
||||
compileSdk : 28,
|
||||
buildTools : '28.0.3',
|
||||
publishVersion : '0.8.0',
|
||||
publishVersionCode : 28,
|
||||
|
||||
// Plugins
|
||||
gradlePlugin : '3.2.1',
|
||||
spotlessPlugin : '3.17.0',
|
||||
versionPlugin : '0.20.0',
|
||||
|
||||
// Misc
|
||||
okHttp : '3.12.1',
|
||||
rhino : '1.7.10',
|
||||
|
||||
// Kotlin
|
||||
kotlin : '1.3.11',
|
||||
coroutines : '1.1.0',
|
||||
koin : '1.0.2',
|
||||
|
||||
// Google/AndroidX
|
||||
androidxAnnotations : '1.0.1',
|
||||
androidxCore : '1.0.2',
|
||||
androidxRecyclerView: '1.0.0',
|
||||
androidxBrowser : '1.0.0',
|
||||
googleMaterial : '1.0.0',
|
||||
room : '2.0.0',
|
||||
lifecycle : '2.0.0',
|
||||
|
||||
// Rx
|
||||
rxBinding : '3.0.0-alpha1',
|
||||
|
||||
// afollestad
|
||||
materialDialogs : '2.0.0-rc7',
|
||||
rxkPrefs : '1.2.0',
|
||||
rxkPrefs : '1.2.1',
|
||||
|
||||
// Debugging
|
||||
timber : '4.7.1',
|
||||
|
||||
// Unit testing
|
||||
junit : '4.12',
|
||||
mockito : '2.23.4',
|
||||
mockitoKotlin : '2.0.0-RC1',
|
||||
truth : '0.42',
|
||||
|
||||
// UI testing
|
||||
androidxTestRunner : '1.1.1',
|
||||
androidxTest : '1.1.0',
|
||||
archTesting : '2.0.0'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue