Skip to content
Snippets Groups Projects
Commit f6975e69 authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Implemented account setup, selection and editing

parent 7beb1463
Branches
Tags
No related merge requests found
Showing
with 714 additions and 106 deletions
...@@ -13,10 +13,11 @@ ...@@ -13,10 +13,11 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<activity <activity
android:name=".ui.MainActivity" android:name=".ui.ChatActivity"
android:exported="true" android:exported="true"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/SplashTheme"> android:theme="@style/SplashTheme"
android:windowSoftInputMode="adjustResize">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
...@@ -25,10 +26,23 @@ ...@@ -25,10 +26,23 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
android:name=".ui.setup.AccountSetupActivity" android:name=".ui.setup.accounts.AccountSetupActivity"
android:exported="true" android:exported="false"
android:label="AccountSetup" android:label="AccountSetup"
android:theme="@style/SplashTheme" /> android:theme="@style/SplashTheme"
android:windowSoftInputMode="adjustResize" />
<activity
android:name=".ui.setup.accounts.AccountEditActivity"
android:exported="true"
android:label="AccountEdit"
android:theme="@style/SplashTheme"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="de.kuschku.quasseldroid_ng.ui.setup.accounts.AccountSelectionActivity"
android:exported="true"
android:label="AccountSelection"
android:theme="@style/SplashTheme"
android:windowSoftInputMode="adjustResize" />
<service <service
android:name=".service.QuasselService" android:name=".service.QuasselService"
......
...@@ -2,12 +2,10 @@ package de.kuschku.quasseldroid_ng ...@@ -2,12 +2,10 @@ package de.kuschku.quasseldroid_ng
import android.app.Application import android.app.Application
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.pm.ShortcutInfo import android.content.pm.ShortcutInfo
import android.content.pm.ShortcutManager import android.content.pm.ShortcutManager
import android.graphics.drawable.Icon import android.graphics.drawable.Icon
import android.os.Build import android.os.Build
import de.kuschku.quasseldroid_ng.service.QuasselService
import de.kuschku.quasseldroid_ng.util.AndroidCompatibilityUtils import de.kuschku.quasseldroid_ng.util.AndroidCompatibilityUtils
import de.kuschku.quasseldroid_ng.util.AndroidLoggingHandler import de.kuschku.quasseldroid_ng.util.AndroidLoggingHandler
import de.kuschku.quasseldroid_ng.util.AndroidStreamChannelFactory import de.kuschku.quasseldroid_ng.util.AndroidStreamChannelFactory
...@@ -26,7 +24,7 @@ class QuasseldroidNG : Application() { ...@@ -26,7 +24,7 @@ class QuasseldroidNG : Application() {
.setResDialogText(R.string.crash_text) .setResDialogText(R.string.crash_text)
.build() .build()
ACRA.init(this, config) //ACRA.init(this, config)
} }
override fun onCreate() { override fun onCreate() {
...@@ -38,7 +36,6 @@ class QuasseldroidNG : Application() { ...@@ -38,7 +36,6 @@ class QuasseldroidNG : Application() {
AndroidLoggingHandler.inject() AndroidLoggingHandler.inject()
AndroidStreamChannelFactory.inject() AndroidStreamChannelFactory.inject()
startService(Intent(this, QuasselService::class.java))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
systemService<ShortcutManager>().dynamicShortcuts = listOf( systemService<ShortcutManager>().dynamicShortcuts = listOf(
ShortcutInfo.Builder(this, "id1") ShortcutInfo.Builder(this, "id1")
......
package de.kuschku.quasseldroid_ng.persistence
import android.arch.paging.LivePagedListProvider
import android.arch.persistence.room.*
import android.content.Context
@Database(entities = arrayOf(AccountDatabase.Account::class), version = 1)
abstract class AccountDatabase : RoomDatabase() {
abstract fun accounts(): AccountDao
@Entity
data class Account(
@PrimaryKey(autoGenerate = true)
var id: Long,
var host: String,
var port: Int,
var user: String,
var pass: String,
var name: String,
var lastUsed: Long
)
@Dao
interface AccountDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun save(vararg entities: AccountDatabase.Account)
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun create(vararg entities: AccountDatabase.Account): Array<Long>
@Query("SELECT * FROM account WHERE id = :id")
fun findById(id: Long): AccountDatabase.Account
@Query("SELECT * FROM account ORDER BY lastUsed DESC")
fun all(): LivePagedListProvider<Int, Account>
@Delete
fun delete(account: AccountDatabase.Account)
@Query("DELETE FROM account")
fun clear()
}
object Creator {
private var database: AccountDatabase? = null
private set
// For Singleton instantiation
private val LOCK = Any()
fun init(context: Context): AccountDatabase {
if (database == null) {
synchronized(LOCK) {
if (database == null) {
database = Room.databaseBuilder(context.applicationContext,
AccountDatabase::class.java, DATABASE_NAME)
.build()
}
}
}
return database!!
}
}
companion object {
const val DATABASE_NAME = "persistence-accounts"
}
}
...@@ -133,7 +133,6 @@ abstract class QuasselDatabase : RoomDatabase() { ...@@ -133,7 +133,6 @@ abstract class QuasselDatabase : RoomDatabase() {
if (database == null) { if (database == null) {
database = Room.databaseBuilder(context.applicationContext, database = Room.databaseBuilder(context.applicationContext,
QuasselDatabase::class.java, DATABASE_NAME) QuasselDatabase::class.java, DATABASE_NAME)
.fallbackToDestructiveMigration()
.build() .build()
} }
} }
......
...@@ -47,15 +47,10 @@ class QuasselService : LifecycleService() { ...@@ -47,15 +47,10 @@ class QuasselService : LifecycleService() {
} }
} }
private val asyncBackend = object : Backend {
private val thread = HandlerThread("BackendHandler") private val thread = HandlerThread("BackendHandler")
private val handler: Handler private lateinit var handler: Handler
init {
thread.start()
handler = Handler(thread.looper)
}
private val asyncBackend = object : Backend {
override fun connect(address: SocketAddress, user: String, pass: String) { override fun connect(address: SocketAddress, user: String, pass: String) {
handler.post { handler.post {
backendImplementation.connect(address, user, pass) backendImplementation.connect(address, user, pass)
...@@ -71,9 +66,16 @@ class QuasselService : LifecycleService() { ...@@ -71,9 +66,16 @@ class QuasselService : LifecycleService() {
override fun sessionManager() = backendImplementation.sessionManager() override fun sessionManager() = backendImplementation.sessionManager()
} }
override fun onDestroy() {
handler.post { thread.quit() }
super.onDestroy()
}
private lateinit var database: QuasselDatabase private lateinit var database: QuasselDatabase
override fun onCreate() { override fun onCreate() {
thread.start()
handler = Handler(thread.looper)
super.onCreate() super.onCreate()
database = QuasselDatabase.Creator.init(application) database = QuasselDatabase.Creator.init(application)
sessionManager = SessionManager(ISession.NULL) sessionManager = SessionManager(ISession.NULL)
......
...@@ -2,6 +2,7 @@ package de.kuschku.quasseldroid_ng.ui ...@@ -2,6 +2,7 @@ package de.kuschku.quasseldroid_ng.ui
import android.arch.lifecycle.LiveDataReactiveStreams import android.arch.lifecycle.LiveDataReactiveStreams
import android.arch.lifecycle.Observer import android.arch.lifecycle.Observer
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.support.design.widget.Snackbar import android.support.design.widget.Snackbar
import android.util.Log import android.util.Log
...@@ -17,13 +18,14 @@ import de.kuschku.libquassel.session.ConnectionState ...@@ -17,13 +18,14 @@ import de.kuschku.libquassel.session.ConnectionState
import de.kuschku.libquassel.session.SocketAddress import de.kuschku.libquassel.session.SocketAddress
import de.kuschku.libquassel.util.compatibility.LoggingHandler import de.kuschku.libquassel.util.compatibility.LoggingHandler
import de.kuschku.quasseldroid_ng.R import de.kuschku.quasseldroid_ng.R
import de.kuschku.quasseldroid_ng.service.QuasselService
import de.kuschku.quasseldroid_ng.util.helper.stickyMapNotNull import de.kuschku.quasseldroid_ng.util.helper.stickyMapNotNull
import de.kuschku.quasseldroid_ng.util.helper.stickySwitchMapNotNull import de.kuschku.quasseldroid_ng.util.helper.stickySwitchMapNotNull
import org.threeten.bp.ZoneOffset import org.threeten.bp.ZoneOffset
import org.threeten.bp.ZonedDateTime import org.threeten.bp.ZonedDateTime
import org.threeten.bp.format.DateTimeFormatter import org.threeten.bp.format.DateTimeFormatter
class MainActivity : ServiceBoundActivity() { class ChatActivity : ServiceBoundActivity() {
@BindView(R.id.host) @BindView(R.id.host)
lateinit var host: EditText lateinit var host: EditText
...@@ -77,6 +79,7 @@ class MainActivity : ServiceBoundActivity() { ...@@ -77,6 +79,7 @@ class MainActivity : ServiceBoundActivity() {
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
startService(Intent(this, QuasselService::class.java))
setTheme(R.style.AppTheme) setTheme(R.style.AppTheme)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
......
package de.kuschku.quasseldroid_ng.ui.setup
import android.os.Bundle
import de.kuschku.quasseldroid_ng.ui.setup.slides.AccountSetupConnectionSlide
import de.kuschku.quasseldroid_ng.ui.setup.slides.AccountSetupNameSlide
import de.kuschku.quasseldroid_ng.ui.setup.slides.AccountSetupUserSlide
class AccountSetupActivity : SetupActivity() {
override fun onDone(data: Bundle) {
}
override val fragments = listOf(
AccountSetupConnectionSlide(),
AccountSetupUserSlide(),
AccountSetupNameSlide()
)
}
...@@ -14,7 +14,6 @@ import android.view.ViewGroup ...@@ -14,7 +14,6 @@ import android.view.ViewGroup
import butterknife.BindView import butterknife.BindView
import butterknife.ButterKnife import butterknife.ButterKnife
import de.kuschku.quasseldroid_ng.R import de.kuschku.quasseldroid_ng.R
import de.kuschku.quasseldroid_ng.ui.setup.slides.SlideFragment
import de.kuschku.quasseldroid_ng.util.helper.stickySwitchMapNotNull import de.kuschku.quasseldroid_ng.util.helper.stickySwitchMapNotNull
abstract class SetupActivity : AppCompatActivity() { abstract class SetupActivity : AppCompatActivity() {
...@@ -86,30 +85,33 @@ abstract class SetupActivity : AppCompatActivity() { ...@@ -86,30 +85,33 @@ abstract class SetupActivity : AppCompatActivity() {
onDone(adapter.result) onDone(adapter.result)
} }
fun setInitData(data: Bundle?) {
adapter.result.putAll(data)
}
abstract fun onDone(data: Bundle) abstract fun onDone(data: Bundle)
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
outState.putInt("currentItem", viewPager.currentItem) outState.putInt(currentItemKey, viewPager.currentItem)
outState.putInt("lastValidItem", adapter.lastValidItem) outState.putInt(lastValidItemKey, adapter.lastValidItem)
outState.putBundle("result", adapter.result) outState.putBundle(resultKey, adapter.result)
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
} }
override fun onRestoreInstanceState(savedInstanceState: Bundle?) { override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
super.onRestoreInstanceState(savedInstanceState) super.onRestoreInstanceState(savedInstanceState)
if (savedInstanceState != null) { if (savedInstanceState != null) {
if (savedInstanceState.containsKey("result")) if (savedInstanceState.containsKey(resultKey))
adapter.result.putAll(savedInstanceState.getBundle("result")) adapter.result.putAll(savedInstanceState.getBundle(resultKey))
if (savedInstanceState.containsKey("lastValidItem")) if (savedInstanceState.containsKey(lastValidItemKey))
adapter.lastValidItem = savedInstanceState.getInt("lastValidItem") adapter.lastValidItem = savedInstanceState.getInt(lastValidItemKey)
if (savedInstanceState.containsKey("currentItem")) if (savedInstanceState.containsKey(currentItemKey))
viewPager.currentItem = savedInstanceState.getInt("currentItem") viewPager.currentItem = savedInstanceState.getInt(currentItemKey)
currentPage.value = adapter.getItem(viewPager.currentItem) currentPage.value = adapter.getItem(viewPager.currentItem)
} }
pageChanged() pageChanged()
} }
companion object {
private class SlidePagerAdapter(private val fragmentManager: FragmentManager) : private class SlidePagerAdapter(private val fragmentManager: FragmentManager) :
FragmentStatePagerAdapter(fragmentManager) { FragmentStatePagerAdapter(fragmentManager) {
private val retainedFragments = SparseArray<SlideFragment>() private val retainedFragments = SparseArray<SlideFragment>()
...@@ -141,7 +143,7 @@ abstract class SetupActivity : AppCompatActivity() { ...@@ -141,7 +143,7 @@ abstract class SetupActivity : AppCompatActivity() {
override fun instantiateItem(container: ViewGroup?, position: Int): Any { override fun instantiateItem(container: ViewGroup?, position: Int): Any {
val fragment = super.instantiateItem(container, position) val fragment = super.instantiateItem(container, position)
retainedFragments.put(position, fragment as SlideFragment) storeNewFragment(position, fragment as SlideFragment)
return fragment return fragment
} }
...@@ -161,12 +163,22 @@ abstract class SetupActivity : AppCompatActivity() { ...@@ -161,12 +163,22 @@ abstract class SetupActivity : AppCompatActivity() {
val index = Integer.parseInt(key.substring(1)) val index = Integer.parseInt(key.substring(1))
val f = fragmentManager.getFragment(bundle, key) val f = fragmentManager.getFragment(bundle, key)
if (f != null && f is SlideFragment) { if (f != null && f is SlideFragment) {
retainedFragments.put(index, f) storeNewFragment(index, f)
} }
} }
} }
} }
} }
private fun storeNewFragment(index: Int, fragment: SlideFragment) {
fragment.initData = result
retainedFragments.put(index, fragment)
} }
} }
companion object {
private const val currentItemKey = ":setupActivity:currentItem"
private const val lastValidItemKey = ":setupActivity:lastValidItem"
private const val resultKey = ":setupActivity:result"
}
} }
package de.kuschku.quasseldroid_ng.ui.setup.slides package de.kuschku.quasseldroid_ng.ui.setup
import android.arch.lifecycle.LifecycleOwner import android.arch.lifecycle.LifecycleOwner
import android.arch.lifecycle.MutableLiveData import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.Observer import android.arch.lifecycle.Observer
import android.os.Bundle import android.os.Bundle
import android.support.annotation.StringRes import android.support.annotation.StringRes
import android.support.design.widget.CollapsingToolbarLayout
import android.support.v4.app.Fragment import android.support.v4.app.Fragment
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
...@@ -16,7 +17,7 @@ abstract class SlideFragment : Fragment() { ...@@ -16,7 +17,7 @@ abstract class SlideFragment : Fragment() {
@get:StringRes @get:StringRes
protected abstract val title: Int protected abstract val title: Int
@get:StringRes @get:StringRes
protected abstract val descripion: Int protected abstract val description: Int
protected abstract fun isValid(): Boolean protected abstract fun isValid(): Boolean
...@@ -33,9 +34,7 @@ abstract class SlideFragment : Fragment() { ...@@ -33,9 +34,7 @@ abstract class SlideFragment : Fragment() {
} }
protected fun updateValidity() { protected fun updateValidity() {
val valid1 = isValid() valid.value = isValid()
println("Updating validity: ${this::class.java.simpleName}@${hashCode()} $valid1")
valid.value = valid1
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
...@@ -44,9 +43,14 @@ abstract class SlideFragment : Fragment() { ...@@ -44,9 +43,14 @@ abstract class SlideFragment : Fragment() {
val viewGroup = view.findViewById<View>(R.id.content_host) as ViewGroup val viewGroup = view.findViewById<View>(R.id.content_host) as ViewGroup
viewGroup.addView(onCreateContent(inflater, viewGroup, savedInstanceState)) viewGroup.addView(onCreateContent(inflater, viewGroup, savedInstanceState))
view.findViewById<TextView>(R.id.title).setText(title) view.findViewById<TextView>(R.id.title)?.setText(title)
view.findViewById<TextView>(R.id.description).setText(descripion) view.findViewById<CollapsingToolbarLayout>(R.id.collapsingToolbar)?.title = resources.getString(
title)
view.findViewById<TextView>(R.id.description).setText(description)
val data = initData
if (data != null)
setData(data)
if (savedInstanceState != null) if (savedInstanceState != null)
setData(savedInstanceState) setData(savedInstanceState)
updateValidity() updateValidity()
...@@ -66,6 +70,7 @@ abstract class SlideFragment : Fragment() { ...@@ -66,6 +70,7 @@ abstract class SlideFragment : Fragment() {
abstract fun setData(data: Bundle) abstract fun setData(data: Bundle)
abstract fun getData(data: Bundle) abstract fun getData(data: Bundle)
var initData: Bundle? = null
protected abstract fun onCreateContent(inflater: LayoutInflater, container: ViewGroup?, protected abstract fun onCreateContent(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View savedInstanceState: Bundle?): View
......
package de.kuschku.quasseldroid_ng.ui.setup.slides package de.kuschku.quasseldroid_ng.ui.setup
interface ValidityChangeCallback { interface ValidityChangeCallback {
fun invoke(isValid: Boolean) fun invoke(isValid: Boolean)
......
package de.kuschku.quasseldroid_ng.ui.setup.accounts
import android.arch.lifecycle.MutableLiveData
import android.arch.paging.PagedListAdapter
import android.support.v7.recyclerview.extensions.DiffCallback
import android.support.v7.widget.AppCompatImageButton
import android.support.v7.widget.AppCompatRadioButton
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import butterknife.BindView
import butterknife.ButterKnife
import de.kuschku.quasseldroid_ng.R
import de.kuschku.quasseldroid_ng.persistence.AccountDatabase
class AccountAdapter :
PagedListAdapter<AccountDatabase.Account, AccountAdapter.AccountViewHolder>(DIFF_CALLBACK) {
private val actionListeners = mutableSetOf<(Long) -> Unit>()
private val addListeners = mutableSetOf<() -> Unit>()
val selectedItemId: Long
get() {
val position = selectedPos.value
return if (position != null && position > -1 && position < super.getItemCount())
getItem(position)?.id ?: -1
else
-1
}
private val clickListener = object : ItemListener {
override fun onAction(id: Long, pos: Int) {
changeSelection(id, pos)
}
}
private val actionListener = object : ItemListener {
override fun onAction(id: Long, pos: Int) {
for (actionListener in actionListeners) {
actionListener.invoke(id)
}
}
}
private val addListener = {
for (addListener in addListeners) {
addListener.invoke()
}
}
fun addEditListener(f: (Long) -> Unit) {
actionListeners.add(f)
}
fun removeEditListener(f: (Long) -> Unit) {
actionListeners.remove(f)
}
fun addAddListener(f: () -> Unit) {
addListeners.add(f)
}
fun removeAddListener(f: () -> Unit) {
addListeners.remove(f)
}
override fun onBindViewHolder(holder: AccountViewHolder, position: Int) {
when (holder) {
is AccountViewHolder.Item -> {
val account = getItem(position)
if (account == null) {
holder.clear()
} else {
val selected = selectedId == account.id
holder.bind(account, position, selected)
if (selected && position != selectedPos.value)
holder.itemView.post {
changeSelection(account.id, position)
}
}
}
is AccountViewHolder.Add -> {
}
}
}
override fun getItemViewType(position: Int) = when (position) {
super.getItemCount() -> TYPE_ADD
else -> TYPE_ACCOUNT
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AccountViewHolder {
val inflater = LayoutInflater.from(parent.context)
val view = inflater.inflate(
when (viewType) {
TYPE_ADD -> R.layout.widget_core_account_add
else -> R.layout.widget_core_account
}, parent, false)
return when (viewType) {
TYPE_ADD -> AccountViewHolder.Add(view, addListener)
else -> AccountViewHolder.Item(view, actionListener, clickListener)
}
}
override fun getItemCount(): Int {
return super.getItemCount() + 1
}
companion object {
private const val TYPE_ACCOUNT = 0
private const val TYPE_ADD = 1
private val DIFF_CALLBACK = object : DiffCallback<AccountDatabase.Account>() {
override fun areContentsTheSame(oldItem: AccountDatabase.Account,
newItem: AccountDatabase.Account): Boolean {
return oldItem == newItem
}
override fun areItemsTheSame(oldItem: AccountDatabase.Account,
newItem: AccountDatabase.Account): Boolean {
return oldItem.id == newItem.id
}
}
}
private fun notifySelectionChanged(from: Int?, to: Int?) {
if (from != null && from != -1)
notifyItemChanged(from)
val real_to = to ?: -1
selectedPos.value = real_to
if (to != null && to != -1)
notifyItemChanged(to)
}
fun changeSelection(id: Long, position: Int) {
notifySelectionChanged(selectedPos.value, position)
selectedId = id
}
private fun indexOf(id: Long) = (0 until itemCount).lastOrNull {
getItemViewType(it) == TYPE_ACCOUNT && getItem(it)?.id == id
} ?: -1
fun selectAccount(id: Long) {
val index = indexOf(id)
if (index != -1) {
changeSelection(id, index)
} else {
selectedId = id
}
}
private var selectedId = -1L
var selectedPos = MutableLiveData<Int>()
interface ItemListener {
fun onAction(id: Long, pos: Int)
}
sealed class AccountViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
class Item(itemView: View, actionListener: ItemListener, clickListener: ItemListener)
: AccountViewHolder(itemView) {
@BindView(R.id.account_name)
lateinit var accountName: TextView
@BindView(R.id.account_description)
lateinit var accountDescription: TextView
@BindView(R.id.account_select)
lateinit var accountSelect: AppCompatRadioButton
@BindView(R.id.account_edit)
lateinit var accountEdit: AppCompatImageButton
private var id = -1L
private var index = -1
init {
ButterKnife.bind(this, itemView)
accountEdit.setOnClickListener {
actionListener.onAction(id, index)
}
itemView.setOnClickListener {
clickListener.onAction(id, index)
}
}
fun bind(account: AccountDatabase.Account, position: Int, selected: Boolean) {
index = position
id = account.id
accountName.text = account.name
accountDescription.text = itemView.context.resources.getString(
R.string.userOnHost, account.user, account.host, account.port
)
accountSelect.isChecked = selected
}
fun clear() {
index = -1
id = -1L
accountName.text = ""
accountDescription.text = ""
accountSelect.isChecked = false
}
}
class Add(itemView: View, clickListener: () -> Unit) : AccountViewHolder(itemView) {
init {
itemView.setOnClickListener {
clickListener.invoke()
}
}
}
}
}
package de.kuschku.quasseldroid_ng.ui.setup.accounts
import android.app.Activity
import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
import android.support.design.widget.FloatingActionButton
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity
import android.view.Menu
import android.view.MenuItem
import android.widget.TextView
import butterknife.BindView
import butterknife.ButterKnife
import de.kuschku.quasseldroid_ng.R
import de.kuschku.quasseldroid_ng.persistence.AccountDatabase
class AccountEditActivity : AppCompatActivity() {
@BindView(R.id.name)
lateinit var name: TextView
@BindView(R.id.host)
lateinit var host: TextView
@BindView(R.id.port)
lateinit var port: TextView
@BindView(R.id.user)
lateinit var user: TextView
@BindView(R.id.pass)
lateinit var pass: TextView
@BindView(R.id.save_button)
lateinit var saveButton: FloatingActionButton
private var accountId: Long = -1
private var account: AccountDatabase.Account? = null
lateinit var database: AccountDatabase
private val thread = HandlerThread("AccountEdit")
private lateinit var handler: Handler
override fun onCreate(savedInstanceState: Bundle?) {
thread.start()
handler = Handler(thread.looper)
setTheme(R.style.AppTheme)
super.onCreate(savedInstanceState)
setContentView(R.layout.setup_account_edit)
ButterKnife.bind(this)
saveButton.setOnClickListener {
val it = account
if (it != null) {
it.name = name.text.toString()
it.host = host.text.toString()
it.port = port.text.toString().toIntOrNull() ?: 4242
it.user = user.text.toString()
it.pass = pass.text.toString()
handler.post {
database.accounts().save(it)
setResult(Activity.RESULT_OK)
finish()
}
}
}
database = AccountDatabase.Creator.init(this)
handler.post {
accountId = intent.getLongExtra("account", -1)
if (accountId == -1L) {
setResult(Activity.RESULT_CANCELED)
finish()
}
account = database.accounts().findById(accountId)
if (account == null) {
setResult(Activity.RESULT_CANCELED)
finish()
}
name.text = account?.name
host.text = account?.host
port.text = account?.port?.toString()
user.text = account?.user
pass.text = account?.pass
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.setup_edit_account, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onDestroy() {
handler.post { thread.quit() }
super.onDestroy()
}
override fun onOptionsItemSelected(item: MenuItem?) = when (item?.itemId) {
R.id.delete -> {
AlertDialog.Builder(this)
.setTitle("Delete?")
.setMessage("Are you sure?")
.setPositiveButton("Delete") { _, _ ->
val it = account
if (it != null)
handler.post {
database.accounts().delete(it)
}
setResult(Activity.RESULT_OK)
finish()
}
.setNegativeButton("Cancel") { dialogInterface, _ ->
dialogInterface.cancel()
}
.show()
true
}
else -> super.onOptionsItemSelected(item)
}
}
package de.kuschku.quasseldroid_ng.ui.setup.accounts
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import de.kuschku.quasseldroid_ng.ui.setup.SetupActivity
import de.kuschku.quasseldroid_ng.util.helper.editCommit
class AccountSelectionActivity : SetupActivity() {
override val fragments = listOf(
AccountSelectionSlide()
)
lateinit var statusPreferences: SharedPreferences
override fun onDone(data: Bundle) {
statusPreferences.editCommit {
putLong(selectedAccountKey, data.getLong(selectedAccountKey, -1))
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
statusPreferences = this.getSharedPreferences("status", Context.MODE_PRIVATE)
val data = Bundle()
data.putLong(selectedAccountKey, statusPreferences.getLong(selectedAccountKey, -1))
setInitData(data)
}
companion object {
private const val selectedAccountKey = "selectedAccount"
}
}
package de.kuschku.quasseldroid_ng.ui.setup.accounts
import android.arch.lifecycle.Observer
import android.arch.lifecycle.ViewModelProviders
import android.arch.paging.PagedList
import android.content.Intent
import android.os.Bundle
import android.support.v7.widget.DefaultItemAnimator
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import butterknife.BindView
import butterknife.ButterKnife
import de.kuschku.quasseldroid_ng.R
import de.kuschku.quasseldroid_ng.persistence.AccountDatabase
import de.kuschku.quasseldroid_ng.ui.setup.SlideFragment
class AccountSelectionSlide : SlideFragment() {
@BindView(R.id.account_list)
lateinit var accountList: RecyclerView
override fun isValid() = adapter.selectedPos.value ?: -1 != -1
override val title = R.string.slideAccountSelectTitle
override val description = R.string.slideAccountSelectDescription
override fun setData(data: Bundle) {
if (data.containsKey("selectedAccount"))
adapter.selectAccount(data.getLong("selectedAccount"))
}
override fun getData(data: Bundle) {
data.putLong("selectedAccount", adapter.selectedItemId)
}
private val adapter = AccountAdapter()
override fun onCreateContent(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View {
val view = inflater.inflate(R.layout.setup_select_account, container, false)
ButterKnife.bind(this, view)
val accountViewmodel = ViewModelProviders.of(this).get(
AccountViewModel::class.java)
val firstObserver = object : Observer<PagedList<AccountDatabase.Account>?> {
override fun onChanged(t: PagedList<AccountDatabase.Account>?) {
if (t?.isEmpty() != false)
startActivityForResult(Intent(context, AccountSetupActivity::class.java), -1)
accountViewmodel.accounts.removeObserver(this)
}
}
accountViewmodel.accounts.observe(this, firstObserver)
accountViewmodel.accounts.observe(this, Observer(adapter::setList))
accountList.layoutManager = LinearLayoutManager(context)
accountList.itemAnimator = DefaultItemAnimator()
accountList.adapter = adapter
adapter.selectedPos.observe(this, Observer {
updateValidity()
})
adapter.addAddListener {
startActivityForResult(Intent(context, AccountSetupActivity::class.java), -1)
}
adapter.addEditListener { id ->
val intent = Intent(context, AccountEditActivity::class.java)
intent.putExtra("account", id)
startActivityForResult(intent, -1)
}
return view
}
}
package de.kuschku.quasseldroid_ng.ui.setup.accounts
import android.app.Activity
import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
import de.kuschku.quasseldroid_ng.persistence.AccountDatabase
import de.kuschku.quasseldroid_ng.ui.setup.SetupActivity
import org.threeten.bp.Instant
class AccountSetupActivity : SetupActivity() {
private val thread = HandlerThread("Setup")
private lateinit var handler: Handler
override fun onDone(data: Bundle) {
val account = AccountDatabase.Account(
id = 0,
host = data.getString("host"),
port = data.getInt("port"),
user = data.getString("user"),
pass = data.getString("pass"),
name = data.getString("name"),
lastUsed = Instant.now().epochSecond
)
handler.post {
val (id) = AccountDatabase.Creator.init(this).accounts().create(account)
runOnUiThread {
setResult(Activity.RESULT_OK)
finish()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
thread.start()
handler = Handler(thread.looper)
super.onCreate(savedInstanceState)
}
override fun onDestroy() {
handler.post { thread.quit() }
super.onDestroy()
}
override val fragments = listOf(
AccountSetupConnectionSlide(),
AccountSetupUserSlide(),
AccountSetupNameSlide()
)
}
package de.kuschku.quasseldroid_ng.ui.setup.slides package de.kuschku.quasseldroid_ng.ui.setup.accounts
import android.os.Bundle import android.os.Bundle
import android.support.design.widget.TextInputEditText import android.support.design.widget.TextInputEditText
...@@ -10,6 +10,7 @@ import android.view.ViewGroup ...@@ -10,6 +10,7 @@ import android.view.ViewGroup
import butterknife.BindView import butterknife.BindView
import butterknife.ButterKnife import butterknife.ButterKnife
import de.kuschku.quasseldroid_ng.R import de.kuschku.quasseldroid_ng.R
import de.kuschku.quasseldroid_ng.ui.setup.SlideFragment
class AccountSetupConnectionSlide : SlideFragment() { class AccountSetupConnectionSlide : SlideFragment() {
@BindView(R.id.host) @BindView(R.id.host)
...@@ -29,7 +30,7 @@ class AccountSetupConnectionSlide : SlideFragment() { ...@@ -29,7 +30,7 @@ class AccountSetupConnectionSlide : SlideFragment() {
} }
override val title = R.string.slideAccountConnectionTitle override val title = R.string.slideAccountConnectionTitle
override val descripion = R.string.slideAccountConnectionDescription override val description = R.string.slideAccountConnectionDescription
override fun setData(data: Bundle) { override fun setData(data: Bundle) {
if (data.containsKey("host")) if (data.containsKey("host"))
......
package de.kuschku.quasseldroid_ng.ui.setup.slides package de.kuschku.quasseldroid_ng.ui.setup.accounts
import android.os.Bundle import android.os.Bundle
import android.support.design.widget.TextInputEditText import android.support.design.widget.TextInputEditText
...@@ -10,6 +10,7 @@ import android.view.ViewGroup ...@@ -10,6 +10,7 @@ import android.view.ViewGroup
import butterknife.BindView import butterknife.BindView
import butterknife.ButterKnife import butterknife.ButterKnife
import de.kuschku.quasseldroid_ng.R import de.kuschku.quasseldroid_ng.R
import de.kuschku.quasseldroid_ng.ui.setup.SlideFragment
class AccountSetupNameSlide : SlideFragment() { class AccountSetupNameSlide : SlideFragment() {
@BindView(R.id.name) @BindView(R.id.name)
...@@ -26,7 +27,7 @@ class AccountSetupNameSlide : SlideFragment() { ...@@ -26,7 +27,7 @@ class AccountSetupNameSlide : SlideFragment() {
} }
override val title = R.string.slideAccountNameTitle override val title = R.string.slideAccountNameTitle
override val descripion = R.string.slideAccountNameDescription override val description = R.string.slideAccountNameDescription
override fun setData(data: Bundle) { override fun setData(data: Bundle) {
if (data.containsKey("name")) if (data.containsKey("name"))
......
package de.kuschku.quasseldroid_ng.ui.setup.slides package de.kuschku.quasseldroid_ng.ui.setup.accounts
import android.os.Bundle import android.os.Bundle
import android.support.design.widget.TextInputEditText import android.support.design.widget.TextInputEditText
...@@ -10,6 +10,7 @@ import android.view.ViewGroup ...@@ -10,6 +10,7 @@ import android.view.ViewGroup
import butterknife.BindView import butterknife.BindView
import butterknife.ButterKnife import butterknife.ButterKnife
import de.kuschku.quasseldroid_ng.R import de.kuschku.quasseldroid_ng.R
import de.kuschku.quasseldroid_ng.ui.setup.SlideFragment
class AccountSetupUserSlide : SlideFragment() { class AccountSetupUserSlide : SlideFragment() {
@BindView(R.id.user) @BindView(R.id.user)
...@@ -29,7 +30,7 @@ class AccountSetupUserSlide : SlideFragment() { ...@@ -29,7 +30,7 @@ class AccountSetupUserSlide : SlideFragment() {
} }
override val title = R.string.slideAccountUserTitle override val title = R.string.slideAccountUserTitle
override val descripion = R.string.slideAccountUserDescription override val description = R.string.slideAccountUserDescription
override fun setData(data: Bundle) { override fun setData(data: Bundle) {
if (data.containsKey("user")) if (data.containsKey("user"))
......
package de.kuschku.quasseldroid_ng.ui.setup.accounts
import android.app.Application
import android.arch.lifecycle.AndroidViewModel
import android.arch.lifecycle.LiveData
import android.arch.paging.PagedList
import de.kuschku.quasseldroid_ng.persistence.AccountDatabase
class AccountViewModel(application: Application) : AndroidViewModel(application) {
private val database: AccountDatabase = AccountDatabase.Creator.init(
getApplication())
val accounts: LiveData<PagedList<AccountDatabase.Account>> = database.accounts().all().create(
0,
PagedList.Config.Builder()
.setPageSize(50)
.setPrefetchDistance(50)
.build()
)
}
package de.kuschku.quasseldroid_ng.util.helper
import de.kuschku.quasseldroid_ng.persistence.AccountDatabase
fun AccountDatabase.AccountDao.new(vararg entities: AccountDatabase.Account) {
val ids = create(*entities)
for (i in 0 until entities.size) {
entities[i].id = ids[i]
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment