Skip to content

Instantly share code, notes, and snippets.

@whalemare
Last active May 26, 2017 03:07
Show Gist options
  • Save whalemare/2e7d7e5ae3d8da3134902a127e2f006b to your computer and use it in GitHub Desktop.
Save whalemare/2e7d7e5ae3d8da3134902a127e2f006b to your computer and use it in GitHub Desktop.
Kotlin samples
package ru.whalemare.vkbirthday.mvp.presenter.base
import com.hannesdorfmann.mosby.mvp.MvpBasePresenter
import com.hannesdorfmann.mosby.mvp.MvpView
/**
* @since 2017
* @author Anton Vlasov - whalemare
*/
open class BaseMvpPresenterK<V : MvpView> : MvpBasePresenter<V>() {
fun isActive(body: () -> Any): Boolean {
val attached = isViewAttached
if (attached) {
body.invoke()
}
return attached
}
}
package ru.whalemare.vkbirthday.mvp.model
import android.content.SharedPreferences
import android.content.res.Resources
import ru.whalemare.vkbirthday.R
import java.util.*
/**
* @since 2017
* @author Anton Vlasov - whalemare
*/
class BirthSettings(val sharedPreferences: SharedPreferences, val resources: Resources) : Settings {
val KEY_DEFAULT_MESSAGE = "KEY_DEFAULT_MESSAGE"
val KEY_TIME_SENDING = "KEY_TIME_SENDING"
val KEY_AUTO_SENDING = "KEY_AUTO_SENDING"
override var notificationTimeMillis: Long = 0L
get() {
field = sharedPreferences.getLong(KEY_TIME_SENDING, 0L)
if (field == 0L) {
val c = Calendar.getInstance()
c.set(Calendar.HOUR_OF_DAY, 8)
c.set(Calendar.MINUTE, 8)
c.set(Calendar.SECOND, 0)
notificationTimeMillis = field
}
return field
}
set(value) {
sharedPreferences.edit()
.putLong(KEY_TIME_SENDING, value)
.apply()
}
override var defaultMessageText: String?
get() {
return sharedPreferences.getString(KEY_DEFAULT_MESSAGE, resources.getString(R.string.text_default_message))
}
set(value) {
sharedPreferences.edit()
.putString(KEY_DEFAULT_MESSAGE, value)
.apply()
}
override var autoSending: Boolean
get() = sharedPreferences.getBoolean(KEY_AUTO_SENDING, true)
set(value) {
sharedPreferences.edit()
.putBoolean(KEY_AUTO_SENDING, value)
.apply()
}
}
package ru.whalemare.vkbirthday.ui.view
import android.content.Context
import android.support.v7.widget.TintTypedArray
import android.util.AttributeSet
import android.widget.CompoundButton
import kotlinx.android.synthetic.main.view_checkable_text.view.*
import ru.whalemare.vkbirthday.R
/**
* @since 2017
* @author Anton Vlasov - whalemare
*/
class CheckableTextView : DescriptionTextView {
lateinit var listeners: MutableList<CompoundButton.OnCheckedChangeListener>
lateinit var descriptionOn: String
lateinit var descriptionOff: String
var isAutoDescriptionChange = true
override fun getLayoutRes(): Int = R.layout.view_checkable_text
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun setup(context: Context, attrs: AttributeSet?, defStyleAttr: Int) {
super.setup(context, attrs, defStyleAttr)
listeners = ArrayList()
val a = TintTypedArray.obtainStyledAttributes(getContext(),
attrs,
R.styleable.checkableTextView,
defStyleAttr, 0)
val checked = a.getBoolean(R.styleable.checkableTextView_checked, false)
switch_checked.isChecked = checked
container_layout.setOnTouchListener { _, event ->
switch_checked.onTouchEvent(event)
}
descriptionOn = a.getString(R.styleable.checkableTextView_descriptionOn)
descriptionOff = a.getString(R.styleable.checkableTextView_descriptionOff)
addOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener { _, isChecked ->
if (isAutoDescriptionChange) {
setDescription(if (isChecked) descriptionOn else descriptionOff)
}
})
switch_checked.setOnCheckedChangeListener { buttonView, isChecked ->
for (listener in listeners) {
listener?.onCheckedChanged(buttonView, isChecked)
}
}
// for display description text by first setup
setDescription(if (switch_checked.isChecked) descriptionOn else descriptionOff)
a.recycle()
}
fun addOnCheckedChangeListener(listener: CompoundButton.OnCheckedChangeListener) {
listeners.add(listener)
}
fun removeAllListeners() {
listeners.clear()
}
}
package ru.whalemare.vkbirthday.ui.view
import android.content.Context
import android.support.v7.widget.TintTypedArray
import android.util.AttributeSet
import android.view.View
import android.widget.LinearLayout
import kotlinx.android.synthetic.main.view_double_text.view.*
import ru.whalemare.vkbirthday.R
/**
* @since 2017
* @author Anton Vlasov - whalemare
*/
open class DescriptionTextView : LinearLayout {
open fun getLayoutRes(): Int = R.layout.view_double_text
constructor(context: Context) : super(context) {
setup(context)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
setup(context, attrs)
}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
setup(context, attrs, defStyleAttr)
}
open protected fun setup(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) {
View.inflate(context, getLayoutRes(), this)
val a = TintTypedArray.obtainStyledAttributes(getContext(), attrs,
R.styleable.descriptionTextView, defStyleAttr, 0)
text_title.text = a.getString(R.styleable.descriptionTextView_title)
text_description.text = a.getString(R.styleable.descriptionTextView_description)
val enabledTop = a.getBoolean(R.styleable.descriptionTextView_topDividerEnable, false)
top_divider.visibility = if (enabledTop) View.VISIBLE else View.GONE
val enabledBottom = a.getBoolean(R.styleable.descriptionTextView_bottomDividerEnable, false)
bottom_divider.visibility = if (enabledBottom) View.VISIBLE else View.GONE
a.recycle()
}
fun setTitle(id: Int) {
val text = context.getString(id)
setTitle(text)
}
fun setDescription(id: Int) {
val text = context.getString(id)
setDescription(text)
}
fun setTitle(title: String) {
text_title.text = title
text_title.visibility = if (title.isNullOrBlank()) View.GONE else View.VISIBLE
}
fun setDescription(text: String) {
text_description.text = text
text_title.visibility = if (text.isNullOrBlank()) View.GONE else View.VISIBLE
}
}
package ru.whalemare.vkbirthday.ui.controller.settings
import android.app.TimePickerDialog
import android.content.Intent
import android.view.View
import android.widget.Button
import android.widget.CompoundButton
import android.widget.EditText
import com.afollestad.materialdialogs.MaterialDialog
import kotlinx.android.synthetic.main.controller_settings.view.*
import kotlinx.android.synthetic.main.view_checkable_text.view.*
import kotlinx.android.synthetic.main.view_double_text.view.*
import ru.whalemare.vkbirthday.BuildConfig
import ru.whalemare.vkbirthday.R
import ru.whalemare.vkbirthday.dagger.component.AppComponent
import ru.whalemare.vkbirthday.mvp.presenter.SettingsPresenter
import ru.whalemare.vkbirthday.mvp.view.SettingsView
import ru.whalemare.vkbirthday.service.BootReceiver
import ru.whalemare.vkbirthday.service.DatabaseService
import ru.whalemare.vkbirthday.ui.base.BaseMvpController
import ru.whalemare.vkbirthday.ui.view.CheckableTextView
import ru.whalemare.vkbirthday.ui.view.DescriptionTextView
import java.text.SimpleDateFormat
import java.util.*
/**
* @since 2017
* @author Anton Vlasov - whalemare
*/
class MainSettingsController : BaseMvpController<SettingsView, SettingsPresenter>(),
SettingsView {
lateinit var settingsTimeForSending: DescriptionTextView
lateinit var settingsTextByDefault: DescriptionTextView
lateinit var settingsAutoSending: CheckableTextView
lateinit var buttonSendBroadcast: Button
override fun inject(component: AppComponent) {
component.inject(this)
}
override fun getLayout(): Int {
return R.layout.controller_settings
}
override fun onBindViews(view: View) {
settingsTimeForSending = view.double_time_for_send
settingsTextByDefault = view.double_text_by_default
settingsAutoSending = view.switch_autosending
buttonSendBroadcast = view.button_send_broadcast
settingsTimeForSending.setOnClickListener { presenter.onClickTimeForSending() }
settingsTextByDefault.setOnClickListener { presenter.onClickTextByDefault() }
settingsAutoSending.addOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener { _, isChecked ->
presenter.onChangeAutoSendingState(isChecked)
})
if (BuildConfig.DEBUG) {
buttonSendBroadcast.visibility = View.VISIBLE
buttonSendBroadcast.setOnClickListener {
activity?.startService(Intent(applicationContext, DatabaseService::class.java))
}
}
}
override fun onAttach(view: View) {
super.onAttach(view)
presenter.onViewAttached()
}
override fun setDefaultMessage(defaultMessageText: String) {
settingsTextByDefault.text_description.text = defaultMessageText
}
override fun setNotificationTime(notificationTimeMillis: Long) {
val time = SimpleDateFormat("HH:mm", Locale.ROOT).format(notificationTimeMillis)
settingsTimeForSending.text_description.text = time
}
override fun pushDialogEnterMessage(defaultMessageText: String?) {
val dialog = MaterialDialog.Builder(view!!.context)
.title(R.string.title_change_congratulation)
.customView(R.layout.dialog_input, true)
.positiveText(R.string.action_save)
.negativeText(R.string.action_cancel)
.onPositive { dialog, which ->
val editText = dialog.findViewById(R.id.edit_text) as EditText
val text = editText.text.toString()
presenter.onChangeDefaultMessage(text)
}
.onNegative { dialog, which -> dialog.dismiss() }
.build()
val editText = dialog.findViewById(R.id.edit_text) as EditText
editText.setText(defaultMessageText)
dialog.show()
}
override fun pushDialogTime(hours: Int, minutes: Int) {
view?.let {
TimePickerDialog(
it.context,
TimePickerDialog.OnTimeSetListener { view, hourOfDay, minute ->
presenter.onChangeNotificationTime(hourOfDay, minute)
}, hours, minutes, true)
.show()
}
}
override fun sendBroadcastChangeTime() {
activity?.sendBroadcast(Intent(BootReceiver.CHANGE_TIME))
}
override fun showAutoSendingState(autoSending: Boolean) {
settingsAutoSending.switch_checked.isChecked = autoSending
}
}
package ru.whalemare.database
import android.util.Log
import io.realm.Realm
import io.realm.RealmResults
import ru.whalemare.database.model.Note
import ru.whalemare.database.model.Stats
import ru.whalemare.database.model.User
import java.util.*
/**
* @since 2017
* @author Anton Vlasov - whalemare
*/
class RealmDatabaseK : Database {
val COUNT_DAY_TO_RESET = 150
override fun applyStats(stats: Stats) {
val realmStats = realm.where(Stats::class.java)
.findFirst()
realm.executeTransaction {
realmStats.countAddFriends = stats.countAddFriends
realmStats.countAddNotes = stats.countAddNotes
realmStats.countAddedNotes = stats.countAddedNotes
realmStats.countSendedMessages = stats.countSendedMessages
realmStats.countAppStarted = stats.countAppStarted
it.insertOrUpdate(realmStats)
}
}
/**
* Return detached copy of Stats
*/
override fun getStats(): Stats {
var stats = realm.where(Stats::class.java)
.findFirst()
if (stats == null) {
realm.executeTransaction {
stats = realm.createObject(Stats::class.java, 0)
}
}
return realm.copyFromRealm(stats)
}
override fun deleteAll() {
realm.executeTransactionAsync(Realm::deleteAll)
}
val TAG = "Database"
override fun invalidateUsers() {
realm.where(User::class.java)
.equalTo("selected", true)
.findAllAsync()
.addChangeListener { collection, _ ->
invalidateUsers(collection)
}
}
override fun invalidateUsers(collection: RealmResults<User>) {
if (collection.isLoaded && collection.isValid) {
realm.beginTransaction()
for (user in collection) {
user.age = DateUtils.getAge(user.birthDay)
user.dayLeft = DateUtils.getDaysLeft(user.birthDay)
if (user.dayLeft <= COUNT_DAY_TO_RESET && !user.isBirthdayToday) {
user.isCongratulated = false
}
}
realm.commitTransaction()
collection.removeAllChangeListeners()
}
}
override fun getNotes(user: User): MutableList<Note> {
return realm.where(Note::class.java)
.findAllAsync()
}
override fun setCongatulated(user: User): Long {
val realmUser = realm.where(User::class.java)
.equalTo("id", user.getId())
if (realmUser != null) {
realm.executeTransaction {
user.setAlreayCongr(true)
}
return user.getId()
} else {
return -1L
}
}
override fun getUsersForSendMessage(): MutableList<User> {
return realm.where(User::class.java)
.equalTo("selected", true)
.equalTo("dayLeft", 0)
.equalTo("congratulated", false)
.findAllSortedAsync("dayLeft")
}
override fun attachNote(user: User, note: Note) {
realm.executeTransaction {
val positionUser = note.users.indexOf(user)
if (positionUser < 0) {
note.users.add(user)
} else {
note.users.removeAt(positionUser)
}
val positionNote = user.notes.indexOf(note)
if (positionNote < 0) {
user.notes.add(note)
} else {
user.notes.removeAt(positionNote)
}
Log.d(TAG, "User [${user.lastName}] has notes => ${Arrays.toString(user.notes.toArray())}")
Log.d(TAG, "Note [${note.text}] has users => ${Arrays.toString(note.users.toArray())}")
}
}
override fun editNote(old: Note, updated: String) {
realm.executeTransaction {
old.text = updated
}
}
val realm = Realm.getDefaultInstance()!!
override fun getUsers(): RealmResults<User> {
return realm.where(User::class.java)
.between("dayLeft", 0, Int.MAX_VALUE)
.findAllSortedAsync("dayLeft")
}
override fun getNotes(): MutableList<Note> {
return realm.where(Note::class.java).findAllAsync()
}
override fun saveUsers(selectedUsers: MutableList<User>?) {
Realm.getDefaultInstance().use {
it.copyToRealmOrUpdate(selectedUsers)
}
}
override fun removeSelect(user: User) {
val found = realm.where(User::class.java)
.equalTo("id", user.getId())
.findFirst()
realm.executeTransaction {
found.selected = false
}
}
override fun addNote(text: String) {
realm.executeTransactionAsync {
it.insert(Note(text))
}
}
override fun removeNote(note: Note): Boolean {
realm.executeTransaction {
note.deleteFromRealm()
}
return true
}
override fun getSelectedUsers(): RealmResults<User>? {
// invalidateUsers()
return realm.where(User::class.java)
.equalTo("selected", true)
.findAllSortedAsync("dayLeft")
}
override fun merge(remoteUsers: MutableList<User>) {
realm.executeTransactionAsync {
for (user in remoteUsers) {
val realmUser = it.where(User::class.java)
.equalTo("id", user.getId())
.findFirst()
if (realmUser != null) {
user.selected = realmUser.isSelected
user.isCongratulated = realmUser.isCongratulated
user.notes = realmUser.notes
it.insertOrUpdate(user)
} else {
it.insert(user)
}
}
}
}
override fun onUserSelectedStateChanges(id: Long?) {
realm.executeTransactionAsync {
val user = it.where(User::class.java)
.equalTo("id", id)
.findFirst()
user.selected = !user.isSelected
it.insertOrUpdate(user)
}
}
override fun revertCongatulated(user: User) {
val realmUser = realm.where(User::class.java)
.equalTo("id", user.getId())
if (realmUser != null) {
realm.executeTransaction {
user.setAlreayCongr(!user.isCongratulated)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment