diff options
Diffstat (limited to '')
43 files changed, 600 insertions, 83 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 4feb3a3d..e242c3e3 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -48,6 +48,12 @@ <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> + <activity + android:name="eu.siacs.conversations.ui.StartConversation" + android:label="@string/title_activity_start_conversation" + android:parentActivityName="eu.siacs.conversations.ui.ConversationActivity" + android:logo="@drawable/ic_activity" + ></activity> <activity android:name="eu.siacs.conversations.ui.SettingsActivity" android:label="@string/title_activity_settings" diff --git a/libs/android-support-v13.jar b/libs/android-support-v13.jar Binary files differnew file mode 100644 index 00000000..cd47212b --- /dev/null +++ b/libs/android-support-v13.jar diff --git a/libs/android-support-v4.jar b/libs/android-support-v4.jar Binary files differdeleted file mode 100644 index 9056828a..00000000 --- a/libs/android-support-v4.jar +++ /dev/null diff --git a/res/drawable-hdpi/tab_selected_conversations.9.png b/res/drawable-hdpi/tab_selected_conversations.9.png Binary files differnew file mode 100644 index 00000000..b8f44c21 --- /dev/null +++ b/res/drawable-hdpi/tab_selected_conversations.9.png diff --git a/res/drawable-hdpi/tab_selected_focused_conversations.9.png b/res/drawable-hdpi/tab_selected_focused_conversations.9.png Binary files differnew file mode 100644 index 00000000..5512dbd3 --- /dev/null +++ b/res/drawable-hdpi/tab_selected_focused_conversations.9.png diff --git a/res/drawable-hdpi/tab_selected_pressed_conversations.9.png b/res/drawable-hdpi/tab_selected_pressed_conversations.9.png Binary files differnew file mode 100644 index 00000000..e5f1df22 --- /dev/null +++ b/res/drawable-hdpi/tab_selected_pressed_conversations.9.png diff --git a/res/drawable-hdpi/tab_unselected_conversations.9.png b/res/drawable-hdpi/tab_unselected_conversations.9.png Binary files differnew file mode 100644 index 00000000..7cd46d63 --- /dev/null +++ b/res/drawable-hdpi/tab_unselected_conversations.9.png diff --git a/res/drawable-hdpi/tab_unselected_focused_conversations.9.png b/res/drawable-hdpi/tab_unselected_focused_conversations.9.png Binary files differnew file mode 100644 index 00000000..438ecdd8 --- /dev/null +++ b/res/drawable-hdpi/tab_unselected_focused_conversations.9.png diff --git a/res/drawable-hdpi/tab_unselected_pressed_conversations.9.png b/res/drawable-hdpi/tab_unselected_pressed_conversations.9.png Binary files differnew file mode 100644 index 00000000..4f18a95a --- /dev/null +++ b/res/drawable-hdpi/tab_unselected_pressed_conversations.9.png diff --git a/res/drawable-mdpi/tab_selected_conversations.9.png b/res/drawable-mdpi/tab_selected_conversations.9.png Binary files differnew file mode 100644 index 00000000..09d42dc8 --- /dev/null +++ b/res/drawable-mdpi/tab_selected_conversations.9.png diff --git a/res/drawable-mdpi/tab_selected_focused_conversations.9.png b/res/drawable-mdpi/tab_selected_focused_conversations.9.png Binary files differnew file mode 100644 index 00000000..20af01de --- /dev/null +++ b/res/drawable-mdpi/tab_selected_focused_conversations.9.png diff --git a/res/drawable-mdpi/tab_selected_pressed_conversations.9.png b/res/drawable-mdpi/tab_selected_pressed_conversations.9.png Binary files differnew file mode 100644 index 00000000..13a878be --- /dev/null +++ b/res/drawable-mdpi/tab_selected_pressed_conversations.9.png diff --git a/res/drawable-mdpi/tab_unselected_conversations.9.png b/res/drawable-mdpi/tab_unselected_conversations.9.png Binary files differnew file mode 100644 index 00000000..ad2dbae9 --- /dev/null +++ b/res/drawable-mdpi/tab_unselected_conversations.9.png diff --git a/res/drawable-mdpi/tab_unselected_focused_conversations.9.png b/res/drawable-mdpi/tab_unselected_focused_conversations.9.png Binary files differnew file mode 100644 index 00000000..dfff5ac8 --- /dev/null +++ b/res/drawable-mdpi/tab_unselected_focused_conversations.9.png diff --git a/res/drawable-mdpi/tab_unselected_pressed_conversations.9.png b/res/drawable-mdpi/tab_unselected_pressed_conversations.9.png Binary files differnew file mode 100644 index 00000000..4365d178 --- /dev/null +++ b/res/drawable-mdpi/tab_unselected_pressed_conversations.9.png diff --git a/res/drawable-xhdpi/tab_selected_conversations.9.png b/res/drawable-xhdpi/tab_selected_conversations.9.png Binary files differnew file mode 100644 index 00000000..34eb4ec0 --- /dev/null +++ b/res/drawable-xhdpi/tab_selected_conversations.9.png diff --git a/res/drawable-xhdpi/tab_selected_focused_conversations.9.png b/res/drawable-xhdpi/tab_selected_focused_conversations.9.png Binary files differnew file mode 100644 index 00000000..3155ef69 --- /dev/null +++ b/res/drawable-xhdpi/tab_selected_focused_conversations.9.png diff --git a/res/drawable-xhdpi/tab_selected_pressed_conversations.9.png b/res/drawable-xhdpi/tab_selected_pressed_conversations.9.png Binary files differnew file mode 100644 index 00000000..5c2440e4 --- /dev/null +++ b/res/drawable-xhdpi/tab_selected_pressed_conversations.9.png diff --git a/res/drawable-xhdpi/tab_unselected_conversations.9.png b/res/drawable-xhdpi/tab_unselected_conversations.9.png Binary files differnew file mode 100644 index 00000000..e9ab742e --- /dev/null +++ b/res/drawable-xhdpi/tab_unselected_conversations.9.png diff --git a/res/drawable-xhdpi/tab_unselected_focused_conversations.9.png b/res/drawable-xhdpi/tab_unselected_focused_conversations.9.png Binary files differnew file mode 100644 index 00000000..42a2191e --- /dev/null +++ b/res/drawable-xhdpi/tab_unselected_focused_conversations.9.png diff --git a/res/drawable-xhdpi/tab_unselected_pressed_conversations.9.png b/res/drawable-xhdpi/tab_unselected_pressed_conversations.9.png Binary files differnew file mode 100644 index 00000000..a5a2c25e --- /dev/null +++ b/res/drawable-xhdpi/tab_unselected_pressed_conversations.9.png diff --git a/res/drawable-xxhdpi/tab_selected_conversations.9.png b/res/drawable-xxhdpi/tab_selected_conversations.9.png Binary files differnew file mode 100644 index 00000000..e4439e7c --- /dev/null +++ b/res/drawable-xxhdpi/tab_selected_conversations.9.png diff --git a/res/drawable-xxhdpi/tab_selected_focused_conversations.9.png b/res/drawable-xxhdpi/tab_selected_focused_conversations.9.png Binary files differnew file mode 100644 index 00000000..dd2ded89 --- /dev/null +++ b/res/drawable-xxhdpi/tab_selected_focused_conversations.9.png diff --git a/res/drawable-xxhdpi/tab_selected_pressed_conversations.9.png b/res/drawable-xxhdpi/tab_selected_pressed_conversations.9.png Binary files differnew file mode 100644 index 00000000..58c8a576 --- /dev/null +++ b/res/drawable-xxhdpi/tab_selected_pressed_conversations.9.png diff --git a/res/drawable-xxhdpi/tab_unselected_conversations.9.png b/res/drawable-xxhdpi/tab_unselected_conversations.9.png Binary files differnew file mode 100644 index 00000000..566062f0 --- /dev/null +++ b/res/drawable-xxhdpi/tab_unselected_conversations.9.png diff --git a/res/drawable-xxhdpi/tab_unselected_focused_conversations.9.png b/res/drawable-xxhdpi/tab_unselected_focused_conversations.9.png Binary files differnew file mode 100644 index 00000000..432e68c4 --- /dev/null +++ b/res/drawable-xxhdpi/tab_unselected_focused_conversations.9.png diff --git a/res/drawable-xxhdpi/tab_unselected_pressed_conversations.9.png b/res/drawable-xxhdpi/tab_unselected_pressed_conversations.9.png Binary files differnew file mode 100644 index 00000000..8dd01d5c --- /dev/null +++ b/res/drawable-xxhdpi/tab_unselected_pressed_conversations.9.png diff --git a/res/drawable/actionbar_tab_indicator.xml b/res/drawable/actionbar_tab_indicator.xml new file mode 100644 index 00000000..102b75d8 --- /dev/null +++ b/res/drawable/actionbar_tab_indicator.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- Non focused states --> + <item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@android:color/transparent" /> + <item android:state_focused="false" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/tab_selected_conversations" /> + + <!-- Focused states --> + <item android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/tab_unselected_focused_conversations" /> + <item android:state_focused="true" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/tab_selected_focused_conversations" /> + + <!-- Pressed --> + <!-- Non focused states --> + <item android:state_focused="false" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/tab_unselected_pressed_conversations" /> + <item android:state_focused="false" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed_conversations" /> + + <!-- Focused states --> + <item android:state_focused="true" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/tab_unselected_pressed_conversations" /> + <item android:state_focused="true" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed_conversations" /> + </selector>
\ No newline at end of file diff --git a/res/drawable/snackbar.xml b/res/drawable/snackbar.xml new file mode 100644 index 00000000..5f5dc430 --- /dev/null +++ b/res/drawable/snackbar.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="@color/darkbackground"/> + <corners android:radius="8dip"/> + <padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" /> +</shape>
\ No newline at end of file diff --git a/res/layout/activity_start_conversation.xml b/res/layout/activity_start_conversation.xml new file mode 100644 index 00000000..9c757540 --- /dev/null +++ b/res/layout/activity_start_conversation.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/start_conversation_view_pager" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@color/primarybackground"> + +</android.support.v4.view.ViewPager>
\ No newline at end of file diff --git a/res/layout/create_contact_dialog.xml b/res/layout/create_contact_dialog.xml new file mode 100644 index 00000000..45007ef2 --- /dev/null +++ b/res/layout/create_contact_dialog.xml @@ -0,0 +1,37 @@ +<?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:padding="16dp"> + + <TextView + android:id="@+id/your_account" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="14sp" + android:textColor="@color/primarytext" + android:text="@string/your_account" /> + <Spinner + android:id="@+id/account" + android:layout_width="fill_parent" + android:layout_height="wrap_content" /> + + <TextView + android:id="@+id/jabber_id" + android:paddingTop="8dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="14sp" + android:textColor="@color/primarytext" + android:text="@string/account_settings_jabber_id" /> + + <EditText + android:id="@+id/jid" + android:paddingTop="8dp" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:inputType="textEmailAddress" + android:hint="@string/account_settings_example_jabber_id" + /> +</LinearLayout> diff --git a/res/layout/fragment_conversation.xml b/res/layout/fragment_conversation.xml index 4605889d..b712c304 100644 --- a/res/layout/fragment_conversation.xml +++ b/res/layout/fragment_conversation.xml @@ -5,13 +5,31 @@ android:layout_height="match_parent" android:background="@color/secondarybackground" > - <RelativeLayout - android:id="@+id/textsend" + + + <ListView + android:id="@+id/messages_view" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:layout_alignParentBottom="true" + android:layout_above="@+id/snackbar" android:layout_alignParentLeft="true" - android:background="@color/primarybackground" > + android:layout_alignParentTop="true" + android:background="@color/secondarybackground" + android:divider="@null" + android:dividerHeight="0dp" + android:listSelector="@android:color/transparent" + android:stackFromBottom="true" + android:transcriptMode="normal" + tools:listitem="@layout/message_sent" > + </ListView> + + <RelativeLayout + android:id="@+id/textsend" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:layout_alignParentLeft="true" + android:background="@color/primarybackground" > <EditText android:id="@+id/textinput" @@ -43,53 +61,42 @@ android:src="@drawable/ic_action_send_now" /> </RelativeLayout> - <ListView - android:id="@+id/messages_view" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_above="@+id/textsend" - android:layout_alignParentLeft="true" - android:layout_below="@+id/snackbar" - android:background="@color/secondarybackground" - android:divider="@null" - android:dividerHeight="0dp" - android:listSelector="@android:color/transparent" - android:stackFromBottom="true" - android:transcriptMode="normal" - tools:listitem="@layout/message_sent" > - </ListView> + <RelativeLayout + android:id="@+id/snackbar" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_above="@+id/textsend" + android:background="@drawable/snackbar" + android:minHeight="48dp" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" + android:layout_marginBottom="4dp" + android:visibility="gone" > - <RelativeLayout - android:id="@+id/snackbar" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:minHeight="48dp" - android:background="@color/darkbackground" - android:visibility="gone"> + <TextView + android:id="@+id/snackbar_message" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentLeft="true" + android:layout_centerVertical="true" + android:paddingLeft="24dp" + android:textColor="@color/ondarktext" + android:textSize="14sp" /> - <TextView - android:id="@+id/snackbar_message" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentLeft="true" - android:layout_centerVertical="true" - android:textSize="14sp" - android:textColor="@color/ondarktext" - android:paddingLeft="24dp"/> - <TextView - android:id="@+id/snackbar_action" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentRight="true" - android:layout_centerVertical="true" - android:textSize="14sp" - android:textColor="@color/ondarktext" - android:textStyle="bold" - android:textAllCaps="true" - android:paddingLeft="24dp" - android:paddingRight="24dp" - android:paddingTop="18dp" - android:paddingBottom="18dp"/> - </RelativeLayout> + <TextView + android:id="@+id/snackbar_action" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:layout_centerVertical="true" + android:paddingBottom="16dp" + android:paddingLeft="24dp" + android:paddingRight="24dp" + android:paddingTop="16dp" + android:textAllCaps="true" + android:textColor="@color/ondarktext" + android:textSize="14sp" + android:textStyle="bold" /> + </RelativeLayout> </RelativeLayout>
\ No newline at end of file diff --git a/res/menu/contact_context.xml b/res/menu/contact_context.xml new file mode 100644 index 00000000..11ac7d7c --- /dev/null +++ b/res/menu/contact_context.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android" > + + <item + android:id="@+id/context_start_conversation" + android:title="@string/start_conversation"/> + <item + android:id="@+id/context_contact_details" + android:title="@string/view_contact_details"/> + <item + android:id="@+id/context_delete_contact" + android:title="@string/delete_contact"/> + +</menu>
\ No newline at end of file diff --git a/res/menu/start_conversation.xml b/res/menu/start_conversation.xml new file mode 100644 index 00000000..12109d7b --- /dev/null +++ b/res/menu/start_conversation.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android" > + + <item + android:id="@+id/action_search" + android:actionViewClass="android.widget.SearchView" + android:icon="@drawable/ic_action_search" + android:showAsAction="collapseActionView|always" + android:title="@string/search"/> + + <item + android:id="@+id/action_create_contact" + android:icon="@drawable/ic_action_add_person" + android:showAsAction="always" + android:title="@string/create_contact"/> + <item + android:id="@+id/action_create_conference" + android:icon="@drawable/ic_action_add_group" + android:showAsAction="always" + android:title="@string/create_conference"/> + + <item + android:id="@+id/action_accounts" + android:orderInCategory="90" + android:showAsAction="never" + android:title="@string/action_accounts"/> + <item + android:id="@+id/action_settings" + android:orderInCategory="100" + android:showAsAction="never" + android:title="@string/action_settings"/> + +</menu>
\ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 80bd2052..ebfaaa17 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -21,6 +21,7 @@ <string name="title_activity_contact_details">Contact Details</string> <string name="title_activity_conversations">Conversations</string> <string name="title_activity_sharewith">Share with Conversation</string> + <string name="title_activity_start_conversation">Start Conversation</string> <string name="just_now">just now</string> <string name="minute_ago">1 min ago</string> <string name="minutes_ago">%d mins ago</string> @@ -200,10 +201,10 @@ <string name="mgmt_account_account_offline">Account is offline</string> <string name="attach_record_voice">Record voice</string> <string name="account_settings">Account Settings</string> - <string name="account_settings_jabber_id">Jabber ID:</string> - <string name="account_settings_password">Password:</string> + <string name="account_settings_jabber_id">Jabber ID</string> + <string name="account_settings_password">Password</string> <string name="account_settings_example_jabber_id">username@example.com</string> - <string name="account_settings_confirm_password">Confirm password:</string> + <string name="account_settings_confirm_password">Confirm password</string> <string name="password">Password</string> <string name="confirm_password">Confirm password</string> <string name="passwords_do_not_match">Passwords do not match</string> @@ -254,4 +255,12 @@ <string name="otr_fingerprint">OTR fingerprint</string> <string name="verify">Verify</string> <string name="decrypt">Decrypt</string> + <string name="conferences">Conferences</string> + <string name="search">Search</string> + <string name="create_contact">Create Contact</string> + <string name="create_conference">Create Conference</string> + <string name="delete_contact">Delete Contact</string> + <string name="view_contact_details">View contact details</string> + <string name="create">Create</string> + <string name="contact_already_exists">The contact already exists</string> </resources>
\ No newline at end of file diff --git a/res/values/themes.xml b/res/values/themes.xml index 0191d302..0c4ddc39 100644 --- a/res/values/themes.xml +++ b/res/values/themes.xml @@ -1,23 +1,26 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <style name="ConversationsTheme" - parent="@android:style/Theme.Holo.Light.DarkActionBar"> + + <style name="ConversationsTheme" parent="@android:style/Theme.Holo.Light.DarkActionBar"> <item name="android:actionBarStyle">@style/ConversationsActionBar</item> <item name="android:actionBarWidgetTheme">@style/ConversationsActionBarWidget</item> + <item name="android:actionBarTabStyle">@style/ConversationsActionBarTabs</item> </style> - <style name="ConversationsActionBar" - parent="@android:style/Widget.Holo.Light.ActionBar.Solid.Inverse"> + <style name="ConversationsActionBar" parent="@android:style/Widget.Holo.Light.ActionBar.Solid.Inverse"> <item name="android:background">#259b24</item> + <item name="android:backgroundStacked">#0a7e07</item> <item name="android:displayOptions">showHome|homeAsUp|showTitle</item> - <item name="android:icon">@android:color/transparent</item> + <item name="android:icon">@android:color/transparent</item> + </style> + + <style name="ConversationsActionBarWidget" parent="android:Theme.Holo.Light"> + <item name="android:popupMenuStyle">@android:style/Widget.Holo.Light.PopupMenu</item> + <item name="android:dropDownListViewStyle">@android:style/Widget.Holo.Light.ListView.DropDown</item> </style> - - <style name="ConversationsActionBarWidget" - parent="android:Theme.Holo.Light"> - <item name="android:popupMenuStyle">@android:style/Widget.Holo.Light.PopupMenu</item> - <item name="android:dropDownListViewStyle">@android:style/Widget.Holo.Light.ListView.DropDown</item> -</style> -</resources> + <style name="ConversationsActionBarTabs" parent="@android:style/Widget.Holo.ActionBar.TabView"> + <item name="android:background">@drawable/actionbar_tab_indicator</item> + </style> +</resources>
\ No newline at end of file diff --git a/src/eu/siacs/conversations/entities/Contact.java b/src/eu/siacs/conversations/entities/Contact.java index 50d7af8b..59e0fa12 100644 --- a/src/eu/siacs/conversations/entities/Contact.java +++ b/src/eu/siacs/conversations/entities/Contact.java @@ -12,7 +12,7 @@ import eu.siacs.conversations.xml.Element; import android.content.ContentValues; import android.database.Cursor; -public class Contact { +public class Contact implements ListItem { public static final String TABLENAME = "contacts"; public static final String SYSTEMNAME = "systemname"; @@ -37,7 +37,7 @@ public class Contact { protected Account account; protected boolean inRoster = true; - + public Lastseen lastseen = new Lastseen(); public Contact(String account, String systemName, String serverName, @@ -83,8 +83,10 @@ public class Contact { } public boolean match(String needle) { - return (jid.toLowerCase().contains(needle.toLowerCase()) || (getDisplayName() - .toLowerCase().contains(needle.toLowerCase()))); + return needle == null + || jid.contains(needle.toLowerCase()) + || getDisplayName().toLowerCase() + .contains(needle.toLowerCase()); } public ContentValues getContentValues() { @@ -142,8 +144,8 @@ public class Contact { || domainParts[0].equals("room") || domainParts[0].equals("muc") || domainParts[0].equals("chat") - || domainParts[0].equals("sala") - || domainParts[0].equals("salas")); + || domainParts[0].equals("sala") || domainParts[0] + .equals("salas")); } } } @@ -308,9 +310,14 @@ public class Contact { public static final int DIRTY_PUSH = 6; public static final int DIRTY_DELETE = 7; } - + public class Lastseen { public long time = 0; public String presence = null; } + + @Override + public int compareTo(ListItem another) { + return this.getDisplayName().compareToIgnoreCase(another.getDisplayName()); + } } diff --git a/src/eu/siacs/conversations/entities/ListItem.java b/src/eu/siacs/conversations/entities/ListItem.java new file mode 100644 index 00000000..ba47dff2 --- /dev/null +++ b/src/eu/siacs/conversations/entities/ListItem.java @@ -0,0 +1,7 @@ +package eu.siacs.conversations.entities; + +public interface ListItem extends Comparable<ListItem> { + public String getDisplayName(); + public String getJid(); + public String getProfilePhoto(); +} diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java index 3db52753..9993dd67 100644 --- a/src/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/eu/siacs/conversations/services/XmppConnectionService.java @@ -1282,6 +1282,7 @@ public class XmppConnectionService extends Service { public void deleteContactOnServer(Contact contact) { contact.resetOption(Contact.Options.DIRTY_PUSH); + contact.setOption(Contact.Options.DIRTY_DELETE); Account account = contact.getAccount(); if (account.getStatus() == Account.STATUS_ONLINE) { IqPacket iq = new IqPacket(IqPacket.TYPE_SET); @@ -1290,8 +1291,6 @@ public class XmppConnectionService extends Service { item.setAttribute("subscription", "remove"); account.getXmppConnection().sendIqPacket(iq, null); contact.resetOption(Contact.Options.DIRTY_DELETE); - } else { - contact.setOption(Contact.Options.DIRTY_DELETE); } } diff --git a/src/eu/siacs/conversations/ui/ConversationActivity.java b/src/eu/siacs/conversations/ui/ConversationActivity.java index c11e1d65..1f3ab2fb 100644 --- a/src/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/eu/siacs/conversations/ui/ConversationActivity.java @@ -488,7 +488,7 @@ public class ConversationActivity extends XmppActivity { attachFilePopup.show(); break; case R.id.action_add: - startActivity(new Intent(this, ContactsActivity.class)); + startActivity(new Intent(this, StartConversation.class)); break; case R.id.action_archive: this.endConversation(getSelectedConversation()); @@ -496,12 +496,7 @@ public class ConversationActivity extends XmppActivity { case R.id.action_contact_details: Contact contact = this.getSelectedConversation().getContact(); if (contact.showInRoster()) { - Intent intent = new Intent(this, ContactDetailsActivity.class); - intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT); - intent.putExtra("account", this.getSelectedConversation() - .getAccount().getJid()); - intent.putExtra("contact", contact.getJid()); - startActivity(intent); + switchToContactDetails(contact); } else { showAddToRosterDialog(getSelectedConversation()); } diff --git a/src/eu/siacs/conversations/ui/StartConversation.java b/src/eu/siacs/conversations/ui/StartConversation.java new file mode 100644 index 00000000..880b4a9b --- /dev/null +++ b/src/eu/siacs/conversations/ui/StartConversation.java @@ -0,0 +1,359 @@ +package eu.siacs.conversations.ui; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import android.app.ActionBar; +import android.app.ActionBar.Tab; +import android.app.ActionBar.TabListener; +import android.app.AlertDialog; +import android.app.Fragment; +import android.app.FragmentTransaction; +import android.app.ListFragment; +import android.content.Context; +import android.content.DialogInterface; +import android.database.DataSetObserver; +import android.graphics.Color; +import android.os.Bundle; +import android.support.v13.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.AdapterContextMenuInfo; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ArrayAdapter; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.SearchView; +import android.widget.SpinnerAdapter; +import android.widget.SearchView.OnQueryTextListener; +import android.widget.Spinner; +import android.widget.TextView; +import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.entities.Contact; +import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.ListItem; +import eu.siacs.conversations.utils.UIHelper; +import eu.siacs.conversations.utils.Validator; + +public class StartConversation extends XmppActivity { + + private Tab mContactsTab; + private Tab mConferencesTab; + private ViewPager mViewPager; + private SearchView mSearchView; + + private MyListFragment mContactsListFragment = new MyListFragment(); + private List<ListItem> contacts = new ArrayList<ListItem>(); + private ArrayAdapter<ListItem> mContactsAdapter; + + private MyListFragment mConferenceListFragment = new MyListFragment(); + private List<ListItem> conferences = new ArrayList<ListItem>(); + private ArrayAdapter<ListItem> mConferenceAdapter; + + private List<String> mActivatedAccounts = new ArrayList<String>(); + + private TabListener mTabListener = new TabListener() { + + @Override + public void onTabUnselected(Tab tab, FragmentTransaction ft) { + return; + } + + @Override + public void onTabSelected(Tab tab, FragmentTransaction ft) { + mViewPager.setCurrentItem(tab.getPosition()); + onTabChanged(); + } + + @Override + public void onTabReselected(Tab tab, FragmentTransaction ft) { + return; + } + }; + + private ViewPager.SimpleOnPageChangeListener mOnPageChangeListener = new ViewPager.SimpleOnPageChangeListener() { + @Override + public void onPageSelected(int position) { + getActionBar().setSelectedNavigationItem(position); + onTabChanged(); + } + }; + private OnQueryTextListener mOnQueryTextListener = new OnQueryTextListener() { + + @Override + public boolean onQueryTextSubmit(String query) { + return true; + } + + @Override + public boolean onQueryTextChange(String newText) { + filterContacts(newText); + return true; + } + }; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_start_conversation); + mViewPager = (ViewPager) findViewById(R.id.start_conversation_view_pager); + ActionBar actionBar = getActionBar(); + actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + + mContactsTab = actionBar.newTab().setText(R.string.contacts) + .setTabListener(mTabListener); + mConferencesTab = actionBar.newTab().setText(R.string.conferences) + .setTabListener(mTabListener); + actionBar.addTab(mContactsTab); + actionBar.addTab(mConferencesTab); + + mViewPager.setOnPageChangeListener(mOnPageChangeListener); + mViewPager.setAdapter(new FragmentPagerAdapter(getFragmentManager()) { + + @Override + public int getCount() { + return 2; + } + + @Override + public Fragment getItem(int position) { + if (position == 0) { + return mContactsListFragment; + } else { + return mConferenceListFragment; + } + } + }); + + mConferenceAdapter = new ListItemAdapter(conferences); + mConferenceListFragment.setListAdapter(mConferenceAdapter); + + mContactsAdapter = new ListItemAdapter(contacts); + mContactsListFragment.setListAdapter(mContactsAdapter); + mContactsListFragment + .setOnListItemClickListener(new OnItemClickListener() { + + @Override + public void onItemClick(AdapterView<?> arg0, View arg1, + int position, long arg3) { + openConversationForContact(position); + } + }); + + } + + protected void openConversationForContact(int position) { + Contact contact = (Contact) contacts.get(position); + Conversation conversation = xmppConnectionService + .findOrCreateConversation(contact.getAccount(), + contact.getJid(), false); + switchToConversation(conversation, null, false); + } + + protected void openDetailsForContact(int position) { + Contact contact = (Contact) contacts.get(position); + switchToContactDetails(contact); + } + + protected void deleteContact(int position) { + Contact contact = (Contact) contacts.get(position); + xmppConnectionService.deleteContactOnServer(contact); + filterContacts(null); + } + + protected void showCreateContactDialog() { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.create_contact); + View dialogView = getLayoutInflater().inflate(R.layout.create_contact_dialog, null); + final Spinner spinner = (Spinner) dialogView.findViewById(R.id.account); + final EditText jid = (EditText) dialogView.findViewById(R.id.jid); + populateAccountSpinner(spinner); + builder.setView(dialogView); + builder.setNegativeButton(R.string.cancel, null); + builder.setPositiveButton(R.string.create, null); + final AlertDialog dialog = builder.create(); + dialog.show(); + dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + if (Validator.isValidJid(jid.getText().toString())) { + String accountJid = (String) spinner.getSelectedItem(); + String contactJid = jid.getText().toString(); + Account account = xmppConnectionService.findAccountByJid(accountJid); + Contact contact = account.getRoster().getContact(contactJid); + if (contact.showInRoster()) { + jid.setError(getString(R.string.contact_already_exists)); + } else { + xmppConnectionService.createContact(contact); + switchToConversation(contact); + dialog.dismiss(); + } + } else { + jid.setError(getString(R.string.invalid_jid)); + } + } + }); + + } + + protected void switchToConversation(Contact contact) { + Conversation conversation = xmppConnectionService.findOrCreateConversation(contact.getAccount(), contact.getJid(), false); + switchToConversation(conversation, null, false); + } + + private void populateAccountSpinner(Spinner spinner) { + ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, mActivatedAccounts); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spinner.setAdapter(adapter); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.start_conversation, menu); + MenuItem menuCreateContact = (MenuItem) menu + .findItem(R.id.action_create_contact); + MenuItem menuCreateConference = (MenuItem) menu + .findItem(R.id.action_create_conference); + MenuItem menuSearch = (MenuItem) menu.findItem(R.id.action_search); + if (getActionBar().getSelectedNavigationIndex() == 0) { + menuCreateConference.setVisible(false); + } else { + menuCreateContact.setVisible(false); + } + mSearchView = (SearchView) menuSearch.getActionView(); + int id = mSearchView.getContext().getResources() + .getIdentifier("android:id/search_src_text", null, null); + TextView textView = (TextView) mSearchView.findViewById(id); + textView.setTextColor(Color.WHITE); + mSearchView.setOnQueryTextListener(this.mOnQueryTextListener); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_create_contact: + showCreateContactDialog(); + break; + } + return super.onOptionsItemSelected(item); + } + + @Override + void onBackendConnected() { + filterContacts(null); + this.mActivatedAccounts.clear(); + for (Account account : xmppConnectionService.getAccounts()) { + if (account.getStatus() != Account.STATUS_DISABLED) { + this.mActivatedAccounts.add(account.getJid()); + } + } + } + + protected void filterContacts(String needle) { + this.contacts.clear(); + for (Account account : xmppConnectionService.getAccounts()) { + if (account.getStatus() != Account.STATUS_DISABLED) { + for (Contact contact : account.getRoster().getContacts()) { + if (contact.showInRoster() && contact.match(needle)) { + this.contacts.add(contact); + } + } + } + } + Collections.sort(this.contacts); + mContactsAdapter.notifyDataSetChanged(); + } + + private void onTabChanged() { + invalidateOptionsMenu(); + } + + private class ListItemAdapter extends ArrayAdapter<ListItem> { + + public ListItemAdapter(List<ListItem> objects) { + super(getApplicationContext(), 0, objects); + } + + @Override + public View getView(int position, View view, ViewGroup parent) { + LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); + ListItem item = getItem(position); + if (view == null) { + view = (View) inflater.inflate(R.layout.contact, null); + } + TextView name = (TextView) view + .findViewById(R.id.contact_display_name); + TextView jid = (TextView) view.findViewById(R.id.contact_jid); + ImageView picture = (ImageView) view + .findViewById(R.id.contact_photo); + + jid.setText(item.getJid()); + name.setText(item.getDisplayName()); + picture.setImageBitmap(UIHelper.getContactPicture(item, 48, + this.getContext(), false)); + return view; + } + + } + + public static class MyListFragment extends ListFragment { + private AdapterView.OnItemClickListener mOnItemClickListener; + private int mContextPosition = -1; + + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + if (mOnItemClickListener != null) { + mOnItemClickListener.onItemClick(l, v, position, id); + } + } + + public void setOnListItemClickListener(AdapterView.OnItemClickListener l) { + this.mOnItemClickListener = l; + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + registerForContextMenu(getListView()); + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenuInfo menuInfo) { + super.onCreateContextMenu(menu, v, menuInfo); + getActivity().getMenuInflater().inflate(R.menu.contact_context, + menu); + AdapterView.AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo; + this.mContextPosition = acmi.position; + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + StartConversation activity = (StartConversation) getActivity(); + switch(item.getItemId()) { + case R.id.context_start_conversation: + activity.openConversationForContact(mContextPosition); + break; + case R.id.context_contact_details: + activity.openDetailsForContact(mContextPosition); + break; + case R.id.context_delete_contact: + activity.deleteContact(mContextPosition); + break; + } + return true; + } + } +} diff --git a/src/eu/siacs/conversations/ui/XmppActivity.java b/src/eu/siacs/conversations/ui/XmppActivity.java index c95cbfec..96278a6d 100644 --- a/src/eu/siacs/conversations/ui/XmppActivity.java +++ b/src/eu/siacs/conversations/ui/XmppActivity.java @@ -170,6 +170,14 @@ public abstract class XmppActivity extends Activity { } startActivity(viewConversationIntent); } + + public void switchToContactDetails(Contact contact) { + Intent intent = new Intent(this, ContactDetailsActivity.class); + intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT); + intent.putExtra("account", contact.getAccount().getJid()); + intent.putExtra("contact", contact.getJid()); + startActivity(intent); + } protected void announcePgp(Account account, final Conversation conversation) { xmppConnectionService.getPgpEngine().generateSignature(account, diff --git a/src/eu/siacs/conversations/utils/UIHelper.java b/src/eu/siacs/conversations/utils/UIHelper.java index eeefa591..9fd16c43 100644 --- a/src/eu/siacs/conversations/utils/UIHelper.java +++ b/src/eu/siacs/conversations/utils/UIHelper.java @@ -13,11 +13,11 @@ import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.ListItem; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.MucOptions.User; import eu.siacs.conversations.ui.ConversationActivity; import eu.siacs.conversations.ui.ManageAccountActivity; - import android.app.Activity; import android.app.AlertDialog; import android.app.Notification; @@ -239,7 +239,7 @@ public class UIHelper { } } - public static Bitmap getContactPicture(Contact contact, int dpSize, + public static Bitmap getContactPicture(ListItem contact, int dpSize, Context context, boolean notification) { String uri = contact.getProfilePhoto(); if (uri == null) { |