Show identicons in user list and settings (fixes #27).

This commit is contained in:
Felix Ableitner 2015-07-27 13:17:57 +02:00
parent 1c3bc5618e
commit cdece0ef42
13 changed files with 177 additions and 49 deletions

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="25dp">
<ImageView
android:id="@+id/identicon"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginBottom="25dp" />
<TextView
android:id="@+id/address"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>

View file

@ -1,29 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/listPreferredItemHeight"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
android:paddingRight="?android:attr/listPreferredItemPaddingRight"
android:orientation="vertical" >
android:paddingRight="?android:attr/listPreferredItemPaddingRight" >
<TextView android:id="@android:id/text1"
<ImageView
android:id="@+id/identicon"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true" />
<TextView
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textStyle="bold"
android:singleLine="true"
android:ellipsize="end" />
android:ellipsize="end"
android:layout_toRightOf="@id/identicon"
android:layout_marginLeft="10dp" />
<TextView android:id="@android:id/text2"
<TextView
android:id="@android:id/text2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:singleLine="true"
android:ellipsize="end" />
android:ellipsize="end"
android:layout_below="@android:id/text1"
android:layout_alignLeft="@android:id/text1" />
</LinearLayout>
</RelativeLayout>

View file

@ -78,6 +78,9 @@
<!-- Preference title -->
<string name="user_status">Status</string>
<!-- Preference title -->
<string name="my_address">My Address</string>
<!-- Preference title -->
<string name="scan_interval_seconds">Scan Interval (seconds)</string>
@ -98,6 +101,11 @@
<!-- Preference title -->
<string name="version">Version</string>
<!-- IdenticonFragment -->
<!-- Device address label and value -->
<string name="address_colon">Address: %1$s</string>
<!-- ChatService -->

View file

@ -10,6 +10,10 @@
android:title="@string/user_status"
android:key="user_status" />
<Preference
android:title="@string/my_address"
android:key="my_address" />
<CheckBoxPreference
android:title="@string/notification_sounds"
android:key="notification_sounds"

View file

@ -10,7 +10,8 @@ import android.widget._
import com.nutomic.ensichat.R
import com.nutomic.ensichat.protocol.ChatService
import com.nutomic.ensichat.protocol.body.RequestAddContact
import com.nutomic.ensichat.util.{Database, UsersAdapter}
import com.nutomic.ensichat.util.Database
import com.nutomic.ensichat.views.UsersAdapter
/**
* Lists all nearby, connected devices and allows adding them to be added as contacts.

View file

@ -13,7 +13,8 @@ import com.nutomic.ensichat.R
import com.nutomic.ensichat.activities.EnsichatActivity
import com.nutomic.ensichat.protocol.body.Text
import com.nutomic.ensichat.protocol.{Message, Address, ChatService}
import com.nutomic.ensichat.util.{Database, MessagesAdapter}
import com.nutomic.ensichat.util.Database
import com.nutomic.ensichat.views.MessagesAdapter
/**
* Represents a single chat with another specific device.

View file

@ -12,7 +12,8 @@ import android.widget.ListView
import com.nutomic.ensichat.R
import com.nutomic.ensichat.activities.{AddContactsActivity, EnsichatActivity, MainActivity, SettingsActivity}
import com.nutomic.ensichat.protocol.ChatService
import com.nutomic.ensichat.util.{Database, UsersAdapter}
import com.nutomic.ensichat.util.Database
import com.nutomic.ensichat.views.UsersAdapter
import scala.collection.JavaConversions._
/**

View file

@ -0,0 +1,50 @@
package com.nutomic.ensichat.fragments
import android.app.{AlertDialog, Dialog, DialogFragment}
import android.os.Bundle
import android.view.{LayoutInflater, View, ViewGroup}
import android.widget.{ImageView, TextView}
import com.nutomic.ensichat.R
import com.nutomic.ensichat.protocol.Address
import com.nutomic.ensichat.util.IdenticonGenerator
object IdenticonFragment {
private val ExtraAddress = "address"
private val ExtraUserName = "user_name"
def getInstance(address: Address, userName: String): IdenticonFragment = {
val bundle = new Bundle()
bundle.putString(IdenticonFragment.ExtraAddress, address.toString)
bundle.putString(IdenticonFragment.ExtraUserName, userName)
val fragment = new IdenticonFragment()
fragment.setArguments(bundle)
fragment
}
}
/**
* Displays identicon, username and address for a user.
*
* Use [[IdenticonFragment#getInstance]] to invoke.
*/
class IdenticonFragment extends DialogFragment {
private lazy val address = new Address(getArguments.getString(IdenticonFragment.ExtraAddress))
private lazy val userName = getArguments.getString(IdenticonFragment.ExtraUserName)
override def onCreateView(inflater: LayoutInflater, container: ViewGroup,
savedInstanceState: Bundle): View = {
getDialog.setTitle(userName)
val view = inflater.inflate(R.layout.activity_identicon, container)
view.findViewById(R.id.identicon)
.asInstanceOf[ImageView]
.setImageBitmap(IdenticonGenerator.generate(address, (150, 150), getActivity))
view.findViewById(R.id.address)
.asInstanceOf[TextView]
.setText(getString(R.string.address_colon, address.toString))
view
}
}

View file

@ -1,8 +1,10 @@
package com.nutomic.ensichat.fragments
import android.content.Intent
import android.os.{Build, Bundle}
import android.preference.Preference.OnPreferenceChangeListener
import android.preference.Preference.{OnPreferenceClickListener, OnPreferenceChangeListener}
import android.preference.{Preference, PreferenceFragment, PreferenceManager}
import com.nutomic.ensichat.protocol.Crypto
import com.nutomic.ensichat.{BuildConfig, R}
import com.nutomic.ensichat.activities.EnsichatActivity
import com.nutomic.ensichat.fragments.SettingsFragment._
@ -13,6 +15,7 @@ object SettingsFragment {
val KeyUserName = "user_name"
val KeyUserStatus = "user_status"
val KeyMyAddress = "my_address"
val KeyScanInterval = "scan_interval_seconds"
val MaxConnections = "max_connections"
val Version = "version"
@ -22,12 +25,14 @@ object SettingsFragment {
/**
* Settings screen.
*/
class SettingsFragment extends PreferenceFragment with OnPreferenceChangeListener {
class SettingsFragment extends PreferenceFragment with OnPreferenceChangeListener
with OnPreferenceClickListener {
private lazy val database = new Database(getActivity)
private lazy val name = findPreference(KeyUserName)
private lazy val status = findPreference(KeyUserStatus)
private lazy val myAddress = findPreference(KeyMyAddress)
private lazy val scanInterval = findPreference(KeyScanInterval)
private lazy val maxConnections = findPreference(MaxConnections)
private lazy val version = findPreference(Version)
@ -43,6 +48,7 @@ class SettingsFragment extends PreferenceFragment with OnPreferenceChangeListene
name.setOnPreferenceChangeListener(this)
status.setSummary(prefs.getString(KeyUserStatus, ""))
status.setOnPreferenceChangeListener(this)
myAddress.setOnPreferenceClickListener(this)
scanInterval.setOnPreferenceChangeListener(this)
scanInterval.setSummary(prefs.getString(
@ -73,4 +79,16 @@ class SettingsFragment extends PreferenceFragment with OnPreferenceChangeListene
true
}
override def onPreferenceClick (preference: Preference): Boolean = {
preference.getKey match {
case KeyMyAddress =>
val fragment = IdenticonFragment.getInstance(new Crypto(getActivity).localAddress,
prefs.getString(KeyUserName, ""))
fragment.show(getFragmentManager, "dialog")
true
case _ =>
false
}
}
}

View file

@ -20,9 +20,9 @@ object IdenticonGenerator {
/**
* Generates an identicon for the key.
*
* The identicon size is fixed to [[Height]]x[[Width]].
* The identicon size is fixed to [[Width]]x[[Height]].
*
* @param size The size of the bitmap returned.
* @param size The size of the bitmap returned in pixels (widthxheight).
*/
def generate(address: Address, size: (Int, Int), context: Context): Bitmap = {
val hash = address.bytes

View file

@ -1,32 +0,0 @@
package com.nutomic.ensichat.util
import android.content.Context
import android.view.{LayoutInflater, View, ViewGroup}
import android.widget.{ArrayAdapter, TextView}
import com.nutomic.ensichat.R
import com.nutomic.ensichat.bluetooth.Device
import com.nutomic.ensichat.protocol.User
/**
* Displays [[Device]]s in ListView.
*/
class UsersAdapter(context: Context) extends
ArrayAdapter[User](context, 0) {
override def getView(position: Int, convertView: View, parent: ViewGroup): View = {
val view =
if (convertView == null) {
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)
.asInstanceOf[LayoutInflater]
.inflate(R.layout.item_user, parent, false)
} else
convertView
val title = view.findViewById(android.R.id.text1).asInstanceOf[TextView]
val summary = view.findViewById(android.R.id.text2).asInstanceOf[TextView]
val item = getItem(position)
title.setText(item.name)
summary.setText(item.status)
view
}
}

View file

@ -1,11 +1,11 @@
package com.nutomic.ensichat.util
package com.nutomic.ensichat.views
import android.content.Context
import android.view.{Gravity, View, ViewGroup}
import android.widget.{ArrayAdapter, RelativeLayout, TextView}
import com.nutomic.ensichat.R
import com.nutomic.ensichat.protocol.{Message, Address}
import com.nutomic.ensichat.protocol.body.Text
import com.nutomic.ensichat.protocol.{Address, Message}
/**
* Displays [[Message]]s in ListView.

View file

@ -0,0 +1,46 @@
package com.nutomic.ensichat.views
import android.app.Activity
import android.content.Context
import android.view.View.OnClickListener
import android.view.{LayoutInflater, View, ViewGroup}
import android.widget.{ArrayAdapter, ImageView, TextView}
import com.nutomic.ensichat.R
import com.nutomic.ensichat.fragments.IdenticonFragment
import com.nutomic.ensichat.protocol.{Crypto, User}
import com.nutomic.ensichat.util.IdenticonGenerator
/**
* Displays [[User]]s in ListView.
*/
class UsersAdapter(activity: Activity) extends ArrayAdapter[User](activity, 0) with OnClickListener {
override def getView(position: Int, convertView: View, parent: ViewGroup): View = {
val view =
if (convertView == null) {
activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE)
.asInstanceOf[LayoutInflater]
.inflate(R.layout.item_user, parent, false)
} else
convertView
val identicon = view.findViewById(R.id.identicon).asInstanceOf[ImageView]
val title = view.findViewById(android.R.id.text1).asInstanceOf[TextView]
val summary = view.findViewById(android.R.id.text2).asInstanceOf[TextView]
val user = getItem(position)
identicon.setImageBitmap(IdenticonGenerator.generate(user.address, (50, 50), activity))
identicon.setOnClickListener(this)
identicon.setTag(user)
title.setText(user.name)
summary.setText(user.status)
view
}
override def onClick (v: View): Unit = {
val user = v.getTag.asInstanceOf[User]
val fragment = IdenticonFragment.getInstance(user.address, user.name)
fragment.show(activity.getFragmentManager, "dialog")
}
}