diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d7b29b283f5d79f8a3a620aeb30fc53c5d8d052f..88dc8ff21fd6dbc957e042ea23207fe2b993823a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,8 @@ android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/Theme.SplashTheme"> + + <!-- Normal Chat --> <activity android:name=".ui.chat.ChatActivity" android:exported="true" @@ -40,18 +42,33 @@ android:parentActivityName=".ui.chat.ChatActivity" android:windowSoftInputMode="adjustResize" /> + <!-- Client Settings --> <activity - android:name=".ui.setup.accounts.setup.AccountSetupActivity" + android:name=".ui.clientsettings.app.AppSettingsActivity" android:exported="false" - android:label="@string/app_name" - android:parentActivityName=".ui.setup.accounts.selection.AccountSelectionActivity" + android:label="@string/label_settings_client" + android:parentActivityName=".ui.chat.ChatActivity" android:windowSoftInputMode="adjustResize" /> <activity - android:name=".ui.setup.accounts.edit.AccountEditActivity" + android:name=".ui.clientsettings.crash.CrashSettingsActivity" android:exported="false" - android:label="@string/app_name" - android:parentActivityName=".ui.setup.accounts.selection.AccountSelectionActivity" + android:label="@string/label_crashes" + android:parentActivityName=".ui.clientsettings.app.AppSettingsActivity" android:windowSoftInputMode="adjustResize" /> + <activity + android:name=".ui.clientsettings.about.AboutSettingsActivity" + android:exported="false" + android:label="@string/label_about" + android:parentActivityName=".ui.clientsettings.app.AppSettingsActivity" + android:windowSoftInputMode="adjustResize" /> + <activity + android:name=".ui.clientsettings.license.LicenseSettingsActivity" + android:exported="false" + android:label="@string/label_license" + android:parentActivityName=".ui.clientsettings.about.AboutSettingsActivity" + android:windowSoftInputMode="adjustResize" /> + + <!-- Core Settings --> <activity android:name=".ui.coresettings.CoreSettingsActivity" android:exported="false" @@ -62,40 +79,42 @@ android:name=".ui.coresettings.networkconfig.NetworkConfigActivity" android:exported="false" android:label="@string/settings_networkconfig_title" - android:parentActivityName=".ui.chat.ChatActivity" + android:parentActivityName=".ui.coresettings.CoreSettingsActivity" android:windowSoftInputMode="adjustResize" /> <activity - android:name=".ui.clientsettings.app.AppSettingsActivity" + android:name=".ui.coresettings.identity.IdentitiesActivity" android:exported="false" - android:label="@string/label_settings_client" - android:parentActivityName=".ui.chat.ChatActivity" + android:label="@string/settings_identities_title" + android:parentActivityName=".ui.coresettings.CoreSettingsActivity" android:windowSoftInputMode="adjustResize" /> <activity - android:name=".ui.clientsettings.crash.CrashSettingsActivity" + android:name=".ui.coresettings.identity.IdentityActivity" android:exported="false" - android:label="@string/label_crashes" - android:parentActivityName=".ui.clientsettings.app.AppSettingsActivity" + android:label="@string/settings_identity_title" + android:parentActivityName=".ui.coresettings.identity.IdentitiesActivity" android:windowSoftInputMode="adjustResize" /> + + <!-- Client Setup Flow --> <activity - android:name=".ui.clientsettings.about.AboutSettingsActivity" + android:name=".ui.setup.accounts.selection.AccountSelectionActivity" android:exported="false" - android:label="@string/label_about" - android:parentActivityName=".ui.clientsettings.app.AppSettingsActivity" + android:label="@string/app_name" + android:parentActivityName=".ui.chat.ChatActivity" android:windowSoftInputMode="adjustResize" /> <activity - android:name=".ui.clientsettings.license.LicenseSettingsActivity" + android:name=".ui.setup.accounts.setup.AccountSetupActivity" android:exported="false" - android:label="@string/label_license" - android:parentActivityName=".ui.clientsettings.about.AboutSettingsActivity" + android:label="@string/app_name" + android:parentActivityName=".ui.setup.accounts.selection.AccountSelectionActivity" android:windowSoftInputMode="adjustResize" /> - <activity - android:name=".ui.setup.accounts.selection.AccountSelectionActivity" + android:name=".ui.setup.accounts.edit.AccountEditActivity" android:exported="false" android:label="@string/app_name" - android:parentActivityName=".ui.chat.ChatActivity" + android:parentActivityName=".ui.setup.accounts.selection.AccountSelectionActivity" android:windowSoftInputMode="adjustResize" /> + <!-- Services --> <service android:name=".service.QuasselService" android:description="@string/connection_service_description" diff --git a/app/src/main/java/de/kuschku/quasseldroid/dagger/ActivityModule.kt b/app/src/main/java/de/kuschku/quasseldroid/dagger/ActivityModule.kt index c8324a735f87bff4b5b3f3a6c65041fed1087dea..94cef23ec314cd211966767f4a882aedb9e16bd8 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/dagger/ActivityModule.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/dagger/ActivityModule.kt @@ -18,6 +18,10 @@ import de.kuschku.quasseldroid.ui.clientsettings.license.LicenseSettingsActivity import de.kuschku.quasseldroid.ui.clientsettings.license.LicenseSettingsFragmentProvider import de.kuschku.quasseldroid.ui.coresettings.CoreSettingsActivity import de.kuschku.quasseldroid.ui.coresettings.CoreSettingsFragmentProvider +import de.kuschku.quasseldroid.ui.coresettings.identity.IdentitiesActivity +import de.kuschku.quasseldroid.ui.coresettings.identity.IdentitiesFragmentProvider +import de.kuschku.quasseldroid.ui.coresettings.identity.IdentityActivity +import de.kuschku.quasseldroid.ui.coresettings.identity.IdentityFragmentProvider import de.kuschku.quasseldroid.ui.coresettings.networkconfig.NetworkConfigActivity import de.kuschku.quasseldroid.ui.coresettings.networkconfig.NetworkConfigFragmentProvider import de.kuschku.quasseldroid.ui.setup.accounts.edit.AccountEditActivity @@ -49,6 +53,12 @@ abstract class ActivityModule { @ContributesAndroidInjector(modules = [CoreSettingsFragmentProvider::class]) abstract fun bindCoreSettingsActivity(): CoreSettingsActivity + @ContributesAndroidInjector(modules = [IdentitiesFragmentProvider::class]) + abstract fun bindIdentitiesActivity(): IdentitiesActivity + + @ContributesAndroidInjector(modules = [IdentityFragmentProvider::class]) + abstract fun bindIdentityActivity(): IdentityActivity + @ContributesAndroidInjector(modules = [NetworkConfigFragmentProvider::class]) abstract fun bindNetworkConfigActivity(): NetworkConfigActivity diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/CoreSettingsFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/CoreSettingsFragment.kt index 311ba0a6e363e779a2e2db756c88e8c8d336a520..d522f0dc28b26894eb3267bd7c2743d4888d2b23 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/CoreSettingsFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/CoreSettingsFragment.kt @@ -2,6 +2,7 @@ package de.kuschku.quasseldroid.ui.coresettings import android.content.Intent import android.os.Bundle +import android.support.v7.widget.DividerItemDecoration import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.RecyclerView import android.view.LayoutInflater @@ -11,6 +12,7 @@ import android.widget.TextView import butterknife.BindView import butterknife.ButterKnife import de.kuschku.quasseldroid.R +import de.kuschku.quasseldroid.ui.coresettings.identity.IdentitiesActivity import de.kuschku.quasseldroid.ui.coresettings.networkconfig.NetworkConfigActivity import de.kuschku.quasseldroid.util.helper.visibleIf import de.kuschku.quasseldroid.util.service.ServiceBoundFragment @@ -21,17 +23,24 @@ class CoreSettingsFragment : ServiceBoundFragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - val view = inflater.inflate(R.layout.fragment_coresettings, container, false) + val view = inflater.inflate(R.layout.settings_list, container, false) ButterKnife.bind(this, view) - list.layoutManager = LinearLayoutManager(context) - list.adapter = CoreSettingsAdapter(listOf( + val adapter = CoreSettingsAdapter(listOf( + CoreSetting( + getString(R.string.settings_identities_title), + getString(R.string.settings_identities_description), + Intent(requireContext(), IdentitiesActivity::class.java) + ), CoreSetting( getString(R.string.settings_networkconfig_title), getString(R.string.settings_networkconfig_description), Intent(requireContext(), NetworkConfigActivity::class.java) ) )) + list.adapter = adapter + list.layoutManager = LinearLayoutManager(context) + list.addItemDecoration(DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL)) return view } @@ -47,7 +56,7 @@ class CoreSettingsFragment : ServiceBoundFragment() { override fun getItemCount() = data.size override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = CoreSettingsViewHolder( - LayoutInflater.from(parent.context).inflate(R.layout.widget_coresetting, parent, false) + LayoutInflater.from(parent.context).inflate(R.layout.settings_item, parent, false) ) override fun onBindViewHolder(holder: CoreSettingsViewHolder, position: Int) { diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentitiesActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentitiesActivity.kt new file mode 100644 index 0000000000000000000000000000000000000000..ca0cc09af75749d11fdce48e09efa3d64a301f2e --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentitiesActivity.kt @@ -0,0 +1,5 @@ +package de.kuschku.quasseldroid.ui.coresettings.identity + +import de.kuschku.quasseldroid.util.ui.SettingsActivity + +class IdentitiesActivity : SettingsActivity(IdentitiesFragment()) \ No newline at end of file diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentitiesFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentitiesFragment.kt new file mode 100644 index 0000000000000000000000000000000000000000..a8ad3a124a37577dfe7029385f18454a4ae4e715 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentitiesFragment.kt @@ -0,0 +1,103 @@ +package de.kuschku.quasseldroid.ui.coresettings.identity + +import android.arch.lifecycle.Observer +import android.content.Intent +import android.os.Bundle +import android.support.v7.recyclerview.extensions.ListAdapter +import android.support.v7.util.DiffUtil +import android.support.v7.widget.DividerItemDecoration +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 android.widget.TextView +import butterknife.BindView +import butterknife.ButterKnife +import de.kuschku.libquassel.protocol.IdentityId +import de.kuschku.libquassel.quassel.syncables.Identity +import de.kuschku.quasseldroid.R +import de.kuschku.quasseldroid.util.helper.combineLatest +import de.kuschku.quasseldroid.util.helper.toLiveData +import de.kuschku.quasseldroid.util.service.ServiceBoundFragment + +class IdentitiesFragment : ServiceBoundFragment() { + @BindView(R.id.list) + lateinit var list: RecyclerView + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + val view = inflater.inflate(R.layout.settings_list, container, false) + ButterKnife.bind(this, view) + + val adapter = IdentityAdapter { + val intent = Intent(requireContext(), IdentityActivity::class.java) + intent.putExtra("identity", it) + startActivity(intent) + } + + list.adapter = adapter + list.layoutManager = LinearLayoutManager(context) + list.addItemDecoration(DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL)) + + viewModel.identities.switchMap { + combineLatest(it.values.map(Identity::liveUpdates)).map { + it.map { + IdentityItem( + it.id(), + it.identityName() + ) + } + } + }.toLiveData().observe(this, Observer { + adapter.submitList(it.orEmpty()) + }) + + return view + } + + data class IdentityItem( + val id: IdentityId, + val name: String + ) + + class IdentityAdapter(private val clickListener: (IdentityId) -> Unit) : + ListAdapter<IdentityItem, IdentityAdapter.IdentityViewHolder>( + object : DiffUtil.ItemCallback<IdentityItem>() { + override fun areItemsTheSame(oldItem: IdentityItem, newItem: IdentityItem) = + oldItem.id == newItem.id + + override fun areContentsTheSame(oldItem: IdentityItem, newItem: IdentityItem) = + oldItem == newItem + } + ) { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = IdentityViewHolder( + LayoutInflater.from(parent.context).inflate(R.layout.settings_item, parent, false), + clickListener + ) + + override fun onBindViewHolder(holder: IdentityViewHolder, position: Int) { + holder.bind(getItem(position)) + } + + class IdentityViewHolder(itemView: View, clickListener: (IdentityId) -> Unit) : + RecyclerView.ViewHolder(itemView) { + @BindView(R.id.title) + lateinit var title: TextView + + var id: IdentityId? = null + + init { + ButterKnife.bind(this, itemView) + itemView.setOnClickListener { + id?.let(clickListener::invoke) + } + } + + fun bind(item: IdentityItem) { + this.id = item.id + this.title.text = item.name + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentitiesFragmentProvider.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentitiesFragmentProvider.kt new file mode 100644 index 0000000000000000000000000000000000000000..54fd243aea1ca4cc04749e04fdadd18812aaed43 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentitiesFragmentProvider.kt @@ -0,0 +1,10 @@ +package de.kuschku.quasseldroid.ui.coresettings.identity + +import dagger.Module +import dagger.android.ContributesAndroidInjector + +@Module +abstract class IdentitiesFragmentProvider { + @ContributesAndroidInjector + abstract fun bindIdentitiesFragment(): IdentitiesFragment +} diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityActivity.kt new file mode 100644 index 0000000000000000000000000000000000000000..59cd117fd27d7a258fa3bb004a131c097552398e --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityActivity.kt @@ -0,0 +1,5 @@ +package de.kuschku.quasseldroid.ui.coresettings.identity + +import de.kuschku.quasseldroid.util.ui.SettingsActivity + +class IdentityActivity : SettingsActivity(IdentityFragment()) \ No newline at end of file diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityFragment.kt new file mode 100644 index 0000000000000000000000000000000000000000..52479c3df07fb0d38c92a6d10e6de05451d5e9bf --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityFragment.kt @@ -0,0 +1,180 @@ +package de.kuschku.quasseldroid.ui.coresettings.identity + +import android.arch.lifecycle.Observer +import android.os.Bundle +import android.support.v7.widget.LinearLayoutManager +import android.support.v7.widget.RecyclerView +import android.support.v7.widget.RecyclerView.ViewHolder +import android.support.v7.widget.SwitchCompat +import android.support.v7.widget.helper.ItemTouchHelper +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 com.afollestad.materialdialogs.MaterialDialog +import de.kuschku.libquassel.quassel.syncables.Identity +import de.kuschku.libquassel.util.Optional +import de.kuschku.quasseldroid.R +import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment +import de.kuschku.quasseldroid.util.helper.setDependent +import de.kuschku.quasseldroid.util.helper.toLiveData + + +class IdentityFragment : SettingsFragment() { + private var identity: Pair<Identity, Identity>? = null + + @BindView(R.id.identity_name) + lateinit var identityName: TextView + + @BindView(R.id.real_name) + lateinit var realName: TextView + + @BindView(R.id.ident) + lateinit var ident: TextView + + @BindView(R.id.nicks) + lateinit var nicks: RecyclerView + + @BindView(R.id.new_nick) + lateinit var newNick: Button + + @BindView(R.id.kick_reason) + lateinit var kickReason: TextView + + @BindView(R.id.part_reason) + lateinit var partReason: TextView + + @BindView(R.id.quit_reason) + lateinit var quitReason: TextView + + @BindView(R.id.away_reason) + lateinit var awayReason: TextView + + @BindView(R.id.detach_away) + lateinit var detachAway: SwitchCompat + + @BindView(R.id.detach_away_group) + lateinit var detachAwayGroup: ViewGroup + + @BindView(R.id.detach_away_reason) + lateinit var detachAwayReason: TextView + + private lateinit var adapter: IdentityNicksAdapter + private lateinit var helper: ItemTouchHelper + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + val view = inflater.inflate(R.layout.settings_identity, container, false) + ButterKnife.bind(this, view) + + val identityId = arguments?.getInt("identity", -1) ?: -1 + + viewModel.identities.map { + Optional.ofNullable(it[identityId]) + }.filter(Optional<Identity>::isPresent) + .map(Optional<Identity>::get) + .firstElement() + .toLiveData().observe(this, Observer { + if (it != null) { + this.identity = Pair(it, it.copy()) + this.identity?.let { (_, data) -> + identityName.text = data.identityName() + realName.text = data.realName() + ident.text = data.ident() + kickReason.text = data.kickReason() + partReason.text = data.partReason() + quitReason.text = data.quitReason() + awayReason.text = data.awayReason() + detachAway.isChecked = data.detachAwayEnabled() + detachAwayReason.text = data.detachAwayReason() + adapter.nicks = data.nicks() + } + } + }) + + adapter = IdentityNicksAdapter(::nickClick, ::startDrag) + nicks.layoutManager = LinearLayoutManager(requireContext()) + nicks.adapter = adapter + val callback = DragSortItemTouchHelperCallback(adapter) + helper = ItemTouchHelper(callback) + helper.attachToRecyclerView(nicks) + + newNick.setOnClickListener { + MaterialDialog.Builder(requireContext()) + .input(null, null, false) { _, _ -> } + .title(R.string.label_new_nick) + .negativeText(R.string.label_cancel) + .positiveText(R.string.label_save) + .onPositive { dialog, _ -> + dialog.inputEditText?.text?.toString()?.let { + if (it.isNotBlank()) { + adapter.addNick(it) + } + } + }.build().show() + } + + detachAway.setDependent(detachAwayGroup) + + return view + } + + fun startDrag(holder: IdentityNicksAdapter.IdentityNickViewHolder) = helper.startDrag(holder) + + fun nickClick(index: Int, nick: String) { + MaterialDialog.Builder(requireContext()) + .input(null, nick, false) { _, _ -> } + .title(R.string.label_edit_nick) + .negativeText(R.string.label_cancel) + .positiveText(R.string.label_save) + .onPositive { dialog, _ -> + dialog.inputEditText?.text?.toString()?.let { + if (it.isNotBlank()) { + adapter.replaceNick(index, it) + } + } + }.build().show() + } + + override fun onSave() = identity?.let { (it, data) -> + data.setIdentityName(identityName.text.toString()) + data.setRealName(realName.text.toString()) + data.setIdent(ident.text.toString()) + data.setKickReason(kickReason.text.toString()) + data.setPartReason(partReason.text.toString()) + data.setQuitReason(quitReason.text.toString()) + data.setAwayReason(awayReason.text.toString()) + data.setDetachAwayEnabled(detachAway.isChecked) + data.setDetachAwayReason(detachAwayReason.text.toString()) + data.setNicks(adapter.nicks) + + it.requestUpdate(data.toVariantMap()) + true + } ?: false + + class DragSortItemTouchHelperCallback(private val adapter: IdentityNicksAdapter) : + ItemTouchHelper.Callback() { + override fun isLongPressDragEnabled() = true + + override fun isItemViewSwipeEnabled() = true + + override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: ViewHolder): Int { + val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN + val swipeFlags = ItemTouchHelper.START or ItemTouchHelper.END + return ItemTouchHelper.Callback.makeMovementFlags(dragFlags, swipeFlags) + } + + override fun onMove(recyclerView: RecyclerView, viewHolder: ViewHolder, + target: ViewHolder): Boolean { + adapter.moveNick(viewHolder.adapterPosition, target.adapterPosition) + return true + } + + override fun onSwiped(viewHolder: ViewHolder, direction: Int) { + adapter.removeNick(viewHolder.adapterPosition) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityFragmentProvider.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityFragmentProvider.kt new file mode 100644 index 0000000000000000000000000000000000000000..1c156fbe756906402a3d9d4630392f20b73bc078 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityFragmentProvider.kt @@ -0,0 +1,10 @@ +package de.kuschku.quasseldroid.ui.coresettings.identity + +import dagger.Module +import dagger.android.ContributesAndroidInjector + +@Module +abstract class IdentityFragmentProvider { + @ContributesAndroidInjector + abstract fun bindIdentityFragment(): IdentityFragment +} diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityNicksAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityNicksAdapter.kt new file mode 100644 index 0000000000000000000000000000000000000000..c95903662c1f861a896e74ae45178a4466fad350 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityNicksAdapter.kt @@ -0,0 +1,98 @@ +package de.kuschku.quasseldroid.ui.coresettings.identity + +import android.support.v7.widget.RecyclerView +import android.view.LayoutInflater +import android.view.MotionEvent +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import butterknife.BindView +import butterknife.ButterKnife +import de.kuschku.quasseldroid.R +import java.util.* + +class IdentityNicksAdapter( + private val clickListener: (Int, String) -> Unit, + private val dragListener: (IdentityNickViewHolder) -> Unit +) : + RecyclerView.Adapter<IdentityNicksAdapter.IdentityNickViewHolder>() { + private val data = mutableListOf<String>() + var nicks: List<String> + get() = data + set(value) { + val length = data.size + data.clear() + notifyItemRangeRemoved(0, length) + data.addAll(value) + notifyItemRangeInserted(0, nicks.size) + } + + fun addNick(nick: String) { + val index = data.size + data.add(nick) + notifyItemInserted(index) + } + + fun replaceNick(index: Int, nick: String) { + data[index] = nick + notifyItemChanged(index) + } + + fun removeNick(index: Int) { + data.removeAt(index) + notifyItemRemoved(index) + } + + fun moveNick(from: Int, to: Int) { + Collections.swap(data, from, to) + notifyItemMoved(from, to) + } + + override fun getItemCount() = data.size + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = IdentityNickViewHolder( + LayoutInflater.from(parent.context) + .inflate(R.layout.settings_identity_nick, parent, false), + clickListener, + dragListener + ) + + override fun onBindViewHolder(holder: IdentityNickViewHolder, position: Int) { + holder.bind(data[position]) + } + + class IdentityNickViewHolder( + itemView: View, + private val clickListener: (Int, String) -> Unit, + dragListener: (IdentityNickViewHolder) -> Unit + ) : + RecyclerView.ViewHolder(itemView) { + @BindView(R.id.nick) + lateinit var nick: TextView + + @BindView(R.id.handle) + lateinit var handle: View + + private var item: String? = null + + init { + ButterKnife.bind(this, itemView) + itemView.setOnClickListener { + item?.let { + clickListener(adapterPosition, it) + } + } + handle.setOnTouchListener { _, event -> + if (event.action == MotionEvent.ACTION_DOWN) { + dragListener.invoke(this) + } + false + } + } + + fun bind(item: String) { + this.item = item + nick.text = item + } + } +} \ No newline at end of file diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkconfig/NetworkConfigFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkconfig/NetworkConfigFragment.kt index 098c19836bea60d85c8ccd78e66c9be6359bd741..8ef9660153277142d46fef66d8a83c9b5ca3d5d9 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkconfig/NetworkConfigFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/networkconfig/NetworkConfigFragment.kt @@ -10,14 +10,14 @@ import android.widget.EditText import butterknife.BindView import butterknife.ButterKnife import de.kuschku.libquassel.quassel.syncables.NetworkConfig -import de.kuschku.libquassel.session.ISession +import de.kuschku.libquassel.util.Optional import de.kuschku.quasseldroid.R import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment import de.kuschku.quasseldroid.util.helper.setDependent import de.kuschku.quasseldroid.util.helper.toLiveData class NetworkConfigFragment : SettingsFragment() { - private var networkConfig: NetworkConfig? = null + private var networkConfig: Pair<NetworkConfig, NetworkConfig>? = null @BindView(R.id.ping_timeout_enabled) lateinit var pingTimeoutEnabled: SwitchCompat @@ -51,27 +51,30 @@ class NetworkConfigFragment : SettingsFragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - val view = inflater.inflate(R.layout.fragment_networksettings, container, false) + val view = inflater.inflate(R.layout.settings_networkconfig, container, false) ButterKnife.bind(this, view) - setHasOptionsMenu(true) - - viewModel.session.map { it.map(ISession::networkConfig) }.toLiveData().observe(this, Observer { - it?.orNull()?.let { - this.networkConfig = it - - pingTimeoutEnabled.isChecked = it.pingTimeoutEnabled() - pingInterval.setText(it.pingInterval().toString()) - maxPingCount.setText(it.maxPingCount().toString()) - - autoWhoEnabled.isChecked = it.autoWhoEnabled() - autoWhoInterval.setText(it.autoWhoInterval().toString()) - autoWhoNickLimit.setText(it.autoWhoNickLimit().toString()) - autoWhoDelay.setText(it.autoWhoDelay().toString()) - - standardCtcp.isChecked = it.standardCtcp() - } - }) + viewModel.networkConfig + .filter(Optional<NetworkConfig?>::isPresent) + .map(Optional<NetworkConfig?>::get) + .firstElement() + .toLiveData().observe(this, Observer { + if (it != null) { + this.networkConfig = Pair(it, it.copy()) + this.networkConfig?.let { (_, data) -> + pingTimeoutEnabled.isChecked = data.pingTimeoutEnabled() + pingInterval.setText(data.pingInterval().toString()) + maxPingCount.setText(data.maxPingCount().toString()) + + autoWhoEnabled.isChecked = data.autoWhoEnabled() + autoWhoInterval.setText(data.autoWhoInterval().toString()) + autoWhoNickLimit.setText(data.autoWhoNickLimit().toString()) + autoWhoDelay.setText(data.autoWhoDelay().toString()) + + standardCtcp.isChecked = data.standardCtcp() + } + } + }) pingTimeoutEnabled.setDependent(pingTimeoutGroup) autoWhoEnabled.setDependent(autoWhoGroup) @@ -80,22 +83,18 @@ class NetworkConfigFragment : SettingsFragment() { } - override fun onSave() = networkConfig?.let { - val config = it.copy() - - config.setPingTimeoutEnabled(pingTimeoutEnabled.isChecked) - pingInterval.text.toString().toIntOrNull()?.let(config::setPingInterval) - maxPingCount.text.toString().toIntOrNull()?.let(config::setMaxPingCount) - - config.setAutoWhoEnabled(autoWhoEnabled.isChecked) - autoWhoInterval.text.toString().toIntOrNull()?.let(config::setAutoWhoInterval) - autoWhoNickLimit.text.toString().toIntOrNull()?.let(config::setAutoWhoNickLimit) - autoWhoDelay.text.toString().toIntOrNull()?.let(config::setAutoWhoDelay) - config.setStandardCtcp(standardCtcp.isChecked) + override fun onSave() = networkConfig?.let { (it, data) -> + data.setPingTimeoutEnabled(pingTimeoutEnabled.isChecked) + pingInterval.text.toString().toIntOrNull()?.let(data::setPingInterval) + maxPingCount.text.toString().toIntOrNull()?.let(data::setMaxPingCount) - val properties = config.toVariantMap() - it.requestUpdate(properties) + data.setAutoWhoEnabled(autoWhoEnabled.isChecked) + autoWhoInterval.text.toString().toIntOrNull()?.let(data::setAutoWhoInterval) + autoWhoNickLimit.text.toString().toIntOrNull()?.let(data::setAutoWhoNickLimit) + autoWhoDelay.text.toString().toIntOrNull()?.let(data::setAutoWhoDelay) + data.setStandardCtcp(standardCtcp.isChecked) + it.requestUpdate(data.toVariantMap()) true } ?: false } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_account_card.xml b/app/src/main/res/drawable/ic_account_card.xml new file mode 100644 index 0000000000000000000000000000000000000000..636532554b94ad16b6719103cd67b5d81579b603 --- /dev/null +++ b/app/src/main/res/drawable/ic_account_card.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportHeight="24" + android:viewportWidth="24"> + <path + android:fillColor="#000" + android:pathData="M2,3H22C23.05,3 24,3.95 24,5V19C24,20.05 23.05,21 22,21H2C0.95,21 0,20.05 0,19V5C0,3.95 0.95,3 2,3M14,6V7H22V6H14M14,8V9H21.5L22,9V8H14M14,10V11H21V10H14M8,13.91C6,13.91 2,15 2,17V18H14V17C14,15 10,13.91 8,13.91M8,6A3,3 0 0,0 5,9A3,3 0 0,0 8,12A3,3 0 0,0 11,9A3,3 0 0,0 8,6Z" /> +</vector> \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_tag_text.xml b/app/src/main/res/drawable/ic_tag_text.xml new file mode 100644 index 0000000000000000000000000000000000000000..43d0cc112e3083a30bbd43e8aa78befdcc236fa7 --- /dev/null +++ b/app/src/main/res/drawable/ic_tag_text.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportHeight="24" + android:viewportWidth="24"> + <path + android:fillColor="#000" + android:pathData="M5.5,7A1.5,1.5 0 0,0 7,5.5A1.5,1.5 0 0,0 5.5,4A1.5,1.5 0 0,0 4,5.5A1.5,1.5 0 0,0 5.5,7M21.41,11.58C21.77,11.94 22,12.44 22,13C22,13.55 21.78,14.05 21.41,14.41L14.41,21.41C14.05,21.77 13.55,22 13,22C12.45,22 11.95,21.77 11.58,21.41L2.59,12.41C2.22,12.05 2,11.55 2,11V4C2,2.89 2.89,2 4,2H11C11.55,2 12.05,2.22 12.41,2.58L21.41,11.58M13,20L20,13L11.5,4.5L4.5,11.5L13,20M10.09,8.91L11.5,7.5L17,13L15.59,14.41L10.09,8.91M7.59,11.41L9,10L13,14L11.59,15.41L7.59,11.41Z" /> +</vector> \ No newline at end of file diff --git a/app/src/main/res/layout/settings_identity.xml b/app/src/main/res/layout/settings_identity.xml new file mode 100644 index 0000000000000000000000000000000000000000..846ecfdbe802cc1fb125d44340f34aee7e862459 --- /dev/null +++ b/app/src/main/res/layout/settings_identity.xml @@ -0,0 +1,203 @@ +<?xml version="1.0" encoding="utf-8"?> +<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <LinearLayout style="@style/Widget.CoreSettings.Wrapper"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="48dp"> + + <android.support.v7.widget.AppCompatImageView + style="@style/Widget.CoreSettings.PrimaryItemIcon" + app:srcCompat="@drawable/ic_account_card" /> + + <TextView + style="@style/Widget.CoreSettings.PrimaryItemSwitch" + android:text="@string/settings_identity_names" /> + </LinearLayout> + + <LinearLayout + style="@style/Widget.CoreSettings.DependentGroup" + android:visibility="visible"> + + <android.support.design.widget.TextInputLayout + style="@style/Widget.CoreSettings.EditTextLayout" + android:hint="@string/settings_identity_identity_name"> + + <android.support.design.widget.TextInputEditText + android:id="@+id/identity_name" + style="@style/Widget.CoreSettings.EditText" + tools:text="Standardidentität" /> + </android.support.design.widget.TextInputLayout> + + <android.support.design.widget.TextInputLayout + style="@style/Widget.CoreSettings.EditTextLayout" + android:hint="@string/settings_identity_real_name"> + + <android.support.design.widget.TextInputEditText + android:id="@+id/real_name" + style="@style/Widget.CoreSettings.EditText" + tools:text="Janne Koschinski" /> + </android.support.design.widget.TextInputLayout> + + <android.support.design.widget.TextInputLayout + style="@style/Widget.CoreSettings.EditTextLayout" + android:hint="@string/settings_identity_ident"> + + <android.support.design.widget.TextInputEditText + android:id="@+id/ident" + style="@style/Widget.CoreSettings.EditText" + tools:text="justJanne" /> + </android.support.design.widget.TextInputLayout> + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="48dp"> + + <Space style="@style/Widget.CoreSettings.PrimaryItemIcon" /> + + <TextView + style="@style/Widget.CoreSettings.PrimaryItemSwitch" + android:text="@string/settings_identity_nicks" /> + </LinearLayout> + + <LinearLayout + style="@style/Widget.CoreSettings.DependentGroup" + android:orientation="vertical" + android:visibility="visible"> + + <android.support.v7.widget.RecyclerView + android:id="@+id/nicks" + android:layout_width="match_parent" + android:layout_height="wrap_content" + tools:itemCount="4" + tools:listitem="@layout/settings_identity_nick" /> + + <LinearLayout + style="@style/Widget.CoreSettings.EditTextLayout" + android:orientation="horizontal"> + + <Button + android:id="@+id/new_nick" + style="@style/Widget.Button.Borderless.Colored" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/label_new_nick" /> + </LinearLayout> + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="48dp"> + + <android.support.v7.widget.AppCompatImageView + style="@style/Widget.CoreSettings.PrimaryItemIcon" + app:srcCompat="@drawable/ic_message_bulleted" /> + + <TextView + style="@style/Widget.CoreSettings.PrimaryItemSwitch" + android:text="@string/settings_identity_messages" /> + </LinearLayout> + + <LinearLayout + style="@style/Widget.CoreSettings.DependentGroup" + android:visibility="visible"> + + <android.support.design.widget.TextInputLayout + style="@style/Widget.CoreSettings.EditTextLayout" + android:hint="@string/settings_identity_kick_reason"> + + <android.support.design.widget.TextInputEditText + android:id="@+id/kick_reason" + style="@style/Widget.CoreSettings.EditText" + tools:text="" /> + </android.support.design.widget.TextInputLayout> + + <android.support.design.widget.TextInputLayout + style="@style/Widget.CoreSettings.EditTextLayout" + android:hint="@string/settings_identity_part_reason"> + + <android.support.design.widget.TextInputEditText + android:id="@+id/part_reason" + style="@style/Widget.CoreSettings.EditText" + tools:text="So if you care to find me, look to the western sky. As someone told me lately, everyone deserves a chance to fly." /> + </android.support.design.widget.TextInputLayout> + + <android.support.design.widget.TextInputLayout + style="@style/Widget.CoreSettings.EditTextLayout" + android:hint="@string/settings_identity_quit_reason"> + + <android.support.design.widget.TextInputEditText + android:id="@+id/quit_reason" + style="@style/Widget.CoreSettings.EditText" + tools:text="So if you care to find me, look to the western sky. As someone told me lately, everyone deserves a chance to fly." /> + </android.support.design.widget.TextInputLayout> + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="48dp"> + + <android.support.v7.widget.AppCompatImageView + style="@style/Widget.CoreSettings.PrimaryItemIcon" + app:srcCompat="@drawable/ic_history" /> + + <TextView + style="@style/Widget.CoreSettings.PrimaryItemSwitch" + android:text="@string/settings_identity_away" /> + </LinearLayout> + + <LinearLayout + style="@style/Widget.CoreSettings.DependentGroup" + android:visibility="visible"> + + <android.support.design.widget.TextInputLayout + style="@style/Widget.CoreSettings.EditTextLayout" + android:hint="@string/settings_identity_away_reason"> + + <android.support.design.widget.TextInputEditText + android:id="@+id/away_reason" + style="@style/Widget.CoreSettings.EditText" + tools:text="Gone Fishing." /> + </android.support.design.widget.TextInputLayout> + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="48dp"> + + <Space style="@style/Widget.CoreSettings.PrimaryItemIcon" /> + + <android.support.v7.widget.SwitchCompat + android:id="@+id/detach_away" + style="@style/Widget.CoreSettings.PrimaryItemSwitch" + android:text="@string/settings_identity_detach_away" /> + </LinearLayout> + + <LinearLayout + android:id="@+id/detach_away_group" + style="@style/Widget.CoreSettings.DependentGroup" + tools:visibility="visible"> + + <android.support.design.widget.TextInputLayout + style="@style/Widget.CoreSettings.EditTextLayout" + android:hint="@string/settings_identity_detach_away_reason"> + + <android.support.design.widget.TextInputEditText + android:id="@+id/detach_away_reason" + style="@style/Widget.CoreSettings.EditText" + tools:text="Gone Fishing." /> + </android.support.design.widget.TextInputLayout> + </LinearLayout> + </LinearLayout> +</android.support.v4.widget.NestedScrollView> \ No newline at end of file diff --git a/app/src/main/res/layout/settings_identity_nick.xml b/app/src/main/res/layout/settings_identity_nick.xml new file mode 100644 index 0000000000000000000000000000000000000000..ab343f9161d5ee3aa83172c0ac92d7063da0cc59 --- /dev/null +++ b/app/src/main/res/layout/settings_identity_nick.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="2dp" + app:cardElevation="2dp"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="?android:attr/listPreferredItemHeightSmall" + android:orientation="horizontal"> + + <TextView + android:id="@+id/nick" + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_weight="1" + android:paddingLeft="?listPreferredItemPaddingLeft" + android:paddingStart="?listPreferredItemPaddingLeft" + android:textAppearance="?android:attr/textAppearanceListItemSmall" + tools:text="@sample/messages.json/data/sender" /> + + <android.support.v7.widget.AppCompatImageView + android:id="@+id/handle" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_gravity="center_vertical" + android:paddingEnd="?listPreferredItemPaddingRight" + android:paddingLeft="32dp" + android:paddingRight="?listPreferredItemPaddingRight" + android:paddingStart="32dp" + app:srcCompat="@drawable/ic_reorder" + app:tint="?colorTextSecondary" /> + </LinearLayout> +</android.support.v7.widget.CardView> \ No newline at end of file diff --git a/app/src/main/res/layout/widget_coresetting.xml b/app/src/main/res/layout/settings_item.xml similarity index 97% rename from app/src/main/res/layout/widget_coresetting.xml rename to app/src/main/res/layout/settings_item.xml index 6d36188e6a5dfef38c83b63cbe95be566ed6cff0..3a1a9a6d88d54eb9d701197b70441276e87306d0 100644 --- a/app/src/main/res/layout/widget_coresetting.xml +++ b/app/src/main/res/layout/settings_item.xml @@ -35,6 +35,6 @@ android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="?colorTextPrimary" - tools:visibility="gone" /> + android:visibility="gone" /> </LinearLayout> </LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_coresettings.xml b/app/src/main/res/layout/settings_list.xml similarity index 60% rename from app/src/main/res/layout/fragment_coresettings.xml rename to app/src/main/res/layout/settings_list.xml index d84e8ff1d1a6320ca5470f1df23866b6a0e5792b..627c357e7f0098804f61e8971922a0f0f293790e 100644 --- a/app/src/main/res/layout/fragment_coresettings.xml +++ b/app/src/main/res/layout/settings_list.xml @@ -1,5 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:id="@+id/list" android:layout_width="match_parent" - android:layout_height="match_parent" /> \ No newline at end of file + android:layout_height="match_parent" + tools:listitem="@layout/settings_item" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_networksettings.xml b/app/src/main/res/layout/settings_networkconfig.xml similarity index 100% rename from app/src/main/res/layout/fragment_networksettings.xml rename to app/src/main/res/layout/settings_networkconfig.xml diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index ddffffba4a51bf8743a7496cc0f006a18482b5af..7454727507797d7ebd12625fa580487fa31ef616 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -23,6 +23,7 @@ <string name="label_delete_all">Alle Löschen</string> <string name="label_details">Details</string> <string name="label_disconnect">Verbindung trennen</string> + <string name="label_edit_nick">Spitznamen bearbeiten</string> <string name="label_filter_messages">Nachrichten filtern</string> <string name="label_github">GitHub</string> <string name="label_hide_perm">Permanent ausblenden</string> @@ -32,6 +33,7 @@ <string name="label_libraries">Bibliotheken</string> <string name="label_license">Lizenz</string> <string name="label_new_account">Account hinzufügen</string> + <string name="label_new_nick">Spitzname hinzufügen</string> <string name="label_no">Nein</string> <string name="label_reset">Zurücksetzen</string> <string name="label_open">Öffnen</string> diff --git a/app/src/main/res/values-de/strings_settings.xml b/app/src/main/res/values-de/strings_settings.xml index 574f8689bdbcee38e567d2a0a7cb6ab5d8109c89..9323ec34a66c1e040e22a543bf44dfceff376deb 100644 --- a/app/src/main/res/values-de/strings_settings.xml +++ b/app/src/main/res/values-de/strings_settings.xml @@ -20,4 +20,23 @@ <string name="settings_networkconfig_auto_who_delay_unit">Sekunden</string> <string name="settings_networkconfig_standard_ctcp">Standardkonformes CTCP-Verhalten aktivieren</string> + + + <string name="settings_identities_title">Identitäten</string> + <string name="settings_identities_description" /> + + <string name="settings_identity_title">Identität</string> + <string name="settings_identity_names">Namen</string> + <string name="settings_identity_identity_name">Identitätsname</string> + <string name="settings_identity_real_name">Realname</string> + <string name="settings_identity_ident">Ident</string> + <string name="settings_identity_nicks">Spitznamen</string> + <string name="settings_identity_messages">Meldungen</string> + <string name="settings_identity_kick_reason">Rauswurfgrund</string> + <string name="settings_identity_part_reason">Part-Grund</string> + <string name="settings_identity_quit_reason">Beendigungsgrund</string> + <string name="settings_identity_away">Abwesenheitsmeldungen</string> + <string name="settings_identity_away_reason">Abwesenheitsgrund</string> + <string name="settings_identity_detach_away">Abwesend wenn nicht verbunden</string> + <string name="settings_identity_detach_away_reason">Abwesenheitsgrund</string> </resources> \ No newline at end of file diff --git a/app/src/main/res/values-v17/styles_widgets.xml b/app/src/main/res/values-v17/styles_widgets.xml index 5109234c2ce2b548fcb6e36d033f6609d7ebdd21..aa6100a835408b528e10c6fe3be2481a9d6ba83b 100644 --- a/app/src/main/res/values-v17/styles_widgets.xml +++ b/app/src/main/res/values-v17/styles_widgets.xml @@ -12,8 +12,8 @@ </style> <style name="Widget.CoreSettings.PrimaryItemIcon" parent=""> - <item name="android:layout_width">wrap_content</item> - <item name="android:layout_height">wrap_content</item> + <item name="android:layout_width">24dp</item> + <item name="android:layout_height">24dp</item> <item name="android:layout_gravity">center_vertical</item> <item name="android:layout_marginRight">32dp</item> <item name="android:layout_marginEnd">32dp</item> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e1f5126497a30fc7761a5ff1f4ced5b5898f3f01..0485740d40a40c4efd0b450d5ebf163c83b51eb8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -23,6 +23,7 @@ <string name="label_delete_all">Delete All</string> <string name="label_details">Details</string> <string name="label_disconnect">Disconnect</string> + <string name="label_edit_nick">Edit nickname</string> <string name="label_filter_messages">Filter Messages</string> <string name="label_github">GitHub</string> <string name="label_hide_perm">Hide Permanently</string> @@ -32,6 +33,7 @@ <string name="label_libraries">Libraries</string> <string name="label_license">License</string> <string name="label_new_account">New Account</string> + <string name="label_new_nick">New Nick</string> <string name="label_no">No</string> <string name="label_reset">Reset</string> <string name="label_open">Open</string> diff --git a/app/src/main/res/values/strings_settings.xml b/app/src/main/res/values/strings_settings.xml index c6579633b2f9c7f6cdcd3182ab516424dcfcbb20..ce48dfef43d3fa9e71055030b648936d227d7567 100644 --- a/app/src/main/res/values/strings_settings.xml +++ b/app/src/main/res/values/strings_settings.xml @@ -4,13 +4,10 @@ <string name="settings_networkconfig_description" /> <string name="settings_networkconfig_ping_timeout">Ping Timeout Detection</string> - <string name="settings_networkconfig_ping_interval">Ping Interval</string> <string name="settings_networkconfig_ping_interval_unit">seconds</string> - <string name="settings_networkconfig_max_ping_count">Disconnect after</string> <string name="settings_networkconfig_max_ping_count_unit">missed pings</string> - <string name="settings_networkconfig_auto_who">Automatic User Info Lookup</string> <string name="settings_networkconfig_auto_who_interval">Update interval</string> <string name="settings_networkconfig_auto_who_interval_unit">seconds</string> @@ -20,4 +17,23 @@ <string name="settings_networkconfig_auto_who_delay_unit">seconds</string> <string name="settings_networkconfig_standard_ctcp">Standard-Compliant CTCP behavior</string> + + + <string name="settings_identities_title">Identities</string> + <string name="settings_identities_description" /> + + <string name="settings_identity_title">Identity</string> + <string name="settings_identity_names">Names</string> + <string name="settings_identity_identity_name">Identity name</string> + <string name="settings_identity_real_name">Real Name</string> + <string name="settings_identity_ident">Ident</string> + <string name="settings_identity_nicks">Nicknames</string> + <string name="settings_identity_messages">Messages</string> + <string name="settings_identity_kick_reason">Kick Reason</string> + <string name="settings_identity_part_reason">Part Reason</string> + <string name="settings_identity_quit_reason">Quit Reason</string> + <string name="settings_identity_away">Away Messages</string> + <string name="settings_identity_away_reason">Away Reason</string> + <string name="settings_identity_detach_away">Away on Detach</string> + <string name="settings_identity_detach_away_reason">Away on Detach Reason</string> </resources> \ No newline at end of file diff --git a/app/src/main/res/values/styles_widgets.xml b/app/src/main/res/values/styles_widgets.xml index e4ec1d3473e1d21a0667e3a7a203f02f4dcd3c4c..425af41b2b85ed12847756c626b46bb09036ea95 100644 --- a/app/src/main/res/values/styles_widgets.xml +++ b/app/src/main/res/values/styles_widgets.xml @@ -90,12 +90,14 @@ <item name="android:layout_width">match_parent</item> <item name="android:layout_height">match_parent</item> <item name="android:layout_gravity">center_vertical</item> + <item name="android:gravity">center_vertical</item> + <item name="android:textAppearance">?android:textAppearanceMedium</item> <item name="android:textColor">?colorTextPrimary</item> </style> <style name="Widget.CoreSettings.PrimaryItemIcon" parent=""> - <item name="android:layout_width">wrap_content</item> - <item name="android:layout_height">wrap_content</item> + <item name="android:layout_width">24dp</item> + <item name="android:layout_height">24dp</item> <item name="android:layout_gravity">center_vertical</item> <item name="android:layout_marginRight">32dp</item> <item name="tint">?colorTextSecondary</item> diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Identity.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Identity.kt index 953ee32dc5f12760372dbf910c8a7fde7b91c6f9..21d0ff4639127ba271cd41715597d14cfaaab7f1 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Identity.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Identity.kt @@ -3,6 +3,8 @@ package de.kuschku.libquassel.quassel.syncables import de.kuschku.libquassel.protocol.* import de.kuschku.libquassel.quassel.syncables.interfaces.IIdentity import de.kuschku.libquassel.session.SignalProxy +import io.reactivex.Observable +import io.reactivex.subjects.BehaviorSubject class Identity constructor( proxy: SignalProxy @@ -64,6 +66,8 @@ class Identity constructor( setQuitReason(properties["quitReason"].valueOr(this::quitReason)) } + fun liveUpdates(): Observable<Identity> = _change.map { this } + fun id() = _identityId fun identityName() = _identityName fun realName() = _realName @@ -84,6 +88,12 @@ class Identity constructor( fun partReason() = _partReason fun quitReason() = _quitReason + fun copy(): Identity { + val identity = Identity(SignalProxy.NULL) + identity.fromVariantMap(this.toVariantMap()) + return identity + } + override fun setAutoAwayEnabled(enabled: Boolean) { _autoAwayEnabled = enabled super.setAutoAwayEnabled(enabled) @@ -179,23 +189,101 @@ class Identity constructor( super.setRealName(realName) } + private val _change = BehaviorSubject.createDefault(Unit) + private var _identityId: IdentityId = -1 + set(value) { + field = value + _change.onNext(Unit) + } private var _identityName: String = "<isEmpty>" + set(value) { + field = value + _change.onNext(Unit) + } private var _realName: String = "" + set(value) { + field = value + _change.onNext(Unit) + } private var _nicks: MutableList<String> = mutableListOf("quassel") + set(value) { + field = value + _change.onNext(Unit) + } private var _awayNick: String = "" + set(value) { + field = value + _change.onNext(Unit) + } private var _awayNickEnabled: Boolean = false + set(value) { + field = value + _change.onNext(Unit) + } private var _awayReason: String = "Gone fishing." + set(value) { + field = value + _change.onNext(Unit) + } private var _awayReasonEnabled: Boolean = true + set(value) { + field = value + _change.onNext(Unit) + } private var _autoAwayEnabled: Boolean = false + set(value) { + field = value + _change.onNext(Unit) + } private var _autoAwayTime: Int = 10 + set(value) { + field = value + _change.onNext(Unit) + } private var _autoAwayReason: String = "Not here. No, really. not here!" + set(value) { + field = value + _change.onNext(Unit) + } private var _autoAwayReasonEnabled: Boolean = false + set(value) { + field = value + _change.onNext(Unit) + } private var _detachAwayEnabled: Boolean = false + set(value) { + field = value + _change.onNext(Unit) + } private var _detachAwayReason: String = "All Quassel clients vanished from the face of the earth..." + set(value) { + field = value + _change.onNext(Unit) + } private var _detachAwayReasonEnabled: Boolean = false + set(value) { + field = value + _change.onNext(Unit) + } private var _ident: String = "quassel" + set(value) { + field = value + _change.onNext(Unit) + } private var _kickReason: String = "Kindergarten is elsewhere!" + set(value) { + field = value + _change.onNext(Unit) + } private var _partReason: String = "http://quassel-irc.org - Chat comfortably. Anywhere." + set(value) { + field = value + _change.onNext(Unit) + } private var _quitReason: String = "http://quassel-irc.org - Chat comfortably. Anywhere." + set(value) { + field = value + _change.onNext(Unit) + } } diff --git a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt index 03f90a5a7e0f23fe67543ec99ef3851b35ed7e1e..c566fd79b11bbf47257e0da514481c735e587483 100644 --- a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt +++ b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt @@ -156,7 +156,9 @@ class Session( val identity = Identity(this) identity.fromVariantMap(it.valueOr(::emptyMap)) identity.initialized = true + identity.init() identities[identity.id()] = identity + synchronize(identity) val certManager = CertManager(identity.id(), this) certManagers[identity.id()] = certManager diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt index 260f85978a1b7198edcee15136bdba1f136bbb37..64a57cb96a526926be59961c2c7b6cd3e7f3811c 100644 --- a/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt +++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt @@ -2,16 +2,15 @@ package de.kuschku.quasseldroid.util.helper import android.arch.lifecycle.LiveData import android.arch.lifecycle.LiveDataReactiveStreams -import io.reactivex.BackpressureStrategy -import io.reactivex.Flowable -import io.reactivex.Observable -import io.reactivex.ObservableSource +import io.reactivex.* import io.reactivex.functions.BiFunction inline fun <T> Observable<T>.toLiveData( strategy: BackpressureStrategy = BackpressureStrategy.LATEST ): LiveData<T> = LiveDataReactiveStreams.fromPublisher(toFlowable(strategy)) +inline fun <T> Maybe<T>.toLiveData(): LiveData<T> = LiveDataReactiveStreams.fromPublisher(toFlowable()) + inline fun <T> Flowable<T>.toLiveData(): LiveData<T> = LiveDataReactiveStreams.fromPublisher(this) inline fun <reified A, B> combineLatest( diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt index f09fe5356567618f8812cf137b8d6dace374adcd..2e620768182343b0d3becf2c551d3e9494fd4c1d 100644 --- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt +++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt @@ -76,6 +76,18 @@ class QuasselViewModel : ViewModel() { it.orNull()?.error?.toLiveData() } + val networkConfig = session.map { + it.map(ISession::networkConfig) + } + + val networks = session.switchMap { + it.map(ISession::liveNetworks).orElse(Observable.just(emptyMap())) + } + + val identities = session.switchMap { + it.map(ISession::liveIdentities).orElse(Observable.just(emptyMap())) + } + /** * An observable of the changes of the markerline, as pairs of `(old, new)` */