App saves/displays draft messages

This commit is contained in:
Sylvain Berfini 2012-09-20 14:32:43 +02:00
parent fa376612ed
commit 4ff6ae2d5f
8 changed files with 178 additions and 58 deletions

View file

@ -48,7 +48,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/new_fast_chat"
android:textColor="@color/text_default"
android:textColor="@android:color/black"
android:inputType="textEmailAddress"/>
<ListView

View file

@ -1,37 +1,56 @@
<?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="match_parent"
android:gravity="center_vertical"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:background="@drawable/list_selector"
android:orientation="horizontal" >
<TextView
android:id="@+id/sipUri"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.1"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@android:color/black"
android:layout_marginLeft="10dp" />
<ImageView
android:contentDescription="@string/content_description_detail"
android:id="@+id/detail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.9"
android:src="@drawable/list_detail" />
android:background="@drawable/list_selector">
<ImageView
android:contentDescription="@string/content_description_delete"
android:id="@+id/delete"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="0.9"
android:visibility="gone"
android:paddingRight="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:visibility="invisible"
android:src="@drawable/list_delete" />
</LinearLayout>
<ImageView
android:contentDescription="@string/content_description_detail"
android:id="@+id/detail"
android:paddingRight="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:adjustViewBounds="true"
android:src="@drawable/list_detail" />
<TextView
android:id="@+id/draft"
android:visibility="gone"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/text_selected"
android:layout_toLeftOf="@id/detail"
android:text="@string/draft"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp" />
<TextView
android:id="@+id/sipUri"
android:layout_centerVertical="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@android:color/black"
android:layout_toLeftOf="@id/draft"
android:layout_marginLeft="10dp" />
</RelativeLayout>

View file

@ -201,6 +201,7 @@
<string name="addressHint">Numéro ou adresse</string>
<string name="conference">Conférence</string>
<string name="draft">Brouillon</string>
<string name="new_fast_chat">Entrez une adresse SIP avec qui discuter&#8230;</string>
<!-- Used by Android to help blind people by describing them images -->

View file

@ -251,6 +251,7 @@
<string name="addressHint">Number or address</string>
<string name="conference">Conference</string>
<string name="draft">Draft</string>
<string name="new_fast_chat">Enter a SIP address to chat with&#8230;</string>
<!-- Used by Android to help blind people by describing them images -->

View file

@ -322,6 +322,17 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
public void onPause() {
super.onPause();
latestImageMessages = null;
if (!message.getText().toString().equals("") && LinphoneActivity.isInstanciated()) {
ChatStorage chatStorage = LinphoneActivity.instance().getChatStorage();
if (chatStorage.getDraft(sipUri) == null) {
chatStorage.saveDraft(sipUri, message.getText().toString());
} else {
chatStorage.updateDraft(sipUri, message.getText().toString());
}
} else if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().getChatStorage().deleteDraft(sipUri);
}
}
@SuppressLint("UseSparseArrays")
@ -336,6 +347,11 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
LinphoneActivity.instance().updateChatFragment(this);
}
scrollToEnd();
if (LinphoneActivity.isInstanciated()) {
String draft = LinphoneActivity.instance().getChatStorage().getDraft(sipUri);
message.setText(draft);
}
}
@Override

View file

@ -24,8 +24,6 @@ import org.linphone.core.LinphoneCoreFactory;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
@ -47,9 +45,9 @@ import android.widget.TextView;
*/
public class ChatListFragment extends Fragment implements OnClickListener, OnItemClickListener {
private LayoutInflater mInflater;
private List<String> mConversations;
private List<String> mConversations, mDrafts;
private ListView chatList;
private ImageView edit, ok, newDiscussion, isFastNewChatAddressOk;
private ImageView edit, ok, newDiscussion;
private EditText fastNewChat;
private boolean isEditMode = false;
@ -78,10 +76,13 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
public void onResume() {
super.onResume();
if (LinphoneActivity.isInstanciated())
if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().selectMenu(FragmentsAvailable.CHATLIST);
}
mConversations = LinphoneActivity.instance().getChatList();
mDrafts = LinphoneActivity.instance().getDraftChatList();
mConversations.removeAll(mDrafts);
chatList.setAdapter(new ChatListAdapter());
}
@ -101,6 +102,8 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
LinphoneActivity.instance().removeFromChatList(sipUri);
mConversations = LinphoneActivity.instance().getChatList();
mDrafts = LinphoneActivity.instance().getDraftChatList();
mConversations.removeAll(mDrafts);
chatList.setAdapter(new ChatListAdapter());
return true;
}
@ -145,8 +148,13 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
LinphoneActivity.instance().displayChat(sipUri);
} else if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().removeFromChatList(sipUri);
LinphoneActivity.instance().removeFromDrafts(sipUri);
mConversations = LinphoneActivity.instance().getChatList();
mDrafts = LinphoneActivity.instance().getDraftChatList();
mConversations.removeAll(mDrafts);
chatList.setAdapter(new ChatListAdapter());
LinphoneActivity.instance().updateMissedChatCount();
}
}
@ -156,7 +164,7 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
}
public int getCount() {
return mConversations.size();
return mConversations.size() + mDrafts.size();
}
public Object getItem(int position) {
@ -176,7 +184,14 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
view = mInflater.inflate(R.layout.chatlist_cell, parent, false);
}
String contact = mConversations.get(position);
String contact;
boolean isDraft = false;
if (position >= mDrafts.size()) {
contact = mConversations.get(position - mDrafts.size());
} else {
contact = mDrafts.get(position);
isDraft = true;
}
view.setTag(contact);
LinphoneAddress address = LinphoneCoreFactory.instance().createLinphoneAddress(contact);
@ -191,6 +206,9 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
}
sipUri.setText(address.getDisplayName() == null ? contact : address.getDisplayName());
if (isDraft) {
view.findViewById(R.id.draft).setVisibility(View.VISIBLE);
}
ImageView delete, detail;
delete = (ImageView) view.findViewById(R.id.delete);
@ -198,9 +216,9 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
if (isEditMode) {
delete.setVisibility(View.VISIBLE);
detail.setVisibility(View.GONE);
detail.setVisibility(View.INVISIBLE);
} else {
delete.setVisibility(View.GONE);
delete.setVisibility(View.INVISIBLE);
detail.setVisibility(View.VISIBLE);
}

View file

@ -42,6 +42,7 @@ public class ChatStorage {
private Context context;
private SQLiteDatabase db;
private static final String TABLE_NAME = "chat";
private static final String DRAFT_TABLE_NAME = "chat_draft";
public ChatStorage(Context c) {
context = c;
@ -110,6 +111,57 @@ public class ChatStorage {
return (int) db.insert(TABLE_NAME, null, values);
}
public int saveDraft(String to, String message) {
ContentValues values = new ContentValues();
values.put("remoteContact", to);
values.put("message", message);
return (int) db.insert(DRAFT_TABLE_NAME, null, values);
}
public void updateDraft(String to, String message) {
ContentValues values = new ContentValues();
values.put("message", message);
db.update(DRAFT_TABLE_NAME, values, "remoteContact LIKE \"" + to + "\"", null);
}
public void deleteDraft(String to) {
db.delete(DRAFT_TABLE_NAME, "remoteContact LIKE \"" + to + "\"", null);
}
public String getDraft(String to) {
Cursor c = db.query(DRAFT_TABLE_NAME, null, "remoteContact LIKE \"" + to + "\"", null, null, null, "id ASC");
String message = null;
while (c.moveToNext()) {
try {
message = c.getString(c.getColumnIndex("message"));
} catch (Exception e) {
e.printStackTrace();
}
}
c.close();
return message;
}
public List<String> getDrafts() {
List<String> drafts = new ArrayList<String>();
Cursor c = db.query(DRAFT_TABLE_NAME, null, null, null, null, null, "id ASC");
while (c.moveToNext()) {
try {
String to = c.getString(c.getColumnIndex("remoteContact"));
drafts.add(to);
} catch (Exception e) {
e.printStackTrace();
}
}
c.close();
return drafts;
}
public List<ChatMessage> getMessages(String correspondent) {
List<ChatMessage> chatMessages = new ArrayList<ChatMessage>();
@ -167,27 +219,6 @@ public class ChatStorage {
return db.query(TABLE_NAME, null, "read LIKE " + NOT_READ, null, null, null, null).getCount();
}
class ChatHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 13;
private static final String DATABASE_NAME = "linphone-android";
ChatHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, localContact TEXT NOT NULL, remoteContact TEXT NOT NULL, direction INTEGER, message TEXT, image BLOB, time NUMERIC, read INTEGER, status INTEGER);");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME + ";");
onCreate(db);
}
}
public byte[] getRawImageFromMessage(int id) {
String[] columns = { "image" };
Cursor c = db.query(TABLE_NAME, columns, "id LIKE " + id + "", null, null, null, null);
@ -200,4 +231,27 @@ public class ChatStorage {
return null;
}
class ChatHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 14;
private static final String DATABASE_NAME = "linphone-android";
ChatHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, localContact TEXT NOT NULL, remoteContact TEXT NOT NULL, direction INTEGER, message TEXT, image BLOB, time NUMERIC, read INTEGER, status INTEGER);");
db.execSQL("CREATE TABLE " + DRAFT_TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, remoteContact TEXT NOT NULL, message TEXT);");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME + ";");
db.execSQL("DROP TABLE IF EXISTS " + DRAFT_TABLE_NAME + ";");
onCreate(db);
}
}
}

View file

@ -204,8 +204,9 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
statusFragment.getView().setVisibility(View.GONE);
findViewById(R.id.fragmentContainer).setPadding(0, 0, 0, 0);
}
private void showStatusBar() {
if (statusFragment == null) {
if (statusFragment == null || statusFragment.isVisible()) {
return;
}
@ -624,10 +625,14 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
return statusFragment;
}
public ArrayList<String> getChatList() {
public List<String> getChatList() {
return getChatStorage().getChatList();
}
public List<String> getDraftChatList() {
return getChatStorage().getDrafts();
}
public List<ChatMessage> getChatMessages(String correspondent) {
return getChatStorage().getMessages(correspondent);
}
@ -636,6 +641,10 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
getChatStorage().removeDiscussion(sipUri);
}
public void removeFromDrafts(String sipUri) {
getChatStorage().deleteDraft(sipUri);
}
@Override
public void onMessageReceived(LinphoneAddress from, LinphoneChatMessage message) {
String textMessage = message.getMessage();
@ -667,10 +676,12 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
}
public int onMessageSent(String to, String message) {
getChatStorage().deleteDraft(to);
return getChatStorage().saveMessage("", to, message);
}
public int onMessageSent(String to, Bitmap image, String imageURL) {
getChatStorage().deleteDraft(to);
return getChatStorage().saveMessage("", to, image);
}