Commit e6b453db authored by Grigory Fedorov's avatar Grigory Fedorov

Merge branch 'feature/chat' into develop

parents bcbb1c98 3871a0d0
......@@ -8,8 +8,8 @@ android {
applicationId "com.xabber.androiddev"
minSdkVersion 14
targetSdkVersion 21
versionCode 107
versionName '0.10.10'
versionCode 113
versionName '0.10.16'
}
buildTypes {
......@@ -27,4 +27,5 @@ android {
dependencies {
compile files('libs/otr4j.jar')
compile 'com.android.support:appcompat-v7:21.0.3'
compile 'com.android.support:support-v13:21.0.3'
}
......@@ -110,16 +110,6 @@
android:name="android.support.PARENT_ACTIVITY"
android:value="com.xabber.android.ui.preferences.AccountList" />
</activity>
<activity
android:label="@string/chat_list"
android:name="com.xabber.android.ui.ChatList"
android:parentActivityName="com.xabber.android.ui.ContactList"
>
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.xabber.android.ui.ContactList" />
</activity>
<activity
android:label="@string/occupant_list"
android:name="com.xabber.android.ui.OccupantList"
......
/**
Copyright (c) 2012 Antony Tran
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.antonyt.infiniteviewpager;
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import com.xabber.android.ui.adapter.ChatViewerAdapter;
/**
* A {@link android.support.v4.view.ViewPager} that allows pseudo-infinite paging with a wrap-around effect.
*/
public class InfiniteViewPager extends ViewPager {
public static final int OFFSET = 100;
public static final int TOTAL_COUNT = 200;
public InfiniteViewPager(Context context) {
super(context);
}
public InfiniteViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void setAdapter(PagerAdapter adapter) {
super.setAdapter(adapter);
// offset first element so that we can scroll to the left
setCurrentItem(0);
}
@Override
public void setCurrentItem(int item) {
// offset the current item to ensure there is space to scroll
setCurrentItem(item, false);
}
@Override
public void setCurrentItem(int item, boolean smoothScroll) {
item = getOffsetAmount() + (item % getAdapter().getCount());
super.setCurrentItem(item, smoothScroll);
}
@Override
public int getCurrentItem() {
int position = super.getCurrentItem();
// Return the actual item position in the data backing InfinitePagerAdapter
return position % ((ChatViewerAdapter)getAdapter()).getRealCount();
}
private int getOffsetAmount() {
// allow for 100 back cycles from the beginning
// should be enough to create an illusion of infinity
// warning: scrolling to very high values (1,000,000+) results in
// strange drawing behaviour
return OFFSET;
}
@Override
public void setOnPageChangeListener(OnPageChangeListener listener) {
super.setOnPageChangeListener(listener);
}
}
......@@ -14,20 +14,6 @@
*/
package com.xabber.android.data.message;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Message.Type;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.packet.DelayInformation;
import android.database.Cursor;
import com.xabber.android.data.Application;
......@@ -45,6 +31,20 @@ import com.xabber.android.data.message.chat.ChatManager;
import com.xabber.android.data.notification.NotificationManager;
import com.xabber.xmpp.archive.SaveMode;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Message.Type;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.packet.DelayInformation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* Chat instance.
*
......@@ -109,6 +109,8 @@ public abstract class AbstractChat extends BaseEntity {
*/
protected final Collection<MessageItem> sendQuery;
protected Date creationTime = new Date();
protected AbstractChat(final String account, final String user) {
super(account, user);
threadId = StringUtils.randomString(12);
......@@ -120,6 +122,7 @@ public abstract class AbstractChat extends BaseEntity {
historyIds = new ArrayList<Long>();
messages = new ArrayList<MessageItem>();
sendQuery = new ArrayList<MessageItem>();
updateCreationTime();
Application.getInstance().runInBackground(new Runnable() {
@Override
......@@ -267,6 +270,10 @@ public abstract class AbstractChat extends BaseEntity {
}
void openChat() {
if (!active) {
updateCreationTime();
}
active = true;
trackStatus = true;
}
......@@ -672,4 +679,11 @@ public abstract class AbstractChat extends BaseEntity {
protected void onDisconnect() {
}
public Date getCreationTime() {
return creationTime;
}
public void updateCreationTime() {
creationTime.setTime(System.currentTimeMillis());
}
}
/**
* Copyright (c) 2013, Redsolution LTD. All rights reserved.
*
* This file is part of Xabber project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License, Version 3.
*
* Xabber is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License,
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.xabber.android.ui;
import java.util.Collection;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import com.xabber.android.data.Application;
import com.xabber.android.data.account.OnAccountChangedListener;
import com.xabber.android.data.entity.BaseEntity;
import com.xabber.android.data.message.AbstractChat;
import com.xabber.android.data.message.OnChatChangedListener;
import com.xabber.android.data.roster.OnContactChangedListener;
import com.xabber.android.ui.adapter.ChatListAdapter;
import com.xabber.android.ui.helper.ManagedListActivity;
import com.xabber.androiddev.R;
public class ChatList extends ManagedListActivity implements
OnAccountChangedListener, OnContactChangedListener,
OnChatChangedListener, OnItemClickListener {
private ChatListAdapter listAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (isFinishing())
return;
setContentView(R.layout.list);
listAdapter = new ChatListAdapter(this);
setListAdapter(listAdapter);
getListView().setOnItemClickListener(this);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
@Override
protected void onResume() {
super.onResume();
Application.getInstance().addUIListener(OnAccountChangedListener.class,
this);
Application.getInstance().addUIListener(OnContactChangedListener.class,
this);
Application.getInstance().addUIListener(OnChatChangedListener.class,
this);
listAdapter.onChange();
}
@Override
protected void onPause() {
super.onPause();
Application.getInstance().removeUIListener(
OnAccountChangedListener.class, this);
Application.getInstance().removeUIListener(
OnContactChangedListener.class, this);
Application.getInstance().removeUIListener(OnChatChangedListener.class,
this);
}
@Override
public void onChatChanged(String account, String user, boolean incoming) {
listAdapter.onChange();
}
@Override
public void onContactsChanged(Collection<BaseEntity> addresses) {
listAdapter.onChange();
}
@Override
public void onAccountsChanged(Collection<String> accounts) {
listAdapter.onChange();
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
AbstractChat abstractChat = (AbstractChat) parent.getAdapter().getItem(
position);
startActivity(ChatViewer.createIntent(this, abstractChat.getAccount(),
abstractChat.getUser()));
finish();
}
public static Intent createIntent(Context context) {
return new Intent(context, ChatList.class);
}
}
......@@ -171,8 +171,8 @@ public class ContactList extends ManagedActivity implements OnChoosedListener, O
text);
return;
}
AccountChooseDialogFragment.newInstance(bareAddress, text).show(
getSupportFragmentManager(), "OPEN_WITH_ACCOUNT");
AccountChooseDialogFragment.newInstance(bareAddress, text)
.show(getFragmentManager(), "OPEN_WITH_ACCOUNT");
}
/**
......@@ -240,15 +240,14 @@ public class ContactList extends ManagedActivity implements OnChoosedListener, O
if (SettingsManager.bootCount() > 2
&& !SettingsManager.connectionStartAtBoot()
&& !SettingsManager.startAtBootSuggested())
StartAtBootDialogFragment.newInstance().show(
getSupportFragmentManager(), "START_AT_BOOT");
StartAtBootDialogFragment.newInstance().show(getFragmentManager(), "START_AT_BOOT");
if (!SettingsManager.contactIntegrationSuggested()
&& Application.getInstance().isContactsSupported()) {
if (AccountManager.getInstance().getAllAccounts().isEmpty())
SettingsManager.setContactIntegrationSuggested();
else
ContactIntegrationDialogFragment.newInstance().show(
getSupportFragmentManager(), "CONTACT_INTEGRATION");
getFragmentManager(), "CONTACT_INTEGRATION");
}
}
}
......@@ -284,7 +283,7 @@ public class ContactList extends ManagedActivity implements OnChoosedListener, O
startActivity(MUCEditor.createIntent(this));
return true;
case R.id.action_chat_list:
startActivity(ChatList.createIntent(this));
startActivity(ChatViewer.createIntent(this));
return true;
case R.id.action_settings:
startActivity(PreferenceEditor.createIntent(this));
......
......@@ -14,10 +14,6 @@
*/
package com.xabber.android.ui;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
......@@ -34,6 +30,10 @@ import com.xabber.android.ui.dialog.GroupAddDialogFragment.OnGroupAddConfirmed;
import com.xabber.android.ui.helper.ManagedListActivity;
import com.xabber.androiddev.R;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
/**
* Manage list of selected groups.
*
......@@ -146,8 +146,7 @@ public abstract class GroupListActivity extends ManagedListActivity implements
}
private void showGroupAddDialog() {
GroupAddDialogFragment.newInstance(getGroups()).show(
getSupportFragmentManager(), "GROUP-ADD");
GroupAddDialogFragment.newInstance(getGroups()).show(getFragmentManager(), "GROUP-ADD");
}
@Override
......
package com.xabber.android.ui;
import android.app.Activity;
import android.app.ListFragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.Toast;
import com.xabber.android.data.message.AbstractChat;
import com.xabber.android.ui.adapter.ChatListAdapter;
import com.xabber.androiddev.R;
import java.util.List;
public class RecentChatFragment extends ListFragment {
private RecentChatFragmentInteractionListener listener;
private List<AbstractChat> initialChats = null;
public static RecentChatFragment newInstance() {
return new RecentChatFragment();
}
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public RecentChatFragment() {
}
public void setInitialChats(List<AbstractChat> initialChats) {
this.initialChats = initialChats;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ChatListAdapter(getActivity()));
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
listener = (RecentChatFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement RecentChatFragmentInteractionListener");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
if (initialChats != null) {
((ChatListAdapter) getListAdapter()).updateChats(initialChats);
initialChats = null;
}
if (getListAdapter().isEmpty()) {
Activity activity = getActivity();
Toast.makeText(activity, R.string.chat_list_is_empty, Toast.LENGTH_LONG).show();
activity.finish();
}
return inflater.inflate(R.layout.list, container, false);
}
@Override
public void onResume() {
super.onResume();
((ChatViewer)getActivity()).registerRecentChatsList(this);
}
@Override
public void onPause() {
super.onPause();
((ChatViewer)getActivity()).unregisterRecentChatsList(this);
}
@Override
public void onDetach() {
listener = null;
super.onDetach();
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
if (null != listener) {
listener.onRecentChatSelected((AbstractChat) getListAdapter().getItem(position));
}
}
public interface RecentChatFragmentInteractionListener {
public void onRecentChatSelected(AbstractChat chat);
}
public void updateChats(List<AbstractChat> chats) {
((ChatListAdapter) getListAdapter()).updateChats(chats);
}
}
/**
* Copyright (c) 2013, Redsolution LTD. All rights reserved.
*
* This file is part of Xabber project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License, Version 3.
*
* Xabber is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License,
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.xabber.android.ui.adapter;
import java.util.ArrayList;
import java.util.Collections;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.xabber.android.data.message.AbstractChat;
import com.xabber.android.data.message.MessageManager;
import com.xabber.android.data.notification.NotificationManager;
import com.xabber.android.data.roster.AbstractContact;
import com.xabber.android.data.roster.RosterManager;
import com.xabber.android.ui.ChatList;
import com.xabber.android.ui.helper.AbstractAvatarInflaterHelper;
import com.xabber.androiddev.R;
/**
* Adapter for {@link ChatList}.
*
* @author alexander.ivanov
*/
public class ChatListAdapter extends BaseAdapter implements UpdatableAdapter {
import java.util.ArrayList;
import java.util.List;
private final Activity activity;
public class ChatListAdapter extends BaseAdapter {
private final ArrayList<AbstractChat> abstractChats;
private List<AbstractChat> chats;
private final AbstractAvatarInflaterHelper avatarInflaterHelper;
public ChatListAdapter(Activity activity) {
this.activity = activity;
abstractChats = new ArrayList<AbstractChat>();
avatarInflaterHelper = AbstractAvatarInflaterHelper
.createAbstractContactInflaterHelper();
}
private final Context context;
@Override
public void onChange() {
abstractChats.clear();
abstractChats.addAll(MessageManager.getInstance().getActiveChats());
Collections.sort(abstractChats, ChatComparator.CHAT_COMPARATOR);
if (abstractChats.size() == 0) {
Toast.makeText(activity, R.string.chat_list_is_empty,
Toast.LENGTH_LONG).show();
activity.finish();
return;
public ChatListAdapter(Context context) {
this.context = context;
chats = new ArrayList<>();
avatarInflaterHelper = AbstractAvatarInflaterHelper.createAbstractContactInflaterHelper();
}
public void updateChats(List<AbstractChat> chats) {
this.chats.clear();
this.chats.addAll(chats);
notifyDataSetChanged();
}
@Override
public int getCount() {
return abstractChats.size();
return chats.size();
}
@Override
public Object getItem(int position) {
return abstractChats.get(position);
return chats.get(position);
}
@Override
......@@ -87,33 +59,32 @@ public class ChatListAdapter extends BaseAdapter implements UpdatableAdapter {
public View getView(int position, View convertView, ViewGroup parent) {
final View view;
if (convertView == null) {
view = activity.getLayoutInflater().inflate(
R.layout.chat_list_item, parent, false);
view = LayoutInflater.from(context).inflate(R.layout.chat_list_item, parent, false);
} else {
view = convertView;
}
final AbstractChat abstractChat = (AbstractChat) getItem(position);
final AbstractContact abstractContact = RosterManager.getInstance()
.getBestContact(abstractChat.getAccount(),
abstractChat.getUser());
final ImageView colorView = (ImageView) view.findViewById(R.id.color);
.getBestContact(abstractChat.getAccount(), abstractChat.getUser());
((TextView) view.findViewById(R.id.name)).setText(abstractContact.getName());
((ImageView) view.findViewById(R.id.color)).setImageLevel(abstractContact.getColorLevel());
final ImageView avatarView = (ImageView) view.findViewById(R.id.avatar);
final TextView nameView = (TextView) view.findViewById(R.id.name);
final TextView textView = (TextView) view.findViewById(R.id.text);
colorView.setImageLevel(abstractContact.getColorLevel());
avatarView.setImageDrawable(abstractContact.getAvatar());
avatarInflaterHelper.updateAvatar(avatarView, abstractContact);
nameView.setText(abstractContact.getName());
final TextView textView = (TextView) view.findViewById(R.id.text);
String statusText = MessageManager.getInstance().getLastText(
abstractContact.getAccount(), abstractContact.getUser());
textView.setText(statusText);
boolean newMessages = NotificationManager.getInstance()
.getNotificationMessageCount(abstractChat.getAccount(),
abstractChat.getUser()) > 0;
textView.setTextAppearance(activity,
newMessages ? R.style.ChatList_Notification
.getNotificationMessageCount(abstractChat.getAccount(), abstractChat.getUser()) > 0;
textView.setTextAppearance(context, newMessages ? R.style.ChatList_Notification
: R.style.ChatList_Normal);
return view;
}
}
......@@ -14,11 +14,6 @@
*/
package com.xabber.android.ui.adapter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import android.app.Activity;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
......@@ -49,6 +44,11 @@ import com.xabber.android.utils.Emoticons;
import com.xabber.android.utils.StringUtils;
import com.xabber.androiddev.R;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/**
* Adapter for the list of messages in the chat.
*
......@@ -309,8 +309,7 @@ public class ChatMessageAdapter extends BaseAdapter implements UpdatableAdapter
@Override
public void onChange() {
messages = new ArrayList<MessageItem>(MessageManager.getInstance()
.getMessages(account, user));
messages = new ArrayList<>(MessageManager.getInstance().getMessages(account, user));
hint = getHint();
notifyDataSetChanged();
}
......
/**
* Copyright (c) 2013, Redsolution LTD. All rights reserved.
*
* This file is part of Xabber project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License, Version 3.
*
* Xabber is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License,
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.xabber.android.ui.adapter;
import java.util.ArrayList;
import java.util.Collection;
import android.support.v4.app.FragmentActivity;
import android.view.Menu;
import android.view.View;
import android.app.Fragment;
import android.app.FragmentManager;
import android.support.v13.app.FragmentStatePagerAdapter;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import com.xabber.android.data.entity.BaseEntity;
import com.antonyt.infiniteviewpager.InfiniteViewPager;
import com.xabber.android.data.message.AbstractChat;
import com.xabber.android.data.message.MessageManager;
import com.xabber.android.ui.ChatViewerFragment;
import com.xabber.android.ui.RecentChatFragment;
import com.xabber.xmpp.address.Jid;
/**
* Adapter for the list of chat pages.
*
* @author alexander.ivanov
*/
public class ChatViewerAdapter extends BaseAdapter implements SaveStateAdapter,
UpdatableAdapter {
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
private final FragmentActivity activity;
public class ChatViewerAdapter extends FragmentStatePagerAdapter implements UpdatableAdapter {
/**
* Intent sent while opening chat activity.
*/
private final AbstractChat intent;
/**
* Position to insert intent.
*/
private final int intentPosition;
private ArrayList<AbstractChat> activeChats;
public ChatViewerAdapter(FragmentActivity activity, String account,
String user) {
this.activity = activity;
activeChats = new ArrayList<AbstractChat>();
intent = MessageManager.getInstance().getOrCreateChat(account,
Jid.getBareAddress(user));
Collection<? extends BaseEntity> activeChats = MessageManager
.getInstance().getActiveChats();
if (activeChats.contains(intent))
intentPosition = -1;
else
intentPosition = activeChats.size();
private FinishUpdateListener finishUpdateListener;
private Fragment currentFragment;
public ChatViewerAdapter(FragmentManager fragmentManager, String account, String user, FinishUpdateListener finishUpdateListener) {
super(fragmentManager);
this.finishUpdateListener = finishUpdateListener;
activeChats = new ArrayList<>(MessageManager.getInstance().getActiveChats());
intent = MessageManager.getInstance().getOrCreateChat(account, Jid.getBareAddress(user));
if (!activeChats.contains(intent)) {
intent.updateCreationTime();
}
onChange();
}
@Override
public int getCount() {
return activeChats.size();
public ChatViewerAdapter(FragmentManager fragmentManager, FinishUpdateListener finishUpdateListener) {
super(fragmentManager);
this.finishUpdateListener = finishUpdateListener;
activeChats = new ArrayList<>(MessageManager.getInstance().getActiveChats());
intent = null;
onChange();
}
@Override
public Object getItem(int position) {
return activeChats.get(position);
public int getCount() {
// warning: scrolling to very high values (1,000,000+) results in
// strange drawing behaviour
return InfiniteViewPager.TOTAL_COUNT;
}
@Override
public long getItemId(int position) {
return position;
public int getRealCount() {
return activeChats.size() + 1;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
final AbstractChat chat = (AbstractChat) getItem(position);
ChatViewerFragment fragment;
if (convertView == null) {
fragment = new ChatViewerFragment(activity);
view = fragment.getView();
view.setTag(fragment);
public Fragment getItem(int virtualPagePosition) {
int chatIndex;
int realPosition = virtualPagePosition % getRealCount();
if (realPosition == 0) {
RecentChatFragment activeChatFragment = RecentChatFragment.newInstance();
activeChatFragment.setInitialChats(activeChats);
return activeChatFragment;
} else {
view = convertView;
fragment = (ChatViewerFragment) view.getTag();
chatIndex = realPosition -1;
}
fragment.setChat(chat);
return view;
AbstractChat chat = activeChats.get(chatIndex);
return ChatViewerFragment.newInstance(chat.getAccount(), chat.getUser());
}
@Override
public void saveState(View view) {
((ChatViewerFragment) view.getTag()).saveState();
public void onChange() {
activeChats = new ArrayList<>(MessageManager.getInstance().getActiveChats());
if (intent != null && !activeChats.contains(intent)) {
activeChats.add(intent);
}
Collections.sort(activeChats, new Comparator<AbstractChat>() {
@Override
public void hidePages(View view) {
((ChatViewerFragment) view.getTag()).hidePages();
public int compare(AbstractChat lhs, AbstractChat rhs) {
return lhs.getCreationTime().compareTo(rhs.getCreationTime());
}
});
notifyDataSetChanged();
}
public int getPageNumber(String account, String user) {
for (int position = 0; position < activeChats.size(); position++) {
if (activeChats.get(position).equals(account, user)) {
return position + 1;
}
}
return 0;
}
public AbstractChat getChatByPageNumber(int virtualPosition) {
int realPosition = virtualPosition % getRealCount();
int chatIndex = realPosition - 1;
if (chatIndex < 0) {
return null;
}
return activeChats.get(chatIndex);
}
@Override
public void showPages(View view) {
((ChatViewerFragment) view.getTag()).showPages();
public void startUpdate(ViewGroup container) {
if (currentFragment instanceof ChatViewerFragment) {
((ChatViewerFragment)currentFragment).saveInputState();
}
/**
* Must be called on changes in chat (message sent, received, etc.).
*/
public void onChatChange(View view, boolean incomingMessage) {
((ChatViewerFragment) view.getTag()).onChatChange(incomingMessage);
super.startUpdate(container);
}
/**
* Must be called on changes in chat (message sent, received, etc.).
*/
public void onPrepareOptionsMenu(View view, Menu menu) {
((ChatViewerFragment) view.getTag()).onPrepareOptionsMenu(menu);
@Override
public void finishUpdate(ViewGroup container) {
super.finishUpdate(container);
finishUpdateListener.onChatViewAdapterFinishUpdate();
}
public void insertText(View view, String text) {
((ChatViewerFragment) view.getTag()).insertText(text);
public interface FinishUpdateListener {
public void onChatViewAdapterFinishUpdate();
}
@Override
public void onChange() {
activeChats = new ArrayList<AbstractChat>(MessageManager.getInstance()
.getActiveChats());
if (intentPosition != -1) {
int index = activeChats.indexOf(intent);
AbstractChat chat;
if (index == -1)
chat = intent;
else
chat = activeChats.remove(index);
activeChats.add(Math.min(intentPosition, activeChats.size()), chat);
public void setPrimaryItem(ViewGroup container, int position, Object object) {
if (getCurrentFragment() != object) {
currentFragment = ((Fragment) object);
}
notifyDataSetChanged();
super.setPrimaryItem(container, position, object);
}
public int getPosition(String account, String user) {
for (int position = 0; position < activeChats.size(); position++)
if (activeChats.get(position).equals(account, user))
return position;
return -1;
public Fragment getCurrentFragment() {
return currentFragment;
}
public ArrayList<AbstractChat> getActiveChats() {
return activeChats;
}
}
\ No newline at end of file
......@@ -14,13 +14,13 @@
*/
package com.xabber.android.ui.dialog;
import java.util.ArrayList;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.DialogFragment;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import java.util.ArrayList;
/**
* Base dialog fragment.
......
package com.xabber.android.ui.dialog;
import java.util.ArrayList;
import android.app.Activity;
import android.app.AlertDialog.Builder;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.support.v4.app.DialogFragment;
import android.view.View;
import android.view.ViewGroup;
......@@ -14,6 +12,8 @@ import com.xabber.android.data.roster.RosterContact;
import com.xabber.android.data.roster.RosterManager;
import com.xabber.android.ui.adapter.AccountChooseAdapter;
import java.util.ArrayList;
public class AccountChooseDialogFragment extends AbstractDialogFragment {
private static final String USER = "USER";
......
......@@ -14,14 +14,12 @@
*/
package com.xabber.android.ui.dialog;
import java.io.File;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.DialogFragment;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.v4.app.DialogFragment;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
......@@ -34,6 +32,8 @@ import com.xabber.android.data.message.MessageManager;
import com.xabber.android.data.roster.RosterManager;
import com.xabber.androiddev.R;
import java.io.File;
public class ChatExportDialogFragment extends ConfirmDialogFragment {
private static final String ACCOUNT = "ACCOUNT";
......@@ -45,8 +45,7 @@ public class ChatExportDialogFragment extends ConfirmDialogFragment {
* @return
*/
public static DialogFragment newInstance(String account, String user) {
return new ChatExportDialogFragment().putAgrument(ACCOUNT, account)
.putAgrument(USER, user);
return new ChatExportDialogFragment().putAgrument(ACCOUNT, account).putAgrument(USER, user);
}
private String account;
......
package com.xabber.android.ui.dialog;
import android.app.AlertDialog.Builder;
import android.support.v4.app.DialogFragment;
import android.app.DialogFragment;
import com.xabber.android.data.Application;
import com.xabber.android.data.NetworkException;
......
package com.xabber.android.ui.dialog;
import android.app.AlertDialog.Builder;
import android.support.v4.app.DialogFragment;
import android.app.DialogFragment;
import com.xabber.android.data.SettingsManager;
import com.xabber.android.data.account.AccountManager;
......
......@@ -14,17 +14,17 @@
*/
package com.xabber.android.ui.dialog;
import java.util.ArrayList;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.support.v4.app.DialogFragment;
import android.app.DialogFragment;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.xabber.androiddev.R;
import java.util.ArrayList;
public class GroupAddDialogFragment extends ConfirmDialogFragment {
private static final String GROUPS = "GROUPS";
......
package com.xabber.android.ui.dialog;
import android.app.AlertDialog.Builder;
import android.support.v4.app.DialogFragment;
import android.app.DialogFragment;
import com.xabber.android.data.Application;
import com.xabber.android.data.NetworkException;
......
......@@ -16,7 +16,7 @@ package com.xabber.android.ui.dialog;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.support.v4.app.DialogFragment;
import android.app.DialogFragment;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
......
package com.xabber.android.ui.dialog;
import android.app.AlertDialog.Builder;
import android.support.v4.app.DialogFragment;
import android.app.DialogFragment;
import com.xabber.android.data.account.AccountManager;
import com.xabber.android.data.extension.muc.MUCManager;
......
package com.xabber.android.ui.dialog;
import android.app.AlertDialog.Builder;
import android.support.v4.app.DialogFragment;
import android.app.DialogFragment;
import com.xabber.android.data.SettingsManager;
import com.xabber.androiddev.R;
......
......@@ -14,8 +14,6 @@
*/
package com.xabber.android.ui.helper;
import org.jivesoftware.smackx.ChatState;
import android.app.Activity;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
......@@ -24,7 +22,6 @@ import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
......@@ -34,6 +31,8 @@ import com.xabber.android.data.roster.AbstractContact;
import com.xabber.android.utils.Emoticons;
import com.xabber.androiddev.R;
import org.jivesoftware.smackx.ChatState;
/**
* Helper class to update <code>contact_title.xml</code>.
*
......@@ -51,47 +50,53 @@ public class ContactTitleInflater {
*/
public static void updateTitle(View titleView, final Activity activity,
AbstractContact abstractContact) {
final TypedArray typedArray = activity
.obtainStyledAttributes(R.styleable.ContactList);
final TypedArray typedArray = activity.obtainStyledAttributes(R.styleable.ContactList);
final Drawable titleAccountBackground = typedArray
.getDrawable(R.styleable.ContactList_titleAccountBackground);
typedArray.recycle();
final TextView nameView = (TextView) titleView.findViewById(R.id.name);
final ImageView avatarView = (ImageView) titleView
.findViewById(R.id.avatar);
final ImageView statusModeView = (ImageView) titleView
.findViewById(R.id.status_mode);
final TextView statusTextView = (TextView) titleView
.findViewById(R.id.status_text);
final ImageView avatarView = (ImageView) titleView.findViewById(R.id.avatar);
final ImageView statusModeView = (ImageView) titleView.findViewById(R.id.status_mode);
final TextView statusTextView = (TextView) titleView.findViewById(R.id.status_text);
final View shadowView = titleView.findViewById(R.id.shadow);
titleView.setBackgroundDrawable(titleAccountBackground);
nameView.setText(abstractContact.getName());
statusModeView.setImageLevel(abstractContact.getStatusMode()
.getStatusLevel());
titleView.getBackground().setLevel(
AccountManager.getInstance().getColorLevel(
statusModeView.setImageLevel(abstractContact.getStatusMode().getStatusLevel());
titleView.getBackground().setLevel(AccountManager.getInstance().getColorLevel(
abstractContact.getAccount()));
avatarView.setImageDrawable(abstractContact.getAvatar());
setStatusText(activity, abstractContact, statusTextView);
final Bitmap bitmap = BitmapFactory.decodeResource(activity.getResources(), R.drawable.shadow);
final BitmapDrawable shadowDrawable = new BitmapDrawable(bitmap);
shadowDrawable.setTileModeXY(TileMode.REPEAT, TileMode.REPEAT);
shadowView.setBackgroundDrawable(shadowDrawable);
if (abstractContact.isConnected()) {
shadowView.setVisibility(View.GONE);
} else {
shadowView.setVisibility(View.VISIBLE);
}
}
private static void setStatusText(Activity activity, AbstractContact abstractContact,
TextView statusTextView) {
ChatState chatState = ChatStateManager.getInstance().getChatState(
abstractContact.getAccount(), abstractContact.getUser());
final CharSequence statusText;
if (chatState == ChatState.composing)
if (chatState == ChatState.composing) {
statusText = activity.getString(R.string.chat_state_composing);
else if (chatState == ChatState.paused)
} else if (chatState == ChatState.paused) {
statusText = activity.getString(R.string.chat_state_paused);
else
statusText = Emoticons.getSmiledText(activity,
abstractContact.getStatusText());
} else {
statusText = Emoticons.getSmiledText(activity, abstractContact.getStatusText());
}
statusTextView.setText(statusText);
final Bitmap bitmap = BitmapFactory.decodeResource(
activity.getResources(), R.drawable.shadow);
final BitmapDrawable shadowDrawable = new BitmapDrawable(bitmap);
shadowDrawable.setTileModeXY(TileMode.REPEAT, TileMode.REPEAT);
shadowView.setBackgroundDrawable(shadowDrawable);
if (abstractContact.isConnected())
shadowView.setVisibility(View.GONE);
else
shadowView.setVisibility(View.VISIBLE);
}
}
......@@ -33,11 +33,9 @@ import com.xabber.android.data.roster.AbstractContact;
import com.xabber.android.data.roster.GroupManager;
import com.xabber.android.data.roster.PresenceManager;
import com.xabber.android.data.roster.ShowOfflineMode;
import com.xabber.android.ui.preferences.AccountEditor;
import com.xabber.android.ui.ChatViewer;
import com.xabber.android.ui.ContactAdd;
import com.xabber.android.ui.ContactEditor;
import com.xabber.android.ui.preferences.ContactViewer;
import com.xabber.android.ui.MUCEditor;
import com.xabber.android.ui.StatusEditor;
import com.xabber.android.ui.adapter.UpdatableAdapter;
......@@ -45,6 +43,8 @@ import com.xabber.android.ui.dialog.ContactDeleteDialogFragment;
import com.xabber.android.ui.dialog.GroupDeleteDialogFragment;
import com.xabber.android.ui.dialog.GroupRenameDialogFragment;
import com.xabber.android.ui.dialog.MUCDeleteDialogFragment;
import com.xabber.android.ui.preferences.AccountEditor;
import com.xabber.android.ui.preferences.ContactViewer;
import com.xabber.androiddev.R;
/**
......@@ -84,7 +84,7 @@ public class ContextMenuHelper {
@Override
public boolean onMenuItemClick(MenuItem item) {
MUCDeleteDialogFragment.newInstance(account, user)
.show(activity.getSupportFragmentManager(),
.show(activity.getFragmentManager(),
"MUC_DELETE");
return true;
}
......@@ -131,8 +131,7 @@ public class ContextMenuHelper {
@Override
public boolean onMenuItemClick(MenuItem item) {
ContactDeleteDialogFragment.newInstance(account,
user).show(
activity.getSupportFragmentManager(),
user).show(activity.getFragmentManager(),
"CONTACT_DELETE");
return true;
}
......@@ -225,8 +224,7 @@ public class ContextMenuHelper {
account == GroupManager.NO_ACCOUNT ? null
: account,
group == GroupManager.NO_GROUP ? null
: group).show(
activity.getSupportFragmentManager(),
: group).show(activity.getFragmentManager(),
"GROUP_RENAME");
return true;
}
......@@ -241,9 +239,7 @@ public class ContextMenuHelper {
.newInstance(
account == GroupManager.NO_ACCOUNT ? null
: account, group)
.show(activity
.getSupportFragmentManager(),
"GROUP_DELETE");
.show(activity.getFragmentManager(), "GROUP_DELETE");
return true;
}
});
......
<?xml version="1.0" encoding="utf-8"?>
<com.antonyt.infiniteviewpager.InfiniteViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013, Redsolution LTD. All rights reserved.
This file is part of Xabber project; you can redistribute it and/or
modify it under the terms of the GNU General Public License, Version 3.
Xabber is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License,
along with this program. If not, see http://www.gnu.org/licenses/.
-->
<com.xabber.android.ui.widget.PageSwitcher
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/switcher"
/>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013, Redsolution LTD. All rights reserved.
This file is part of Xabber project; you can redistribute it and/or
modify it under the terms of the GNU General Public License, Version 3.
Xabber is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License,
along with this program. If not, see http://www.gnu.org/licenses/.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/action_message_repeat"
android:visible="false"
android:title="@string/message_repeat" />
<item android:id="@+id/action_message_quote"
android:title="@string/message_quote" />
<item android:id="@+id/action_message_copy"
android:title="@string/message_copy" />
<item android:id="@+id/action_message_remove"
android:title="@string/message_remove" />
</menu>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment