Last active
May 26, 2017 03:07
-
-
Save whalemare/2e7d7e5ae3d8da3134902a127e2f006b to your computer and use it in GitHub Desktop.
Kotlin samples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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