chat bubbles. yeah
This commit is contained in:
parent
665ef7511f
commit
898b0ca8c4
|
@ -9,6 +9,7 @@
|
|||
android:targetSdkVersion="19" />
|
||||
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.READ_PROFILE"/>
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
|
|
@ -32,29 +32,33 @@ public final class R {
|
|||
public static final int ic_action_unsecure=0x7f020004;
|
||||
public static final int ic_launcher=0x7f020005;
|
||||
public static final int ic_profile=0x7f020006;
|
||||
public static final int section_header=0x7f020007;
|
||||
public static final int message_border=0x7f020007;
|
||||
public static final int profilemock=0x7f020008;
|
||||
public static final int section_header=0x7f020009;
|
||||
}
|
||||
public static final class id {
|
||||
public static final int action_accounts=0x7f0a001b;
|
||||
public static final int action_add=0x7f0a0017;
|
||||
public static final int action_archive=0x7f0a001a;
|
||||
public static final int action_details=0x7f0a0019;
|
||||
public static final int action_security=0x7f0a0018;
|
||||
public static final int action_settings=0x7f0a001c;
|
||||
public static final int action_accounts=0x7f0a001e;
|
||||
public static final int action_add=0x7f0a001a;
|
||||
public static final int action_archive=0x7f0a001d;
|
||||
public static final int action_details=0x7f0a001c;
|
||||
public static final int action_security=0x7f0a001b;
|
||||
public static final int action_settings=0x7f0a001f;
|
||||
public static final int contact_display_name=0x7f0a0009;
|
||||
public static final int contact_divider=0x7f0a000b;
|
||||
public static final int contact_jid=0x7f0a000a;
|
||||
public static final int contact_photo=0x7f0a0008;
|
||||
public static final int conversation_image=0x7f0a000c;
|
||||
public static final int conversation_lastmsg=0x7f0a000e;
|
||||
public static final int conversation_lastupdate=0x7f0a000f;
|
||||
public static final int conversation_name=0x7f0a000d;
|
||||
public static final int create_new_contact=0x7f0a0007;
|
||||
public static final int duration=0x7f0a000f;
|
||||
public static final int editText1=0x7f0a0011;
|
||||
public static final int imageButton1=0x7f0a0012;
|
||||
public static final int jabber_contacts=0x7f0a0005;
|
||||
public static final int jabber_contacts_header=0x7f0a0004;
|
||||
public static final int list=0x7f0a0015;
|
||||
public static final int message_body=0x7f0a0018;
|
||||
public static final int message_photo=0x7f0a0017;
|
||||
public static final int message_time=0x7f0a0019;
|
||||
public static final int messages_view=0x7f0a0013;
|
||||
public static final int new_contact_header=0x7f0a0006;
|
||||
public static final int new_conversation_search=0x7f0a0000;
|
||||
public static final int phone_contacts=0x7f0a0003;
|
||||
|
@ -62,7 +66,8 @@ public final class R {
|
|||
public static final int scrollView1=0x7f0a0001;
|
||||
public static final int selected_conversation=0x7f0a0016;
|
||||
public static final int slidingpanelayout=0x7f0a0014;
|
||||
public static final int textView1=0x7f0a0013;
|
||||
public static final int textSendButton=0x7f0a0012;
|
||||
public static final int textinput=0x7f0a0011;
|
||||
public static final int textsend=0x7f0a0010;
|
||||
}
|
||||
public static final class layout {
|
||||
|
@ -71,6 +76,7 @@ public final class R {
|
|||
public static final int conversation_list_row=0x7f030002;
|
||||
public static final int fragment_conversation=0x7f030003;
|
||||
public static final int fragment_conversations_overview=0x7f030004;
|
||||
public static final int message_sent=0x7f030005;
|
||||
}
|
||||
public static final class menu {
|
||||
public static final int conversations=0x7f090000;
|
||||
|
@ -84,6 +90,8 @@ public final class R {
|
|||
public static final int action_secure=0x7f070006;
|
||||
public static final int action_settings=0x7f070001;
|
||||
public static final int app_name=0x7f070000;
|
||||
public static final int just_now=0x7f070008;
|
||||
public static final int sending=0x7f070009;
|
||||
public static final int title_activity_new_conversation=0x7f070007;
|
||||
}
|
||||
public static final class style {
|
||||
|
|
6
res/drawable/message_border.xml
Normal file
6
res/drawable/message_border.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<corners android:radius="2dp"/>
|
||||
<padding android:left="1.5dp" android:right="1.5dp" android:top="1.5dp" android:bottom="1.5dp"/>
|
||||
<solid android:color="#cecece"/>
|
||||
</shape>
|
|
@ -38,7 +38,7 @@
|
|||
android:paddingTop="3dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/duration"
|
||||
android:id="@+id/conversation_lastupdate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBaseline="@+id/conversation_name"
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#f9f9f9">
|
||||
android:background="#e5e5e5" >
|
||||
|
||||
<RelativeLayout
|
||||
android:background="#eee"
|
||||
android:id="@+id/textsend"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -12,53 +14,42 @@
|
|||
android:layout_alignParentLeft="true" >
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editText1"
|
||||
android:id="@+id/textinput"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_toLeftOf="@+id/imageButton1"
|
||||
android:paddingBottom="12dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:paddingTop="12dp"
|
||||
android:layout_toLeftOf="@+id/textSendButton"
|
||||
android:background="#eee"
|
||||
android:ems="10"
|
||||
android:inputType="textMultiLine"
|
||||
android:minLines="1"
|
||||
android:background="#ffffff"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp">
|
||||
android:minLines="1" >
|
||||
</EditText>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/imageButton1"
|
||||
android:id="@+id/textSendButton"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:src="@drawable/ic_action_send_now" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/scrollView1"
|
||||
<ListView
|
||||
android:id="@+id/messages_view"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/textsend"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:background="#e5e5e5" >
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:background="#e5e5e5"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TextView" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
tools:listitem="@layout/message_sent"
|
||||
android:divider="@null"
|
||||
android:dividerHeight="0dp">
|
||||
</ListView>
|
||||
|
||||
</RelativeLayout>
|
53
res/layout/message_sent.xml
Normal file
53
res/layout/message_sent.xml
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/message_border"
|
||||
android:layout_toLeftOf="@+id/message_photo"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:minHeight="48dp"
|
||||
>
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="#ededed"
|
||||
android:padding="5dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hi, how are you?"
|
||||
android:textSize="16sp"
|
||||
android:id="@+id/message_body"
|
||||
android:textColor="#333333"/>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="1dp"
|
||||
android:text="@string/sending"
|
||||
android:textColor="#8e8e8e"
|
||||
android:textSize="12sp"
|
||||
android:id="@+id/message_time"/>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<ImageView
|
||||
android:id="@+id/message_photo"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginLeft="-1.5dp"
|
||||
android:padding="0dp"
|
||||
android:src="@drawable/ic_profile"
|
||||
android:scaleType="fitXY"/>
|
||||
|
||||
</RelativeLayout>
|
|
@ -9,4 +9,6 @@
|
|||
<string name="action_details">Show details</string>
|
||||
<string name="action_secure">Secure conversation</string>
|
||||
<string name="title_activity_new_conversation">New Conversation</string>
|
||||
<string name="just_now">just now</string>
|
||||
<string name="sending">sending…</string>
|
||||
</resources>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package de.gultsch.chat.entities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.ContentValues;
|
||||
|
@ -9,6 +10,9 @@ import android.net.Uri;
|
|||
public class Conversation extends AbstractEntity {
|
||||
|
||||
private static final long serialVersionUID = -6727528868973996739L;
|
||||
|
||||
public static final String TABLENAME = "conversations";
|
||||
|
||||
public static final int STATUS_AVAILABLE = 0;
|
||||
public static final int STATUS_ARCHIVED = 1;
|
||||
public static final int STATUS_DELETED = 2;
|
||||
|
@ -27,7 +31,7 @@ public class Conversation extends AbstractEntity {
|
|||
private int status;
|
||||
private long created;
|
||||
|
||||
private transient List<Message> messages;
|
||||
private transient List<Message> messages = null;
|
||||
|
||||
public Conversation(String name, Uri profilePhoto, Account account,
|
||||
String contactJid) {
|
||||
|
@ -48,6 +52,7 @@ public class Conversation extends AbstractEntity {
|
|||
}
|
||||
|
||||
public List<Message> getMessages() {
|
||||
if (messages == null) this.messages = new ArrayList<Message>(); //prevent null pointer
|
||||
return messages;
|
||||
}
|
||||
|
||||
|
@ -82,6 +87,10 @@ public class Conversation extends AbstractEntity {
|
|||
return this.status;
|
||||
}
|
||||
|
||||
public long getCreated() {
|
||||
return this.created;
|
||||
}
|
||||
|
||||
public ContentValues getContentValues() {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(UUID, uuid);
|
||||
|
|
|
@ -7,6 +7,8 @@ public class Message extends AbstractEntity {
|
|||
|
||||
private static final long serialVersionUID = 7222081895167103025L;
|
||||
|
||||
public static final String TABLENAME = "messages";
|
||||
|
||||
public static final int STATUS_RECIEVED = 0;
|
||||
public static final int STATUS_UNSEND = 1;
|
||||
public static final int STATUS_SEND = 2;
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import de.gultsch.chat.entities.Conversation;
|
||||
import de.gultsch.chat.entities.Message;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
@ -22,7 +23,13 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL("create table conversations (uuid TEXT, name TEXT, profilePhotoUri TEXT, accountUuid TEXT, contactJid TEXT, created NUMBER, status NUMBER)");
|
||||
db.execSQL("create table " + Conversation.TABLENAME + " ("
|
||||
+ Conversation.UUID + " TEXT, " + Conversation.NAME + " TEXT, "
|
||||
+ Conversation.PHOTO_URI + " TEXT, " + Conversation.ACCOUNT
|
||||
+ " TEXT, " + Conversation.CONTACT + " TEXT, "
|
||||
+ Conversation.CREATED + " NUMBER, " + Conversation.STATUS
|
||||
+ " NUMBER)");
|
||||
db.execSQL("create table "+Message.TABLENAME+ "()");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -43,10 +50,10 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||
db.insert("conversations", null, conversation.getContentValues());
|
||||
}
|
||||
|
||||
|
||||
public int getConversationCount() {
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
Cursor cursor = db.rawQuery("select count(uuid) as count from conversations",null);
|
||||
Cursor cursor = db.rawQuery(
|
||||
"select count(uuid) as count from conversations", null);
|
||||
cursor.moveToFirst();
|
||||
return cursor.getInt(0);
|
||||
}
|
||||
|
@ -55,7 +62,10 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||
List<Conversation> list = new ArrayList<Conversation>();
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
String[] selectionArgs = { "" + status };
|
||||
Cursor cursor = db.rawQuery("select * from conversations where status = ? order by created desc", selectionArgs);
|
||||
Cursor cursor = db
|
||||
.rawQuery(
|
||||
"select * from conversations where status = ? order by created desc",
|
||||
selectionArgs);
|
||||
while (cursor.moveToNext()) {
|
||||
list.add(Conversation.fromCursor(cursor));
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import de.gultsch.chat.entities.Account;
|
|||
import de.gultsch.chat.entities.Contact;
|
||||
import de.gultsch.chat.entities.Conversation;
|
||||
import de.gultsch.chat.persistance.DatabaseBackend;
|
||||
import de.gultsch.chat.utils.Beautifier;
|
||||
import android.os.Bundle;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.content.Context;
|
||||
|
@ -60,6 +61,8 @@ public class ConversationActivity extends XmppActivity {
|
|||
}
|
||||
((TextView) view.findViewById(R.id.conversation_name))
|
||||
.setText(getItem(position).getName());
|
||||
((TextView) view.findViewById(R.id.conversation_lastupdate))
|
||||
.setText(Beautifier.readableTimeDifference(getItem(position).getCreated()));
|
||||
((ImageView) view.findViewById(R.id.conversation_image))
|
||||
.setImageURI(getItem(position).getProfilePhotoUri());
|
||||
return view;
|
||||
|
|
|
@ -2,11 +2,27 @@ package de.gultsch.chat.ui;
|
|||
|
||||
import de.gultsch.chat.R;
|
||||
import de.gultsch.chat.entities.Conversation;
|
||||
import de.gultsch.chat.entities.Message;
|
||||
import de.gultsch.chat.utils.Beautifier;
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Typeface;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.ContactsContract.Profile;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class ConversationFragment extends Fragment {
|
||||
|
||||
|
@ -17,8 +33,76 @@ public class ConversationFragment extends Fragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_conversation, container, false);
|
||||
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
||||
String[] mProjection = new String[]
|
||||
{
|
||||
Profile._ID,
|
||||
Profile.PHOTO_THUMBNAIL_URI
|
||||
};
|
||||
Cursor mProfileCursor = getActivity().getContentResolver().query(
|
||||
Profile.CONTENT_URI,
|
||||
mProjection ,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
|
||||
mProfileCursor.moveToFirst();
|
||||
final Uri profilePicture = Uri.parse(mProfileCursor.getString(1));
|
||||
|
||||
Log.d("gultsch","found user profile pic "+profilePicture.toString());
|
||||
|
||||
final View view = inflater.inflate(R.layout.fragment_conversation, container,
|
||||
false);
|
||||
((ImageButton) view.findViewById(R.id.textSendButton))
|
||||
.setOnClickListener(new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
EditText chatMsg = (EditText) view.findViewById(R.id.textinput);
|
||||
if (chatMsg.getText().length() < 1) return;
|
||||
Message message = new Message(conversation,chatMsg.getText().toString(),
|
||||
Message.ENCRYPTION_NONE);
|
||||
XmppActivity activity = (XmppActivity) getActivity();
|
||||
activity.xmppConnectionService.sendMessage(message);
|
||||
conversation.getMessages().add(message);
|
||||
chatMsg.setText("");
|
||||
|
||||
ListView messagesView = (ListView) view.findViewById(R.id.messages_view);
|
||||
ArrayAdapter<Message> adapter = (ArrayAdapter<Message>) messagesView.getAdapter();
|
||||
adapter.notifyDataSetChanged();
|
||||
|
||||
messagesView.setSelection(conversation.getMessages().size() -1);
|
||||
}
|
||||
});
|
||||
|
||||
ListView messagesView = (ListView) view
|
||||
.findViewById(R.id.messages_view);
|
||||
messagesView.setAdapter(new ArrayAdapter<Message>(this.getActivity()
|
||||
.getApplicationContext(), R.layout.message_sent,
|
||||
this.conversation.getMessages()) {
|
||||
|
||||
@Override
|
||||
public View getView(int position, View view, ViewGroup parent) {
|
||||
Message item = getItem(position);
|
||||
if ((item.getStatus() != Message.STATUS_RECIEVED)
|
||||
|| (item.getStatus() == Message.STATUS_SEND)) {
|
||||
view = (View) inflater.inflate(R.layout.message_sent, null);
|
||||
((ImageView) view.findViewById(R.id.message_photo)).setImageURI(profilePicture);
|
||||
}
|
||||
((TextView) view.findViewById(R.id.message_body)).setText(item.getBody());
|
||||
TextView time = (TextView) view.findViewById(R.id.message_time);
|
||||
if (item.getStatus() == Message.STATUS_UNSEND) {
|
||||
time.setTypeface(null, Typeface.ITALIC);
|
||||
} else {
|
||||
time.setText(Beautifier.readableTimeDifference(item.getTimeSent()));
|
||||
}
|
||||
return view;
|
||||
}
|
||||
});
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
public Conversation getConversation() {
|
||||
|
|
|
@ -10,8 +10,8 @@ import android.content.ServiceConnection;
|
|||
import android.os.IBinder;
|
||||
|
||||
public abstract class XmppActivity extends Activity {
|
||||
protected XmppConnectionService xmppConnectionService;
|
||||
protected boolean xmppConnectionServiceBound = false;
|
||||
public XmppConnectionService xmppConnectionService;
|
||||
public boolean xmppConnectionServiceBound = false;
|
||||
protected boolean handledViewIntent = false;
|
||||
protected ServiceConnection mConnection = new ServiceConnection() {
|
||||
|
||||
|
|
25
src/de/gultsch/chat/utils/Beautifier.java
Normal file
25
src/de/gultsch/chat/utils/Beautifier.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
package de.gultsch.chat.utils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class Beautifier {
|
||||
public static String readableTimeDifference(long time) {
|
||||
if (time==0) {
|
||||
return "just now";
|
||||
}
|
||||
Date date = new Date(time);
|
||||
long difference = (System.currentTimeMillis() - time) / 1000;
|
||||
if (difference<60) {
|
||||
return "just now";
|
||||
} else if (difference<60*10) {
|
||||
return difference / 60 + " min ago";
|
||||
} else if (difference<60*60*24) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
|
||||
return sdf.format(date);
|
||||
} else {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("M/D");
|
||||
return sdf.format(date);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue