Commit 2748cd7f authored by Grigory Fedorov's avatar Grigory Fedorov

New activity and fragment AccountInfoEditor and AccountInfoEditorFragment....

New activity and fragment AccountInfoEditor and AccountInfoEditorFragment. First implementation of vCard editing.
parent 8e10be53
......@@ -255,6 +255,16 @@
android:value="com.xabber.android.ui.ContactList" />
</activity>
<activity
android:name=".ui.AccountInfoEditor"
android:parentActivityName=".ui.AccountViewer" >
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.xabber.android.ui.AccountViewer" />
</activity>
<activity
android:name=".ui.FingerprintViewer"
android:label="@string/otr_verify_fingerprint"
......
......@@ -54,7 +54,7 @@ public class ConnectionManager implements OnInitializedListener, OnCloseListener
/**
* Timeout for receiving reply from server.
*/
public final static int PACKET_REPLY_TIMEOUT = 5000;
public final static int PACKET_REPLY_TIMEOUT = 60000;
public final static int PING_INTERVAL_SECONDS = 30;
......
......@@ -272,4 +272,21 @@ public class VCardManager implements OnLoadListener, OnPacketListener,
thread.start();
}
public static void saveVCard(final String account, final VCard vCard) {
final XMPPConnection xmppConnection = AccountManager.getInstance().getAccount(account).getConnectionThread().getXMPPConnection();
final org.jivesoftware.smackx.vcardtemp.VCardManager vCardManager = org.jivesoftware.smackx.vcardtemp.VCardManager.getInstanceFor(xmppConnection);
final Thread thread = new Thread("Save vCard for account " + account) {
@Override
public void run() {
try {
vCardManager.saveVCard(vCard);
} catch (SmackException.NoResponseException | XMPPException.XMPPErrorException | SmackException.NotConnectedException e) {
LogManager.w(this, "Error saving vCard: " + e.getMessage());
}
}
};
thread.start();
}
}
package com.xabber.android.ui;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.View;
import com.xabber.android.R;
import com.xabber.android.data.Application;
import com.xabber.android.data.account.AccountManager;
import com.xabber.android.data.account.OnAccountChangedListener;
import com.xabber.android.data.intent.EntityIntentBuilder;
import com.xabber.android.data.roster.AbstractContact;
import com.xabber.android.data.roster.RosterManager;
import com.xabber.android.ui.helper.ContactTitleActionBarInflater;
import com.xabber.android.ui.helper.ManagedActivity;
import com.xabber.xmpp.address.Jid;
import java.util.Collection;
public class AccountInfoEditor extends ManagedActivity implements OnAccountChangedListener {
public static final String ARG_VCARD = "com.xabber.android.ui.AccountInfoEditor.ARG_VCARD";
ContactTitleActionBarInflater contactTitleActionBarInflater;
private String account;
public static Intent createIntent(Context context, String account, String vCard) {
Intent intent = new EntityIntentBuilder(context, AccountInfoEditor.class).setAccount(account).build();
intent.putExtra(ARG_VCARD, vCard);
return intent;
}
private static String getAccount(Intent intent) {
return EntityIntentBuilder.getAccount(intent);
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_with_toolbar_and_container);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_default);
contactTitleActionBarInflater = new ContactTitleActionBarInflater(this, toolbar);
contactTitleActionBarInflater.setUpActionBarView();
Intent intent = getIntent();
account = getAccount(intent);
String vCard = intent.getStringExtra(ARG_VCARD);
if (AccountManager.getInstance().getAccount(account) == null) {
Application.getInstance().onError(R.string.ENTRY_IS_NOT_FOUND);
finish();
}
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.fragment_container, AccountInfoEditorFragment.newInstance(account, vCard)).commit();
}
}
@Override
protected void onResume() {
super.onResume();
Application.getInstance().addUIListener(OnAccountChangedListener.class, this);
update();
}
@Override
protected void onPause() {
super.onPause();
Application.getInstance().removeUIListener(OnAccountChangedListener.class, this);
}
private void update() {
AbstractContact bestContact = RosterManager.getInstance().getBestContact(account, Jid.getBareAddress(account));
contactTitleActionBarInflater.update(bestContact);
contactTitleActionBarInflater.hideStatusIcon();
}
@Override
public void onAccountsChanged(Collection<String> accounts) {
if (accounts.contains(account)) {
update();
}
}
}
package com.xabber.android.ui;
import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import com.xabber.android.R;
import com.xabber.android.data.LogManager;
import com.xabber.android.data.extension.avatar.AvatarManager;
import com.xabber.android.data.extension.vcard.VCardManager;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smackx.vcardtemp.packet.VCard;
import org.xmlpull.v1.XmlPullParserException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class AccountInfoEditorFragment extends Fragment {
public static final String ARGUMENT_ACCOUNT = "com.xabber.android.ui.AccountInfoEditorFragment.ARGUMENT_ACCOUNT";
public static final String ARGUMENT_VCARD = "com.xabber.android.ui.AccountInfoEditorFragment.ARGUMENT_USER";
private VCard vCard;
private EditText prefixName;
private EditText givenName;
private EditText middleName;
private EditText familyName;
private EditText suffixName;
private String account;
private ImageView avatar;
private Uri imageUri;
public static AccountInfoEditorFragment newInstance(String account, String vCard) {
AccountInfoEditorFragment fragment = new AccountInfoEditorFragment();
Bundle arguments = new Bundle();
arguments.putString(ARGUMENT_ACCOUNT, account);
arguments.putString(ARGUMENT_VCARD, vCard);
fragment.setArguments(arguments);
return fragment;
}
public AccountInfoEditorFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
account = args.getString(ARGUMENT_ACCOUNT, null);
String vCardString = args.getString(ARGUMENT_VCARD, null);
if (vCardString != null) {
try {
vCard = ContactVcardViewerFragment.parseVCard(vCardString);
} catch (XmlPullParserException | IOException | SmackException e) {
LogManager.exception(this, e);
}
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.account_info_editor_fragment, container, false);
prefixName = (EditText) view.findViewById(R.id.vcard_prefix_name);
givenName = (EditText) view.findViewById(R.id.vcard_given_name);
middleName = (EditText) view.findViewById(R.id.vcard_middle_name);
familyName = (EditText) view.findViewById(R.id.vcard_family_name);
suffixName = (EditText) view.findViewById(R.id.vcard_suffix_name);
avatar = (ImageView) view.findViewById(R.id.vcard_avatar);
view.findViewById(R.id.vcard_change_avatar).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
changeAvatar();
}
}
);
prefixName.setText(vCard.getPrefix());
givenName.setText(vCard.getFirstName());
middleName.setText(vCard.getMiddleName());
familyName.setText(vCard.getLastName());
suffixName.setText(vCard.getSuffix());
avatar.setImageDrawable(AvatarManager.getInstance().getAccountAvatar(account));
return view;
}
private void changeAvatar() {
Intent pickAvatar = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(pickAvatar, 1);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
imageUri = data.getData();
avatar.setImageURI(imageUri);
}
}
public static byte[] getBytes(InputStream inputStream) throws IOException {
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
return byteBuffer.toByteArray();
}
@Override
public void onStop() {
super.onStop();
vCard.setPrefix(prefixName.getText().toString());
vCard.setFirstName(givenName.getText().toString());
vCard.setMiddleName(middleName.getText().toString());
vCard.setLastName(familyName.getText().toString());
vCard.setSuffix(suffixName.getText().toString());
if (imageUri != null) {
try {
InputStream inputStream = getActivity().getContentResolver().openInputStream(imageUri);
vCard.setAvatar(getBytes(inputStream));
} catch (IOException e) {
e.printStackTrace();
}
}
VCardManager.saveVCard(account, vCard);
}
}
......@@ -10,8 +10,8 @@ import android.view.MenuItem;
import com.xabber.android.R;
import com.xabber.android.data.intent.EntityIntentBuilder;
import com.xabber.android.data.roster.GroupManager;
import com.xabber.android.data.roster.RosterContact;
import com.xabber.android.data.roster.RosterManager;
import org.jivesoftware.smackx.vcardtemp.packet.VCard;
public class AccountViewer extends ContactViewer implements Toolbar.OnMenuItemClickListener {
......@@ -33,10 +33,7 @@ public class AccountViewer extends ContactViewer implements Toolbar.OnMenuItemCl
@Override
public boolean onCreateOptionsMenu(Menu menu) {
RosterContact rosterContact = RosterManager.getInstance().getRosterContact(getAccount(), getBareAddress());
if (rosterContact != null) {
getMenuInflater().inflate(ACCOUNT_VIEWER_MENU, menu);
}
getMenuInflater().inflate(ACCOUNT_VIEWER_MENU, menu);
return true;
}
......@@ -50,6 +47,11 @@ public class AccountViewer extends ContactViewer implements Toolbar.OnMenuItemCl
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_edit_account_user_info:
VCard vCard = ((ContactVcardViewerFragment) getFragmentManager().findFragmentById(R.id.scrollable_container)).getvCard();
if (vCard != null) {
Intent intent = AccountInfoEditor.createIntent(this, getAccount(), vCard.getChildElementXML().toString());
startActivity(intent);
}
return true;
default:
......
......@@ -31,11 +31,14 @@ import com.xabber.xmpp.vcard.EmailType;
import com.xabber.xmpp.vcard.TelephoneType;
import com.xabber.xmpp.vcard.VCardProperty;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smackx.vcardtemp.packet.VCard;
import org.jivesoftware.smackx.vcardtemp.provider.VCardProvider;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
......@@ -78,28 +81,33 @@ public class ContactVcardViewerFragment extends Fragment implements OnContactCha
if (savedInstanceState != null) {
vCardError = savedInstanceState.getBoolean(SAVED_VCARD_ERROR, false);
String xml = savedInstanceState.getString(SAVED_VCARD);
if (xml != null)
if (xml != null) {
try {
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(new StringReader(xml));
int eventType = parser.next();
if (eventType != XmlPullParser.START_TAG) {
throw new IllegalStateException(String.valueOf(eventType));
}
if (!VCard.ELEMENT.equals(parser.getName())) {
throw new IllegalStateException(parser.getName());
}
if (!VCard.NAMESPACE.equals(parser.getNamespace())) {
throw new IllegalStateException(parser.getNamespace());
}
vCard = (new VCardProvider()).parse(parser);
} catch (Exception e) {
vCard = parseVCard(xml);
} catch (XmlPullParserException | IOException | SmackException e) {
LogManager.exception(this, e);
}
}
}
}
public static VCard parseVCard(String xml) throws XmlPullParserException, IOException, SmackException {
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(new StringReader(xml));
int eventType = parser.next();
if (eventType != XmlPullParser.START_TAG) {
throw new IllegalStateException(String.valueOf(eventType));
}
if (!VCard.ELEMENT.equals(parser.getName())) {
throw new IllegalStateException(parser.getName());
}
if (!VCard.NAMESPACE.equals(parser.getNamespace())) {
throw new IllegalStateException(parser.getNamespace());
}
return (new VCardProvider()).parse(parser);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
......@@ -457,4 +465,8 @@ public class ContactVcardViewerFragment extends Fragment implements OnContactCha
return contactInfoItem;
}
public VCard getvCard() {
return vCard;
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="72dp"
>
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="32dp"
android:layout_marginTop="24dp"
android:src="@drawable/ic_vcard_contact_info_24dp"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/vcard_prefix_name"
android:layout_gravity="center_vertical"
android:id="@+id/vcard_prefix_name"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/vcard_given_name"
android:layout_gravity="center_vertical"
android:id="@+id/vcard_given_name"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/vcard_middle_name"
android:layout_gravity="center_vertical"
android:id="@+id/vcard_middle_name"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/vcard_family_name"
android:layout_gravity="center_vertical"
android:id="@+id/vcard_family_name"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/vcard_suffix_name"
android:layout_gravity="center_vertical"
android:id="@+id/vcard_suffix_name"
/>
</LinearLayout>
</LinearLayout>
<include layout="@layout/contact_info_separator"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="72dp"
>
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="32dp"
android:layout_marginTop="24dp"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
>
<ImageView
android:id="@+id/vcard_avatar"
android:layout_width="@dimen/avatar_large_size"
android:layout_height="@dimen/avatar_large_size"
android:src="@drawable/ic_avatar_1" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Change"
android:id="@+id/vcard_change_avatar"
android:layout_marginLeft="16dp"
android:layout_gravity="top" />
</LinearLayout>
</LinearLayout>
<include layout="@layout/contact_info_separator"/>
</LinearLayout>
\ No newline at end of file
......@@ -14,9 +14,6 @@
-->
</startupClasses>
<!-- Packet reply timeout in milliseconds -->
<packetReplyTimeout>30000</packetReplyTimeout>
<!-- Keep-alive interval in milliseconds -->
<keepAliveInterval>30000</keepAliveInterval>
......
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