diff --git a/res/layout/join_conference_dialog.xml b/res/layout/join_conference_dialog.xml
index 2a0e300a2..431bf59e7 100644
--- a/res/layout/join_conference_dialog.xml
+++ b/res/layout/join_conference_dialog.xml
@@ -41,6 +41,7 @@
android:layout_marginTop="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/save_as_bookmark" />
+ android:text="@string/save_as_bookmark"
+ android:checked="true" />
diff --git a/res/menu/conference_context.xml b/res/menu/conference_context.xml
new file mode 100644
index 000000000..fd898580a
--- /dev/null
+++ b/res/menu/conference_context.xml
@@ -0,0 +1,11 @@
+
+
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 417d838ef..9308bba11 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -267,4 +267,5 @@
Conference address
room@conference.example.com
Save as bookmark
+ Delete bookmark
\ No newline at end of file
diff --git a/src/eu/siacs/conversations/entities/Account.java b/src/eu/siacs/conversations/entities/Account.java
index a73d49f91..20abddcd0 100644
--- a/src/eu/siacs/conversations/entities/Account.java
+++ b/src/eu/siacs/conversations/entities/Account.java
@@ -1,6 +1,8 @@
package eu.siacs.conversations.entities;
import java.security.interfaces.DSAPublicKey;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Locale;
import net.java.otr4j.crypto.OtrCryptoEngineImpl;
@@ -67,6 +69,8 @@ public class Account extends AbstractEntity{
private String otrFingerprint;
private Roster roster = null;
+
+ private List bookmarks = new ArrayList();
public Account() {
this.uuid = "0";
@@ -297,4 +301,12 @@ public class Account extends AbstractEntity{
}
return this.roster;
}
+
+ public void setBookmarks(List bookmarks) {
+ this.bookmarks = bookmarks;
+ }
+
+ public List getBookmarks() {
+ return this.bookmarks;
+ }
}
diff --git a/src/eu/siacs/conversations/entities/Bookmark.java b/src/eu/siacs/conversations/entities/Bookmark.java
new file mode 100644
index 000000000..1b97c5730
--- /dev/null
+++ b/src/eu/siacs/conversations/entities/Bookmark.java
@@ -0,0 +1,94 @@
+package eu.siacs.conversations.entities;
+
+import java.util.Locale;
+
+import eu.siacs.conversations.xml.Element;
+
+public class Bookmark implements ListItem {
+
+ private Account account;
+ private String jid;
+ private String nick;
+ private String displayName;
+ private boolean autojoin;
+
+ public Bookmark(Account account) {
+ this.account = account;
+ }
+
+ public static Bookmark parse(Element element, Account account) {
+ Bookmark bookmark = new Bookmark(account);
+ bookmark.setJid(element.getAttribute("jid"));
+ bookmark.setDisplayName(element.getAttribute("name"));
+ String autojoin = element.getAttribute("autojoin");
+ if (autojoin!=null && (autojoin.equals("true")||autojoin.equals("1"))) {
+ bookmark.setAutojoin(true);
+ } else {
+ bookmark.setAutojoin(false);
+ }
+ Element nick = element.findChild("nick");
+ if (nick!=null) {
+ bookmark.setNick(nick.getContent());
+ }
+ return bookmark;
+ }
+
+ public void setAutojoin(boolean autojoin) {
+ this.autojoin = autojoin;
+ }
+
+ public void setDisplayName(String name) {
+ this.displayName = name;
+ }
+
+ public void setJid(String jid) {
+ this.jid = jid;
+ }
+
+ public void setNick(String nick) {
+ this.nick = nick;
+ }
+
+ @Override
+ public int compareTo(ListItem another) {
+ return this.getDisplayName().compareToIgnoreCase(another.getDisplayName());
+ }
+
+ @Override
+ public String getDisplayName() {
+ if (displayName!=null) {
+ return displayName;
+ } else {
+ return this.jid.split("@")[0];
+ }
+ }
+
+ @Override
+ public String getJid() {
+ return this.jid.toLowerCase(Locale.US);
+ }
+
+ public String getNick() {
+ return this.nick;
+ }
+
+ public boolean autojoin() {
+ return autojoin;
+ }
+
+ @Override
+ public String getProfilePhoto() {
+ return null;
+ }
+
+ public boolean match(String needle) {
+ return needle == null
+ || getJid().contains(needle.toLowerCase(Locale.US))
+ || getDisplayName().toLowerCase(Locale.US)
+ .contains(needle.toLowerCase(Locale.US));
+ }
+
+ public Account getAccount() {
+ return this.account;
+ }
+}
diff --git a/src/eu/siacs/conversations/entities/Conversation.java b/src/eu/siacs/conversations/entities/Conversation.java
index 23ab382f8..fbd87f3f6 100644
--- a/src/eu/siacs/conversations/entities/Conversation.java
+++ b/src/eu/siacs/conversations/entities/Conversation.java
@@ -64,6 +64,8 @@ public class Conversation extends AbstractEntity {
private boolean otrSessionNeedsStarting = false;
+ private Bookmark bookmark;
+
public Conversation(String name, Account account, String contactJid,
int mode) {
this(java.util.UUID.randomUUID().toString(), name, null, account
@@ -375,4 +377,8 @@ public class Conversation extends AbstractEntity {
public byte[] getSymmetricKey() {
return this.symmetricKey;
}
+
+ public void setBookmark(Bookmark bookmark) {
+ this.bookmark = bookmark;
+ }
}
diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java
index 0f90f725b..3fa263ab3 100644
--- a/src/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/eu/siacs/conversations/services/XmppConnectionService.java
@@ -20,6 +20,7 @@ import net.java.otr4j.session.Session;
import net.java.otr4j.session.SessionStatus;
import eu.siacs.conversations.crypto.PgpEngine;
import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Bookmark;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
@@ -245,9 +246,13 @@ public class XmppConnectionService extends Service {
return message;
}
- public Conversation findMuc(String name, Account account) {
+ public Conversation findMuc(Bookmark bookmark) {
+ return findMuc(bookmark.getJid(), bookmark.getAccount());
+ }
+
+ public Conversation findMuc(String jid, Account account) {
for (Conversation conversation : this.conversations) {
- if (conversation.getContactJid().split("/")[0].equals(name)
+ if (conversation.getContactJid().split("/")[0].equals(jid)
&& (conversation.getAccount() == account)) {
return conversation;
}
@@ -466,6 +471,7 @@ public class XmppConnectionService extends Service {
account.getRoster().clearPresences();
account.clearPresences(); // self presences
fetchRosterFromServer(account);
+ fetchBookmarks(account);
sendPresencePacket(account, mPresenceGenerator.sendPresence(account));
connectMultiModeConversations(account);
updateConversationUi();
@@ -660,6 +666,45 @@ public class XmppConnectionService extends Service {
}
});
}
+
+ public void fetchBookmarks(Account account) {
+ IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
+ Element query = iqPacket.query("jabber:iq:private");
+ query.addChild("storage", "storage:bookmarks");
+ OnIqPacketReceived callback = new OnIqPacketReceived() {
+
+ @Override
+ public void onIqPacketReceived(Account account, IqPacket packet) {
+ Element query = packet.query();
+ List bookmarks = new ArrayList();
+ Element storage = query.findChild("storage", "storage:bookmarks");
+ if (storage!=null) {
+ for(Element item : storage.getChildren()) {
+ if (item.getName().equals("conference")) {
+ Log.d(LOGTAG,item.toString());
+ Bookmark bookmark = Bookmark.parse(item,account);
+ bookmarks.add(bookmark);
+ if (bookmark.autojoin()) {
+ Log.d(LOGTAG,"has autojoin");
+ Conversation conversation = findMuc(bookmark);
+ if (conversation!=null) {
+ Log.d(LOGTAG,"conversation existed. adding bookmark");
+ conversation.setBookmark(bookmark);
+ } else {
+ Log.d(LOGTAG,"creating new conversation");
+ conversation = findOrCreateConversation(account, bookmark.getJid(), true);
+ conversation.setBookmark(bookmark);
+ }
+ }
+ }
+ }
+ }
+ account.setBookmarks(bookmarks);
+ }
+ };
+ sendIqPacket(account, iqPacket, callback);
+
+ }
private void mergePhoneContactsWithRoster() {
PhoneHelper.loadPhoneContacts(getApplicationContext(),
@@ -1297,6 +1342,10 @@ public class XmppConnectionService extends Service {
account.getXmppConnection().sendPresencePacket(packet);
}
+ public void sendIqPacket(Account account, IqPacket packet, OnIqPacketReceived callback) {
+ account.getXmppConnection().sendIqPacket(packet, callback);
+ }
+
public MessageGenerator getMessageGenerator() {
return this.mMessageGenerator;
}
diff --git a/src/eu/siacs/conversations/ui/StartConversation.java b/src/eu/siacs/conversations/ui/StartConversation.java
index b37d2d07e..99b3385cd 100644
--- a/src/eu/siacs/conversations/ui/StartConversation.java
+++ b/src/eu/siacs/conversations/ui/StartConversation.java
@@ -37,6 +37,7 @@ import android.widget.Spinner;
import android.widget.TextView;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Bookmark;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.ListItem;
@@ -63,6 +64,9 @@ public class StartConversation extends XmppActivity {
private List mKnownConferenceHosts;
private EditText mSearchEditText;
+
+ public int conference_context_id;
+ public int contact_context_id;
private TabListener mTabListener = new TabListener() {
@@ -115,7 +119,7 @@ public class StartConversation extends XmppActivity {
imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(),
InputMethodManager.HIDE_IMPLICIT_ONLY);
mSearchEditText.setText("");
- filterContacts(null);
+ filter(null);
return true;
}
};
@@ -123,7 +127,7 @@ public class StartConversation extends XmppActivity {
@Override
public void afterTextChanged(Editable editable) {
- filterContacts(editable.toString());
+ filter(editable.toString());
}
@Override
@@ -172,9 +176,19 @@ public class StartConversation extends XmppActivity {
mConferenceAdapter = new ListItemAdapter(conferences);
mConferenceListFragment.setListAdapter(mConferenceAdapter);
+ mConferenceListFragment.setContextMenu(R.menu.conference_context);
+ mConferenceListFragment.setOnListItemClickListener(new OnItemClickListener() {
+
+ @Override
+ public void onItemClick(AdapterView> arg0, View arg1,
+ int position, long arg3) {
+ openConversationForBookmark(position);
+ }
+ });
mContactsAdapter = new ListItemAdapter(contacts);
mContactsListFragment.setListAdapter(mContactsAdapter);
+ mContactsListFragment.setContextMenu(R.menu.contact_context);
mContactsListFragment
.setOnListItemClickListener(new OnItemClickListener() {
@@ -192,18 +206,35 @@ public class StartConversation extends XmppActivity {
Conversation conversation = xmppConnectionService
.findOrCreateConversation(contact.getAccount(),
contact.getJid(), false);
- switchToConversation(conversation, null, false);
+ switchToConversation(conversation);
+ }
+
+ protected void openConversationForContact() {
+ int position = contact_context_id;
+ openConversationForContact(position);
+ }
+
+ protected void openConversationForBookmark() {
+ openConversationForBookmark(conference_context_id);
+ }
+
+ protected void openConversationForBookmark(int position) {
+ Bookmark bookmark = (Bookmark) conferences.get(position);
+ Conversation conversation = xmppConnectionService.findOrCreateConversation(bookmark.getAccount(), bookmark.getJid(), true);
+ switchToConversation(conversation);
}
- protected void openDetailsForContact(int position) {
+ protected void openDetailsForContact() {
+ int position = contact_context_id;
Contact contact = (Contact) contacts.get(position);
switchToContactDetails(contact);
}
- protected void deleteContact(int position) {
+ protected void deleteContact() {
+ int position = contact_context_id;
Contact contact = (Contact) contacts.get(position);
xmppConnectionService.deleteContactOnServer(contact);
- filterContacts(mSearchEditText.getText().toString());
+ filter(mSearchEditText.getText().toString());
}
protected void showCreateContactDialog() {
@@ -339,9 +370,9 @@ public class StartConversation extends XmppActivity {
@Override
void onBackendConnected() {
if (mSearchEditText != null) {
- filterContacts(mSearchEditText.getText().toString());
+ filter(mSearchEditText.getText().toString());
} else {
- filterContacts(null);
+ filter(null);
}
this.mActivatedAccounts.clear();
for (Account account : xmppConnectionService.getAccounts()) {
@@ -353,6 +384,11 @@ public class StartConversation extends XmppActivity {
this.mKnownConferenceHosts = xmppConnectionService
.getKnownConferenceHosts();
}
+
+ protected void filter(String needle) {
+ this.filterContacts(needle);
+ this.filterConferences(needle);
+ }
protected void filterContacts(String needle) {
this.contacts.clear();
@@ -368,6 +404,21 @@ public class StartConversation extends XmppActivity {
Collections.sort(this.contacts);
mContactsAdapter.notifyDataSetChanged();
}
+
+ protected void filterConferences(String needle) {
+ this.conferences.clear();
+ for (Account account : xmppConnectionService.getAccounts()) {
+ if (account.getStatus() != Account.STATUS_DISABLED) {
+ for(Bookmark bookmark : account.getBookmarks()) {
+ if (bookmark.match(needle)) {
+ this.conferences.add(bookmark);
+ }
+ }
+ }
+ }
+ Collections.sort(this.conferences);
+ mConferenceAdapter.notifyDataSetChanged();
+ }
private void onTabChanged() {
invalidateOptionsMenu();
@@ -403,7 +454,11 @@ public class StartConversation extends XmppActivity {
public static class MyListFragment extends ListFragment {
private AdapterView.OnItemClickListener mOnItemClickListener;
- private int mContextPosition = -1;
+ private int mResContextMenu;
+
+ public void setContextMenu(int res) {
+ this.mResContextMenu = res;
+ }
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
@@ -426,10 +481,15 @@ public class StartConversation extends XmppActivity {
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
- getActivity().getMenuInflater().inflate(R.menu.contact_context,
+ StartConversation activity = (StartConversation) getActivity();
+ activity.getMenuInflater().inflate(mResContextMenu,
menu);
AdapterView.AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo;
- this.mContextPosition = acmi.position;
+ if (mResContextMenu == R.menu.conference_context) {
+ activity.conference_context_id = acmi.position;
+ } else {
+ activity.contact_context_id = acmi.position;
+ }
}
@Override
@@ -437,13 +497,16 @@ public class StartConversation extends XmppActivity {
StartConversation activity = (StartConversation) getActivity();
switch (item.getItemId()) {
case R.id.context_start_conversation:
- activity.openConversationForContact(mContextPosition);
+ activity.openConversationForContact();
break;
case R.id.context_contact_details:
- activity.openDetailsForContact(mContextPosition);
+ activity.openDetailsForContact();
break;
case R.id.context_delete_contact:
- activity.deleteContact(mContextPosition);
+ activity.deleteContact();
+ break;
+ case R.id.context_join_conference:
+ activity.openConversationForBookmark();
break;
}
return true;