diff --git a/.gitignore b/.gitignore index 6e8e9f3..808bfeb 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ /.idea/workspace.xml /.idea/vcs.xml /.idea/libraries +/.idea/markdown-navigator.xml +/.idea/markdown-navigator +/.idea/caches .DS_Store /build /captures diff --git a/app/build.gradle b/app/build.gradle index 7d5e5ba..4bf95c0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,14 +3,14 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' android { - compileSdkVersion 27 + compileSdkVersion 28 defaultConfig { applicationId "com.physphil.android.remindme" minSdkVersion 21 - targetSdkVersion 27 - versionCode 9030 - versionName "0.9.3" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + targetSdkVersion 28 + versionCode 9040 + versionName "0.9.4" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { @@ -32,20 +32,18 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" - implementation 'com.android.support:appcompat-v7:27.0.2' - implementation 'com.android.support.constraint:constraint-layout:1.0.2' - implementation 'com.android.support:design:27.0.2' - implementation 'android.arch.lifecycle:extensions:1.1.0' - kapt 'android.arch.lifecycle:compiler:1.1.0' - implementation 'android.arch.persistence.room:runtime:1.0.0' - kapt 'android.arch.persistence.room:compiler:1.0.0' - implementation 'android.arch.persistence.room:rxjava2:1.0.0' + implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'com.google.android.material:material:1.1.0-alpha01' + implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0' + kapt 'androidx.lifecycle:lifecycle-compiler:2.0.0' + implementation 'androidx.room:room-runtime:2.0.0' + kapt 'androidx.room:room-compiler:2.0.0' + implementation 'androidx.room:room-rxjava2:2.0.0' implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' implementation 'com.evernote:android-job:1.2.1' - implementation 'com.jakewharton:butterknife:8.8.1' - kapt 'com.jakewharton:butterknife-compiler:8.8.1' implementation 'com.google.dagger:dagger:2.14.1' kapt 'com.google.dagger:dagger-compiler:2.14.1' @@ -53,12 +51,12 @@ dependencies { testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:2.15.0' - testImplementation 'android.arch.core:core-testing:1.1.0' - testImplementation 'android.arch.persistence.room:testing:1.0.0' + testImplementation 'androidx.arch.core:core-testing:2.0.0' + testImplementation 'androidx.room:room-testing:2.1.0-alpha02' - androidTestImplementation 'com.android.support.test:runner:1.0.1' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' - androidTestImplementation 'android.arch.core:core-testing:1.1.0' + androidTestImplementation 'androidx.test:runner:1.1.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' + androidTestImplementation 'androidx.arch.core:core-testing:2.0.0' } apply plugin: 'kotlin-android-extensions' \ No newline at end of file diff --git a/app/src/androidTest/java/com/physphil/android/remindme/ReminderDaoTest.kt b/app/src/androidTest/java/com/physphil/android/remindme/ReminderDaoTest.kt index 7c2676d..46e893d 100644 --- a/app/src/androidTest/java/com/physphil/android/remindme/ReminderDaoTest.kt +++ b/app/src/androidTest/java/com/physphil/android/remindme/ReminderDaoTest.kt @@ -1,9 +1,9 @@ package com.physphil.android.remindme -import android.arch.core.executor.testing.InstantTaskExecutorRule -import android.arch.persistence.room.Room -import android.support.test.InstrumentationRegistry -import android.support.test.runner.AndroidJUnit4 +import androidx.arch.core.executor.testing.InstantTaskExecutorRule +import androidx.room.Room +import androidx.test.InstrumentationRegistry +import androidx.test.runner.AndroidJUnit4 import com.physphil.android.remindme.room.AppDatabase import com.physphil.android.remindme.room.ReminderDao import com.physphil.android.remindme.room.entities.Reminder diff --git a/app/src/main/java/com/physphil/android/remindme/BaseActivity.kt b/app/src/main/java/com/physphil/android/remindme/BaseActivity.kt index 0bf2000..2f1d820 100644 --- a/app/src/main/java/com/physphil/android/remindme/BaseActivity.kt +++ b/app/src/main/java/com/physphil/android/remindme/BaseActivity.kt @@ -1,7 +1,7 @@ package com.physphil.android.remindme -import android.support.annotation.StringRes -import android.support.v7.app.AppCompatActivity +import androidx.annotation.StringRes +import androidx.appcompat.app.AppCompatActivity import android.view.MenuItem /** diff --git a/app/src/main/java/com/physphil/android/remindme/MainActivity.kt b/app/src/main/java/com/physphil/android/remindme/MainActivity.kt index c73f346..4499582 100644 --- a/app/src/main/java/com/physphil/android/remindme/MainActivity.kt +++ b/app/src/main/java/com/physphil/android/remindme/MainActivity.kt @@ -2,33 +2,27 @@ package com.physphil.android.remindme import android.app.NotificationChannel import android.app.NotificationManager -import android.arch.lifecycle.Observer -import android.arch.lifecycle.ViewModelProviders import android.content.Context import android.graphics.drawable.InsetDrawable import android.os.Build import android.os.Bundle -import android.support.design.widget.FloatingActionButton -import android.support.v7.widget.DefaultItemAnimator -import android.support.v7.widget.LinearLayoutManager -import android.support.v7.widget.RecyclerView import android.view.Menu import android.view.MenuItem -import android.widget.TextView -import butterknife.BindView -import butterknife.ButterKnife -import butterknife.OnClick +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProviders +import androidx.recyclerview.widget.DefaultItemAnimator +import androidx.recyclerview.widget.LinearLayoutManager import com.physphil.android.remindme.reminders.ReminderActivity import com.physphil.android.remindme.reminders.list.DeleteAllDialogFragment import com.physphil.android.remindme.reminders.list.DeleteReminderDialogFragment import com.physphil.android.remindme.reminders.list.ReminderListAdapter import com.physphil.android.remindme.room.entities.Reminder -import com.physphil.android.remindme.ui.ProgressSpinner import com.physphil.android.remindme.ui.ReminderListDivider import com.physphil.android.remindme.util.setVisibility import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable import io.reactivex.schedulers.Schedulers +import kotlinx.android.synthetic.main.activity_main.* import javax.inject.Inject class MainActivity : BaseActivity(), ReminderListAdapter.ReminderListAdapterClickListener, @@ -38,18 +32,6 @@ class MainActivity : BaseActivity(), ReminderListAdapter.ReminderListAdapterClic @Inject lateinit var viewModelFactory: MainActivityViewModelFactory - @BindView(R.id.reminder_list_recyclerview) - lateinit var recyclerView: RecyclerView - - @BindView(R.id.reminder_list_fab) - lateinit var fab: FloatingActionButton - - @BindView(R.id.reminder_list_spinner) - lateinit var spinner: ProgressSpinner - - @BindView(R.id.reminder_list_empty) - lateinit var empty: TextView - private val disposables = CompositeDisposable() private val adapter = ReminderListAdapter() private val viewModel: MainActivityViewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(MainActivityViewModel::class.java) } @@ -59,7 +41,6 @@ class MainActivity : BaseActivity(), ReminderListAdapter.ReminderListAdapterClic super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) (application as RemindMeApplication).applicationComponent.inject(this) - ButterKnife.bind(this) setupRecyclerview() // Create required notification channel on Android 8.0+ @@ -69,6 +50,10 @@ class MainActivity : BaseActivity(), ReminderListAdapter.ReminderListAdapterClic } bindViewModel() + + reminderListFabView.setOnClickListener { + startActivity(ReminderActivity.intent(this)) + } } override fun onDestroy() { @@ -78,14 +63,14 @@ class MainActivity : BaseActivity(), ReminderListAdapter.ReminderListAdapterClic private fun setupRecyclerview() { adapter.setOnClickListener(this) - recyclerView.adapter = adapter - recyclerView.layoutManager = LinearLayoutManager(this) - recyclerView.itemAnimator = DefaultItemAnimator() + reminderListRecyclerView.adapter = adapter + reminderListRecyclerView.layoutManager = LinearLayoutManager(this) + reminderListRecyclerView.itemAnimator = DefaultItemAnimator() // Setup list divider val inset = resources.getDimensionPixelSize(R.dimen.reminder_divider_margin) val divider = ReminderListDivider(InsetDrawable(getDrawable(R.drawable.divider), inset, 0, inset, 0)) - recyclerView.addItemDecoration(divider) + reminderListRecyclerView.addItemDecoration(divider) // Setup random list header val headers = resources.getStringArray(R.array.reminder_list_headers) @@ -106,17 +91,12 @@ class MainActivity : BaseActivity(), ReminderListAdapter.ReminderListAdapterClic // onNext adapter.setReminderList(it) viewModel.reminderListUpdated(it) - fab.show() // make sure the fab is always showing when the list is updated + reminderListFabView.show() // make sure the fab is always showing when the list is updated }, { // onError })) } - @OnClick(R.id.reminder_list_fab) - fun onAddReminderClick() { - startActivity(ReminderActivity.intent(this)) - } - override fun onCreateOptionsMenu(menu: Menu): Boolean { super.onCreateOptionsMenu(menu) menuInflater.inflate(R.menu.menu_main, menu) @@ -135,11 +115,11 @@ class MainActivity : BaseActivity(), ReminderListAdapter.ReminderListAdapterClic // region ViewModel observers private val spinnerVisibilityObserver = Observer { - it?.let { spinner.setVisibility(it) } + it?.let { reminderListSpinnerView.setVisibility(it) } } private val emptyVisibilityObserver = Observer { - it?.let { empty.setVisibility(it) } + it?.let { reminderListEmptyView.setVisibility(it) } } private val deleteNotificationsObserver = Observer { diff --git a/app/src/main/java/com/physphil/android/remindme/MainActivityViewModel.kt b/app/src/main/java/com/physphil/android/remindme/MainActivityViewModel.kt index cb697b4..9b60bdb 100644 --- a/app/src/main/java/com/physphil/android/remindme/MainActivityViewModel.kt +++ b/app/src/main/java/com/physphil/android/remindme/MainActivityViewModel.kt @@ -1,8 +1,8 @@ package com.physphil.android.remindme -import android.arch.lifecycle.LiveData -import android.arch.lifecycle.MutableLiveData -import android.arch.lifecycle.ViewModel +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel import com.physphil.android.remindme.data.ReminderRepo import com.physphil.android.remindme.job.JobRequestScheduler import com.physphil.android.remindme.room.entities.Reminder diff --git a/app/src/main/java/com/physphil/android/remindme/MainActivityViewModelFactory.kt b/app/src/main/java/com/physphil/android/remindme/MainActivityViewModelFactory.kt index 68085db..625de94 100644 --- a/app/src/main/java/com/physphil/android/remindme/MainActivityViewModelFactory.kt +++ b/app/src/main/java/com/physphil/android/remindme/MainActivityViewModelFactory.kt @@ -1,7 +1,7 @@ package com.physphil.android.remindme -import android.arch.lifecycle.ViewModel -import android.arch.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider import com.physphil.android.remindme.data.ReminderRepo import com.physphil.android.remindme.job.JobRequestScheduler diff --git a/app/src/main/java/com/physphil/android/remindme/inject/ApplicationModule.kt b/app/src/main/java/com/physphil/android/remindme/inject/ApplicationModule.kt index 1457b1b..f703135 100644 --- a/app/src/main/java/com/physphil/android/remindme/inject/ApplicationModule.kt +++ b/app/src/main/java/com/physphil/android/remindme/inject/ApplicationModule.kt @@ -1,6 +1,6 @@ package com.physphil.android.remindme.inject -import android.arch.persistence.room.Room +import androidx.room.Room import android.content.Context import com.physphil.android.remindme.DATABASE_NAME import com.physphil.android.remindme.MainActivityViewModelFactory diff --git a/app/src/main/java/com/physphil/android/remindme/job/ShowNotificationJob.kt b/app/src/main/java/com/physphil/android/remindme/job/ShowNotificationJob.kt index 2b3c628..6fc0e97 100644 --- a/app/src/main/java/com/physphil/android/remindme/job/ShowNotificationJob.kt +++ b/app/src/main/java/com/physphil/android/remindme/job/ShowNotificationJob.kt @@ -4,9 +4,9 @@ import android.app.NotificationManager import android.app.PendingIntent import android.content.Context import android.content.Intent -import android.support.v4.app.NotificationCompat -import android.support.v4.app.TaskStackBuilder -import android.support.v4.content.ContextCompat +import androidx.core.app.NotificationCompat +import androidx.core.app.TaskStackBuilder +import androidx.core.content.ContextCompat import com.evernote.android.job.Job import com.physphil.android.remindme.CHANNEL_NOTIFICATIONS import com.physphil.android.remindme.R diff --git a/app/src/main/java/com/physphil/android/remindme/reminders/RecurrencePickerDialog.kt b/app/src/main/java/com/physphil/android/remindme/reminders/RecurrencePickerDialog.kt index 60565a8..4d21f93 100644 --- a/app/src/main/java/com/physphil/android/remindme/reminders/RecurrencePickerDialog.kt +++ b/app/src/main/java/com/physphil/android/remindme/reminders/RecurrencePickerDialog.kt @@ -3,8 +3,8 @@ package com.physphil.android.remindme.reminders import android.app.Dialog import android.content.Context import android.os.Bundle -import android.support.v4.app.DialogFragment -import android.support.v7.app.AlertDialog +import androidx.fragment.app.DialogFragment +import androidx.appcompat.app.AlertDialog import com.physphil.android.remindme.R import com.physphil.android.remindme.models.Recurrence diff --git a/app/src/main/java/com/physphil/android/remindme/reminders/ReminderActivity.kt b/app/src/main/java/com/physphil/android/remindme/reminders/ReminderActivity.kt index 1c6ae5a..fa7f27d 100644 --- a/app/src/main/java/com/physphil/android/remindme/reminders/ReminderActivity.kt +++ b/app/src/main/java/com/physphil/android/remindme/reminders/ReminderActivity.kt @@ -3,8 +3,6 @@ package com.physphil.android.remindme.reminders import android.app.DatePickerDialog import android.app.NotificationManager import android.app.TimePickerDialog -import android.arch.lifecycle.Observer -import android.arch.lifecycle.ViewModelProviders import android.content.Context import android.content.Intent import android.os.Bundle @@ -12,23 +10,22 @@ import android.view.Menu import android.view.MenuItem import android.widget.DatePicker import android.widget.TimePicker -import butterknife.BindView -import butterknife.ButterKnife +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProviders import com.physphil.android.remindme.BaseActivity import com.physphil.android.remindme.R import com.physphil.android.remindme.RemindMeApplication import com.physphil.android.remindme.models.Recurrence import com.physphil.android.remindme.reminders.list.DeleteReminderDialogFragment -import com.physphil.android.remindme.ui.ReminderEntryButton -import com.physphil.android.remindme.ui.ReminderEntryField import com.physphil.android.remindme.util.getDisplayDate import com.physphil.android.remindme.util.getDisplayTime import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable import io.reactivex.schedulers.Schedulers +import kotlinx.android.synthetic.main.activity_reminder.* /** - * Create a new [Reminder] or edit and existing one. + * Create a new [Reminder] or edit an existing one. * * Copyright (c) 2017 Phil Shadlyn */ @@ -36,21 +33,6 @@ class ReminderActivity : BaseActivity(), TimePickerDialog.OnTimeSetListener, DatePickerDialog.OnDateSetListener, RecurrencePickerDialog.OnRecurrenceSetListener, DeleteReminderDialogFragment.Listener { - @BindView(R.id.reminder_title) - lateinit var titleView: ReminderEntryField - - @BindView(R.id.reminder_body) - lateinit var bodyView: ReminderEntryField - - @BindView(R.id.reminder_time) - lateinit var timeView: ReminderEntryButton - - @BindView(R.id.reminder_date) - lateinit var dateView: ReminderEntryButton - - @BindView(R.id.reminder_recurrence) - lateinit var recurrenceView: ReminderEntryButton - /** A [CompositeDisposable] to contain all active subscriptions. Should be cleared when Activity is destroyed */ private val disposables = CompositeDisposable() @@ -75,25 +57,23 @@ class ReminderActivity : BaseActivity(), TimePickerDialog.OnTimeSetListener, } private fun bindViews() { - ButterKnife.bind(this) - - titleView.setOnTextChangedListener { + reminderTitleView.setOnTextChangedListener { viewModel.updateTitle(it) } - bodyView.setOnTextChangedListener { + reminderBodyView.setOnTextChangedListener { viewModel.updateBody(it) } - timeView.setOnClickListener { + reminderTimeView.setOnClickListener { viewModel.openTimePicker() } - dateView.setOnClickListener { + reminderDateView.setOnClickListener { viewModel.openDatePicker() } - recurrenceView.setOnClickListener { + reminderRecurrenceView.setOnClickListener { viewModel.openRecurrencePicker() } } @@ -106,11 +86,11 @@ class ReminderActivity : BaseActivity(), TimePickerDialog.OnTimeSetListener, .subscribe({ // on success. Save Reminder in viewmodel and update UI viewModel.reminder = it - titleView.setText(it.title) - bodyView.setText(it.body) - timeView.setText(it.getDisplayTime(this)) - dateView.setText(it.getDisplayDate(this)) - recurrenceView.setText(it.recurrence.displayString) + reminderTitleView.setText(it.title, true) + reminderBodyView.setText(it.body) + reminderTimeView.setText(it.getDisplayTime(this)) + reminderDateView.setText(it.getDisplayDate(this)) + reminderRecurrenceView.setText(it.recurrence.displayString) // Clear any notifications for this Reminder notificationManager.cancel(it.notificationId) @@ -118,9 +98,9 @@ class ReminderActivity : BaseActivity(), TimePickerDialog.OnTimeSetListener, // on error })) - viewModel.getReminderTime().observe(this, Observer { it?.let { timeView.setText(it) } }) - viewModel.getReminderDate().observe(this, Observer { it?.let { dateView.setText(it) } }) - viewModel.getReminderRecurrence().observe(this, Observer { it?.let { recurrenceView.setText(it) } }) + viewModel.getReminderTime().observe(this, Observer { it?.let { reminderTimeView.setText(it) } }) + viewModel.getReminderDate().observe(this, Observer { it?.let { reminderDateView.setText(it) } }) + viewModel.getReminderRecurrence().observe(this, Observer { it?.let { reminderRecurrenceView.setText(it) } }) viewModel.getToolbarTitle().observe(this, Observer { it?.let { setToolbarTitle(it) } }) viewModel.clearNotificationEvent.observe(this, Observer { diff --git a/app/src/main/java/com/physphil/android/remindme/reminders/ReminderViewModel.kt b/app/src/main/java/com/physphil/android/remindme/reminders/ReminderViewModel.kt index 21a70e6..b266648 100644 --- a/app/src/main/java/com/physphil/android/remindme/reminders/ReminderViewModel.kt +++ b/app/src/main/java/com/physphil/android/remindme/reminders/ReminderViewModel.kt @@ -1,10 +1,10 @@ package com.physphil.android.remindme.reminders -import android.arch.lifecycle.LiveData -import android.arch.lifecycle.MutableLiveData -import android.arch.lifecycle.ViewModel +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel import android.content.Context -import android.support.annotation.VisibleForTesting +import androidx.annotation.VisibleForTesting import android.view.MenuItem import com.physphil.android.remindme.R import com.physphil.android.remindme.data.ReminderRepo diff --git a/app/src/main/java/com/physphil/android/remindme/reminders/ReminderViewModelFactory.kt b/app/src/main/java/com/physphil/android/remindme/reminders/ReminderViewModelFactory.kt index 2afff0d..daceb06 100644 --- a/app/src/main/java/com/physphil/android/remindme/reminders/ReminderViewModelFactory.kt +++ b/app/src/main/java/com/physphil/android/remindme/reminders/ReminderViewModelFactory.kt @@ -1,7 +1,7 @@ package com.physphil.android.remindme.reminders -import android.arch.lifecycle.ViewModel -import android.arch.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider import com.physphil.android.remindme.RemindMeApplication import com.physphil.android.remindme.data.ReminderRepo import com.physphil.android.remindme.job.JobRequestScheduler diff --git a/app/src/main/java/com/physphil/android/remindme/reminders/list/DeleteAllDialogFragment.kt b/app/src/main/java/com/physphil/android/remindme/reminders/list/DeleteAllDialogFragment.kt index ea5cef8..0a5ba6b 100644 --- a/app/src/main/java/com/physphil/android/remindme/reminders/list/DeleteAllDialogFragment.kt +++ b/app/src/main/java/com/physphil/android/remindme/reminders/list/DeleteAllDialogFragment.kt @@ -3,8 +3,8 @@ package com.physphil.android.remindme.reminders.list import android.app.Dialog import android.content.Context import android.os.Bundle -import android.support.v4.app.DialogFragment -import android.support.v7.app.AlertDialog +import androidx.appcompat.app.AlertDialog +import androidx.fragment.app.DialogFragment import com.physphil.android.remindme.R /** diff --git a/app/src/main/java/com/physphil/android/remindme/reminders/list/DeleteReminderDialogFragment.kt b/app/src/main/java/com/physphil/android/remindme/reminders/list/DeleteReminderDialogFragment.kt index 06b7b4c..64f75be 100644 --- a/app/src/main/java/com/physphil/android/remindme/reminders/list/DeleteReminderDialogFragment.kt +++ b/app/src/main/java/com/physphil/android/remindme/reminders/list/DeleteReminderDialogFragment.kt @@ -3,8 +3,8 @@ package com.physphil.android.remindme.reminders.list import android.app.Dialog import android.content.Context import android.os.Bundle -import android.support.v4.app.DialogFragment -import android.support.v7.app.AlertDialog +import androidx.fragment.app.DialogFragment +import androidx.appcompat.app.AlertDialog import com.physphil.android.remindme.R /** diff --git a/app/src/main/java/com/physphil/android/remindme/reminders/list/ReminderListAdapter.kt b/app/src/main/java/com/physphil/android/remindme/reminders/list/ReminderListAdapter.kt index 9ad3296..5f7ba5d 100644 --- a/app/src/main/java/com/physphil/android/remindme/reminders/list/ReminderListAdapter.kt +++ b/app/src/main/java/com/physphil/android/remindme/reminders/list/ReminderListAdapter.kt @@ -1,19 +1,17 @@ package com.physphil.android.remindme.reminders.list -import android.support.v7.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.Button -import android.widget.TextView -import butterknife.BindView -import butterknife.ButterKnife +import androidx.recyclerview.widget.RecyclerView import com.physphil.android.remindme.R import com.physphil.android.remindme.models.Recurrence import com.physphil.android.remindme.room.entities.Reminder import com.physphil.android.remindme.util.getDisplayDate import com.physphil.android.remindme.util.getDisplayTime import com.physphil.android.remindme.util.setVisibility +import kotlinx.android.synthetic.main.view_header_reminder_list.view.* +import kotlinx.android.synthetic.main.view_row_reminder_list.view.* private const val HEADER_ID = "header_id" private const val VIEW_TYPE_HEADER = 0 @@ -44,32 +42,42 @@ class ReminderListAdapter : RecyclerView.Adapter override fun onBindViewHolder(holder: ViewHolder, position: Int) { - if (holder is HeaderViewHolder) { - holder.header.setVisibility(headerText.isNotEmpty()) - holder.header.text = headerText + if (holder is ViewHolder.Header) { + with(holder.itemView) { + reminderItemHeaderView.setVisibility(headerText.isNotEmpty()) + reminderItemHeaderView.text = headerText + } } - else if (holder is ReminderViewHolder) { + else if (holder is ViewHolder.Reminder) { val reminder = reminders[position] - holder.date.text = reminder.getDisplayDate(holder.date.context) - holder.time.text = reminder.getDisplayTime(holder.time.context) - holder.title.text = reminder.title - - // Hide description if not entered - if (reminder.body.isNotEmpty()) { - holder.body.setVisibility(true) - holder.body.text = reminder.body - } - else { - holder.body.setVisibility(false) - } - - // Hide recurrence if it is a single alarm - if (reminder.recurrence != Recurrence.NONE) { - holder.recurrence.setVisibility(true) - holder.recurrence.setText(reminder.recurrence.displayString) - } - else { - holder.recurrence.setVisibility(false) + with(holder.itemView) { + setOnClickListener { + listener?.onReminderClicked(reminder) + } + + reminderItemDeleteView.setOnClickListener { + listener?.onDeleteReminder(reminder) + } + + reminderItemDateView.text = reminder.getDisplayDate(context) + reminderItemTimeView.text = reminder.getDisplayTime(context) + reminderItemTitleView.text = reminder.title + + // Hide description if not entered + if (reminder.body.isNotEmpty()) { + reminderItemBodyView.setVisibility(true) + reminderItemBodyView.text = reminder.body + } else { + reminderItemBodyView.setVisibility(false) + } + + // Hide recurrence if it is a single alarm + if (reminder.recurrence != Recurrence.NONE) { + reminderItemRecurrenceView.setVisibility(true) + reminderItemRecurrenceView.setText(reminder.recurrence.displayString) + } else { + reminderItemRecurrenceView.setVisibility(false) + } } } } @@ -77,11 +85,11 @@ class ReminderListAdapter : RecyclerView.Adapter override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { return if (viewType == VIEW_TYPE_HEADER) { val view = LayoutInflater.from(parent.context).inflate(R.layout.view_header_reminder_list, parent, false) - HeaderViewHolder(view) + ViewHolder.Header(view) } else { val view = LayoutInflater.from(parent.context).inflate(R.layout.view_row_reminder_list, parent, false) - ReminderViewHolder(view) + ViewHolder.Reminder(view) } } @@ -111,49 +119,8 @@ class ReminderListAdapter : RecyclerView.Adapter * The ViewHolders used for both the Header and Reminder. They both extend from RecyclerView.ViewHolder * in order to work with RecyclerView */ - abstract inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) - - inner class HeaderViewHolder(view: View) : ViewHolder(view) { - - @BindView(R.id.reminder_list_header) - lateinit var header: TextView - - init { - ButterKnife.bind(this, view) - } - } - - inner class ReminderViewHolder(view: View) : ViewHolder(view), View.OnClickListener { - - @BindView(R.id.reminder_list_delete) - lateinit var delete: Button - - @BindView(R.id.reminder_list_date) - lateinit var date: TextView - - @BindView(R.id.reminder_list_time) - lateinit var time: TextView - - @BindView(R.id.reminder_list_recurrence) - lateinit var recurrence: TextView - - @BindView(R.id.reminder_list_title) - lateinit var title: TextView - - @BindView(R.id.reminder_list_body) - lateinit var body: TextView - - init { - ButterKnife.bind(this, view) - view.setOnClickListener(this) - delete.setOnClickListener(this) - } - - override fun onClick(v: View) { - when (v.id) { - R.id.reminder_list_delete -> listener?.onDeleteReminder(reminders[adapterPosition]) - else -> listener?.onReminderClicked(reminders[adapterPosition]) - } - } + sealed class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { + class Header(view: View) : ViewHolder(view) + class Reminder(view: View) : ViewHolder(view) } } \ No newline at end of file diff --git a/app/src/main/java/com/physphil/android/remindme/room/AppDatabase.kt b/app/src/main/java/com/physphil/android/remindme/room/AppDatabase.kt index eab7e6d..5c19755 100644 --- a/app/src/main/java/com/physphil/android/remindme/room/AppDatabase.kt +++ b/app/src/main/java/com/physphil/android/remindme/room/AppDatabase.kt @@ -1,8 +1,8 @@ package com.physphil.android.remindme.room -import android.arch.persistence.room.Database -import android.arch.persistence.room.RoomDatabase -import android.arch.persistence.room.TypeConverters +import androidx.room.Database +import androidx.room.RoomDatabase +import androidx.room.TypeConverters import com.physphil.android.remindme.DATABASE_VERSION import com.physphil.android.remindme.room.entities.Reminder diff --git a/app/src/main/java/com/physphil/android/remindme/room/Converters.kt b/app/src/main/java/com/physphil/android/remindme/room/Converters.kt index 24c9961..27a8f52 100644 --- a/app/src/main/java/com/physphil/android/remindme/room/Converters.kt +++ b/app/src/main/java/com/physphil/android/remindme/room/Converters.kt @@ -1,6 +1,6 @@ package com.physphil.android.remindme.room -import android.arch.persistence.room.TypeConverter +import androidx.room.TypeConverter import com.physphil.android.remindme.models.Recurrence import java.util.* diff --git a/app/src/main/java/com/physphil/android/remindme/room/ReminderDao.kt b/app/src/main/java/com/physphil/android/remindme/room/ReminderDao.kt index 5dfce12..84d8609 100644 --- a/app/src/main/java/com/physphil/android/remindme/room/ReminderDao.kt +++ b/app/src/main/java/com/physphil/android/remindme/room/ReminderDao.kt @@ -1,11 +1,11 @@ package com.physphil.android.remindme.room -import android.arch.persistence.room.Dao -import android.arch.persistence.room.Delete -import android.arch.persistence.room.Insert -import android.arch.persistence.room.OnConflictStrategy -import android.arch.persistence.room.Query -import android.arch.persistence.room.Update +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import androidx.room.Update import com.physphil.android.remindme.REMINDER_COLUMN_EXTERNAL_ID import com.physphil.android.remindme.REMINDER_COLUMN_ID import com.physphil.android.remindme.REMINDER_COLUMN_NOTIFICATION_ID diff --git a/app/src/main/java/com/physphil/android/remindme/room/entities/Reminder.kt b/app/src/main/java/com/physphil/android/remindme/room/entities/Reminder.kt index 3041079..21dd34b 100644 --- a/app/src/main/java/com/physphil/android/remindme/room/entities/Reminder.kt +++ b/app/src/main/java/com/physphil/android/remindme/room/entities/Reminder.kt @@ -1,8 +1,8 @@ package com.physphil.android.remindme.room.entities -import android.arch.persistence.room.ColumnInfo -import android.arch.persistence.room.Entity -import android.arch.persistence.room.PrimaryKey +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey import com.physphil.android.remindme.REMINDER_COLUMN_EXTERNAL_ID import com.physphil.android.remindme.REMINDER_COLUMN_NOTIFICATION_ID import com.physphil.android.remindme.REMINDER_COLUMN_RECURRENCE diff --git a/app/src/main/java/com/physphil/android/remindme/ui/ProgressSpinner.kt b/app/src/main/java/com/physphil/android/remindme/ui/ProgressSpinner.kt index 0b584e6..7608f74 100644 --- a/app/src/main/java/com/physphil/android/remindme/ui/ProgressSpinner.kt +++ b/app/src/main/java/com/physphil/android/remindme/ui/ProgressSpinner.kt @@ -1,24 +1,23 @@ package com.physphil.android.remindme.ui import android.content.Context -import android.support.annotation.StringRes -import android.support.constraint.ConstraintLayout import android.util.AttributeSet -import android.widget.ProgressBar -import android.widget.TextView -import butterknife.BindView -import butterknife.ButterKnife +import androidx.annotation.StringRes +import androidx.constraintlayout.widget.ConstraintLayout import com.physphil.android.remindme.R +import kotlinx.android.synthetic.main.view_progress_spinner.view.* /** * Copyright (c) 2018 Phil Shadlyn */ -class ProgressSpinner : ConstraintLayout { - constructor(context: Context) : this(context, null) - constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) - constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { - val view = inflate(context, R.layout.view_progress_spinner, this) - ButterKnife.bind(this, view) +class ProgressSpinner @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayout(context, attrs, defStyleAttr) { + + init { + inflate(context, R.layout.view_progress_spinner, this) attrs?.let { // Load any xml-specified attributes @@ -28,25 +27,18 @@ class ProgressSpinner : ConstraintLayout { if (res != 0) { setMessage(res) - } - else if (str != null) { + } else if (str != null) { setMessage(str) } ta.recycle() } } - @BindView(R.id.progress_spinner) - lateinit var spinner: ProgressBar - - @BindView(R.id.progress_message) - lateinit var message: TextView - fun setMessage(@StringRes message: Int) { - this.message.setText(message) + progressMessageView.setText(message) } fun setMessage(message: String) { - this.message.text = message + progressMessageView.text = message } } \ No newline at end of file diff --git a/app/src/main/java/com/physphil/android/remindme/ui/ReminderEntryButton.kt b/app/src/main/java/com/physphil/android/remindme/ui/ReminderEntryButton.kt index d03c892..db3176b 100644 --- a/app/src/main/java/com/physphil/android/remindme/ui/ReminderEntryButton.kt +++ b/app/src/main/java/com/physphil/android/remindme/ui/ReminderEntryButton.kt @@ -1,32 +1,20 @@ package com.physphil.android.remindme.ui import android.content.Context -import android.support.annotation.DrawableRes -import android.support.constraint.ConstraintLayout import android.util.AttributeSet import android.view.LayoutInflater -import android.view.View -import android.widget.Button -import android.widget.ImageView -import butterknife.BindView -import butterknife.ButterKnife -import butterknife.OnClick +import androidx.annotation.DrawableRes +import androidx.constraintlayout.widget.ConstraintLayout import com.physphil.android.remindme.R +import kotlinx.android.synthetic.main.view_reminder_entry_button.view.* class ReminderEntryButton @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : ConstraintLayout(context, attrs, defStyleAttr) { - @BindView(R.id.reminder_entry_button_icon) - lateinit var icon: ImageView - - @BindView(R.id.reminder_entry_button) - lateinit var button: Button - private var listener: OnClickListener? = null init { val view = LayoutInflater.from(context).inflate(R.layout.view_reminder_entry_button, this) - ButterKnife.bind(this, view) attrs?.let { val ta = context.obtainStyledAttributes(attrs, R.styleable.ReminderEntryButton) @@ -41,10 +29,18 @@ class ReminderEntryButton @JvmOverloads constructor(context: Context, attrs: Att ta.recycle() } + + view.reminderEntryButtonView.setOnClickListener { + listener?.onClick(it) + } + + view.reminderEntryButtonIconView.setOnClickListener { + listener?.onClick(it) + } } fun setText(text: String) { - this.button.text = text + reminderEntryButtonView.text = text } fun setText(res: Int) { @@ -52,15 +48,10 @@ class ReminderEntryButton @JvmOverloads constructor(context: Context, attrs: Att } fun setIcon(@DrawableRes icon: Int) { - this.icon.setImageResource(icon) + reminderEntryButtonIconView.setImageResource(icon) } override fun setOnClickListener(l: OnClickListener?) { listener = l } - - @OnClick(R.id.reminder_entry_button, R.id.reminder_entry_button_icon) - protected fun onButtonClicked(view: View) { - listener?.onClick(view) - } } \ No newline at end of file diff --git a/app/src/main/java/com/physphil/android/remindme/ui/ReminderEntryField.kt b/app/src/main/java/com/physphil/android/remindme/ui/ReminderEntryField.kt index c7f313b..ded377b 100644 --- a/app/src/main/java/com/physphil/android/remindme/ui/ReminderEntryField.kt +++ b/app/src/main/java/com/physphil/android/remindme/ui/ReminderEntryField.kt @@ -1,18 +1,16 @@ package com.physphil.android.remindme.ui import android.content.Context -import android.support.annotation.DrawableRes -import android.support.annotation.StringRes -import android.support.constraint.ConstraintLayout +import android.text.Editable +import android.text.TextWatcher import android.util.AttributeSet import android.view.LayoutInflater -import android.widget.EditText -import android.widget.ImageView -import android.widget.TextView -import butterknife.BindView -import butterknife.ButterKnife -import butterknife.OnTextChanged +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import androidx.constraintlayout.widget.ConstraintLayout import com.physphil.android.remindme.R +import com.physphil.android.remindme.util.setTextMoveCursorToEnd +import kotlinx.android.synthetic.main.view_reminder_entry.view.* /** * Copyright (c) 2018 Phil Shadlyn @@ -20,20 +18,10 @@ import com.physphil.android.remindme.R class ReminderEntryField @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : ConstraintLayout(context, attrs, defStyleAttr) { - @BindView(R.id.reminder_entry_title) - lateinit var title: TextView - - @BindView(R.id.reminder_entry_field) - lateinit var text: EditText - - @BindView(R.id.reminder_entry_icon) - lateinit var icon: ImageView - private var textChangedListener: ((String) -> Unit)? = null init { val view = LayoutInflater.from(context).inflate(R.layout.view_reminder_entry, this) - ButterKnife.bind(this, view) attrs?.let { val ta = context.obtainStyledAttributes(attrs, R.styleable.ReminderEntryField) @@ -50,27 +38,34 @@ class ReminderEntryField @JvmOverloads constructor(context: Context, attrs: Attr ta.recycle() } + + view.reminderEntryContentView.addTextChangedListener(object : TextWatcher { + override fun afterTextChanged(text: Editable?) { + textChangedListener?.invoke(text.toString()) + } + + override fun beforeTextChanged(text: CharSequence?, s: Int, c: Int, a: Int) {} + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} + }) } fun setTitle(@StringRes title: Int) { - this.title.setText(title) + reminderEntryTitleView.setText(title) } - fun setText(text: String) { - this.text.setText(text) + fun setText(text: String, moveCursorToEnd: Boolean = false) { + when(moveCursorToEnd) { + true -> reminderEntryContentView.setTextMoveCursorToEnd(text) + false -> reminderEntryContentView.setText(text) + } } fun setIcon(@DrawableRes icon: Int) { - this.icon.setImageResource(icon) + reminderEntryIconView.setImageResource(icon) } fun setOnTextChangedListener(listener: (String) -> Unit) { textChangedListener = listener } - - @OnTextChanged(R.id.reminder_entry_field) - protected fun onTextChanged(text: CharSequence) { - textChangedListener?.invoke(text.toString()) - } - } \ No newline at end of file diff --git a/app/src/main/java/com/physphil/android/remindme/ui/ReminderListDivider.kt b/app/src/main/java/com/physphil/android/remindme/ui/ReminderListDivider.kt index 14f2dec..9339e24 100644 --- a/app/src/main/java/com/physphil/android/remindme/ui/ReminderListDivider.kt +++ b/app/src/main/java/com/physphil/android/remindme/ui/ReminderListDivider.kt @@ -2,7 +2,7 @@ package com.physphil.android.remindme.ui import android.graphics.Canvas import android.graphics.drawable.Drawable -import android.support.v7.widget.RecyclerView +import androidx.recyclerview.widget.RecyclerView /** * Copyright (c) 2018 Phil Shadlyn diff --git a/app/src/main/java/com/physphil/android/remindme/ui/ScrollAwareFabBehaviour.java b/app/src/main/java/com/physphil/android/remindme/ui/ScrollAwareFabBehaviour.java index 7064ea1..44c5af4 100644 --- a/app/src/main/java/com/physphil/android/remindme/ui/ScrollAwareFabBehaviour.java +++ b/app/src/main/java/com/physphil/android/remindme/ui/ScrollAwareFabBehaviour.java @@ -1,10 +1,10 @@ package com.physphil.android.remindme.ui; import android.content.Context; -import android.support.annotation.NonNull; -import android.support.design.widget.CoordinatorLayout; -import android.support.design.widget.FloatingActionButton; -import android.support.v4.view.ViewCompat; +import androidx.annotation.NonNull; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import androidx.core.view.ViewCompat; import android.util.AttributeSet; import android.view.View; diff --git a/app/src/main/java/com/physphil/android/remindme/util/SingleLiveEvent.java b/app/src/main/java/com/physphil/android/remindme/util/SingleLiveEvent.java index 2056038..732c083 100644 --- a/app/src/main/java/com/physphil/android/remindme/util/SingleLiveEvent.java +++ b/app/src/main/java/com/physphil/android/remindme/util/SingleLiveEvent.java @@ -16,11 +16,12 @@ package com.physphil.android.remindme.util; -import android.arch.lifecycle.LifecycleOwner; -import android.arch.lifecycle.MutableLiveData; -import android.arch.lifecycle.Observer; -import android.support.annotation.MainThread; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.Observer; +import androidx.annotation.MainThread; +import androidx.annotation.Nullable; import android.util.Log; import java.util.concurrent.atomic.AtomicBoolean; @@ -42,7 +43,7 @@ public class SingleLiveEvent extends MutableLiveData { private final AtomicBoolean mPending = new AtomicBoolean(false); @MainThread - public void observe(LifecycleOwner owner, final Observer observer) { + public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) { if (hasActiveObservers()) { Log.w(TAG, "Multiple observers registered but only one will be notified of changes."); diff --git a/app/src/main/java/com/physphil/android/remindme/util/ViewExtensions.kt b/app/src/main/java/com/physphil/android/remindme/util/ViewExtensions.kt index af75f21..8d7362e 100644 --- a/app/src/main/java/com/physphil/android/remindme/util/ViewExtensions.kt +++ b/app/src/main/java/com/physphil/android/remindme/util/ViewExtensions.kt @@ -3,6 +3,7 @@ package com.physphil.android.remindme.util import android.view.View import android.view.View.GONE import android.view.View.VISIBLE +import android.widget.EditText /** * View-related extension methods @@ -16,4 +17,12 @@ import android.view.View.VISIBLE */ fun View.setVisibility(visible: Boolean) { visibility = if (visible) VISIBLE else GONE +} + +/** + * Sets the text on the [EditText], then moves the cursor to the end of the field. + */ +fun EditText.setTextMoveCursorToEnd(text: CharSequence) { + setText(text) + setSelection(text.length) } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 7e7972e..0832831 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,5 +1,5 @@ - - - - - + - + diff --git a/app/src/main/res/layout/activity_reminder.xml b/app/src/main/res/layout/activity_reminder.xml index 53dacc8..85907bf 100644 --- a/app/src/main/res/layout/activity_reminder.xml +++ b/app/src/main/res/layout/activity_reminder.xml @@ -13,7 +13,7 @@ android:orientation="vertical"> - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/view_progress_spinner.xml b/app/src/main/res/layout/view_progress_spinner.xml index 8535878..f9946ae 100644 --- a/app/src/main/res/layout/view_progress_spinner.xml +++ b/app/src/main/res/layout/view_progress_spinner.xml @@ -1,5 +1,5 @@ - + app:layout_constraintTop_toBottomOf="@+id/progressSpinnerView"/> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/view_reminder_entry.xml b/app/src/main/res/layout/view_reminder_entry.xml index b58a196..3c57002 100644 --- a/app/src/main/res/layout/view_reminder_entry.xml +++ b/app/src/main/res/layout/view_reminder_entry.xml @@ -1,5 +1,5 @@ - + app:layout_constraintStart_toStartOf="@id/reminderEntryTitleView" + app:layout_constraintTop_toBottomOf="@id/reminderEntryTitleView"/> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/view_reminder_entry_button.xml b/app/src/main/res/layout/view_reminder_entry_button.xml index b27aa9c..a4c6368 100644 --- a/app/src/main/res/layout/view_reminder_entry_button.xml +++ b/app/src/main/res/layout/view_reminder_entry_button.xml @@ -1,5 +1,5 @@ -