/* * Copyright (C) 2008 Esmertec AG. Copyright (C) 2008 The Android Open Source * Project * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package info.guardianproject.otr.app.im.app; import info.guardianproject.otr.app.im.IContactListManager; import info.guardianproject.otr.app.im.IImConnection; import info.guardianproject.otr.app.im.R; import info.guardianproject.otr.app.im.engine.ImErrorInfo; import info.guardianproject.otr.app.im.provider.Imps; import info.guardianproject.util.LogCleaner; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.res.Resources; import android.database.Cursor; import android.database.DatabaseUtils; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.widget.ResourceCursorAdapter; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemLongClickListener; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; public class ContactListFilterView extends LinearLayout { private AbsListView mFilterList; private ContactAdapter mContactAdapter; private String mSearchString; private TextView mEmptyView = null; private Uri mUri; private final Context mContext; private final SimpleAlertHandler mHandler; private MyLoaderCallbacks mLoaderCallbacks; private ContactListListener mListener = null; private LoaderManager mLoaderManager; private int mLoaderId; public ContactListFilterView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; mHandler = new SimpleAlertHandler((Activity)context); } @Override protected void onFinishInflate() { mFilterList = (AbsListView) findViewById(R.id.filteredList); mFilterList.setTextFilterEnabled(true); mEmptyView = (TextView) findViewById(R.id.empty); mFilterList.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Cursor c = (Cursor) mFilterList.getItemAtPosition(position); if (mListener != null) mListener.openChat(c); } }); mFilterList.setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> arg0, View arg1, final int position, long arg3) { String[] contactOptions = { // mContext.getString(R.string.menu_verify), mContext.getString(R.string.menu_contact_nickname), mContext.getString(R.string.menu_remove_contact)}; // mContext.getString(R.string.menu_block_contact)}; AlertDialog.Builder builder = new AlertDialog.Builder(mContext); builder.setItems(contactOptions, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // The 'which' argument contains the index position // of the selected item if (which == 0) setContactNickname(position); else if (which == 1) removeContactAtPosition(position); else if (which == 2) blockContactAtPosition(position); } }); builder.create().show(); return true; } }); /** mEtSearch = (EditText)findViewById(R.id.contactSearch); mEtSearch.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable s) { } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { ContactListFilterView.this.doFilter(mEtSearch.getText().toString()); } }); mEtSearch.setOnKeyListener(new OnKeyListener () { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { ContactListFilterView.this.doFilter(mEtSearch.getText().toString()); return false; } }); */ /* mFilterList.setItemActionListener(new ListView.OnActionClickListener() { @Override public void onClick(View listView, View buttonview, int position) { Cursor c = (Cursor) mFilterList.getItemAtPosition(position); if (mListener != null) if (buttonview.getId() == R.id.btnExListChat) mListener.startChat(c); else if (buttonview.getId() == R.id.btnExListProfile) mListener.showProfile(c); } }, R.id.btnExListChat, R.id.btnExListProfile); */ // //if (!isInEditMode()) // mPresenceView = (UserPresenceView) findViewById(R.id.userPresence); } public AbsListView getListView() { return mFilterList; } public Cursor getContactAtPosition(int position) { return (Cursor) mContactAdapter.getItem(position); } public void doFilter(Uri uri, String filterString) { if (uri != null && !uri.equals(mUri)) { mUri = uri; } doFilter(filterString); } boolean mAwaitingUpdate = false; public synchronized void doFilter(String filterString) { mSearchString = filterString; if (mContactAdapter == null) { mContactAdapter = new ContactAdapter(mContext, R.layout.contact_view); ((ListView)mFilterList).setAdapter(mContactAdapter); mLoaderCallbacks = new MyLoaderCallbacks(); mLoaderManager.initLoader(mLoaderId, null, mLoaderCallbacks); } else { if (!mAwaitingUpdate) { mAwaitingUpdate = true; mHandler.postDelayed(new Runnable () { public void run () { mLoaderManager.restartLoader(mLoaderId, null, mLoaderCallbacks); mAwaitingUpdate = false; } },1000); } } } private class ContactAdapter extends ResourceCursorAdapter { public ContactAdapter(Context context, int view) { super(context, view, null,0); } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { View view = super.newView(context, cursor, parent); ContactView.ViewHolder holder = null; holder = new ContactView.ViewHolder(); holder.mLine1 = (TextView) view.findViewById(R.id.line1); holder.mLine2 = (TextView) view.findViewById(R.id.line2); holder.mAvatar = (ImageView)view.findViewById(R.id.avatar); holder.mStatusIcon = (ImageView)view.findViewById(R.id.statusIcon); //holder.mEncryptionIcon = (ImageView)view.findViewById(R.id.encryptionIcon); holder.mContainer = view.findViewById(R.id.message_container); holder.mMediaThumb = (ImageView)view.findViewById(R.id.media_thumbnail); view.setTag(holder); return view; } @Override public void bindView(View view, Context context, Cursor cursor) { ContactView v = (ContactView) view; v.bind(cursor, mSearchString, true); } } public interface ContactListListener { public void openChat (Cursor c); public void showProfile (Cursor c); } public void setListener (ContactListListener listener) { mListener = listener; } private void setContactNickname(int aPosition) { Cursor cursor = (Cursor)mFilterList.getItemAtPosition(aPosition); final IImConnection conn = getConnection (cursor); final String address = cursor.getString(cursor.getColumnIndexOrThrow(Imps.Contacts.USERNAME)); final String nickname = cursor.getString(cursor.getColumnIndexOrThrow(Imps.Contacts.NICKNAME)); final View view = LayoutInflater.from(mContext).inflate(R.layout.alert_dialog_contact_nickname, null); ((TextView)view.findViewById(R.id.contact_address_textview)).setText( address ); ((EditText)view.findViewById(R.id.contact_nickname_edittext)).setText( nickname ); new AlertDialog.Builder(mContext) .setTitle(mContext.getString(R.string.menu_contact_nickname, nickname)) .setView(view) .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); final String newNickname = ((EditText)view.findViewById(R.id.contact_nickname_edittext)).getText().toString(); new Handler().postDelayed(new Runnable() { @Override public void run() { setContactNickname( address, newNickname, conn) ; } }, 500); } }) .setNegativeButton(R.string.cancel, null).show(); } /** * @param value */ protected void setContactNickname(String aAddress, String aNickname, IImConnection conn) { try { IContactListManager listManager = conn.getContactListManager(); int result = listManager.setContactName(aAddress, aNickname); if( result != ImErrorInfo.NO_ERROR ) { Toast.makeText(mContext, mContext.getString(R.string.error_prefix) + result, Toast.LENGTH_LONG).show(); // TODO -LS error handling } } catch( Exception e ) { Toast.makeText(mContext, mContext.getString(R.string.error_prefix) + e.getMessage(), Toast.LENGTH_LONG).show(); // TODO -LS error handling } mFilterList.invalidate(); final InputMethodManager imm = (InputMethodManager)mContext.getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getWindowToken(), 0); } public void removeContactAtPosition(int packedPosition) { removeContact((Cursor)mFilterList.getItemAtPosition(packedPosition)); } void removeContact(Cursor c) { final IImConnection conn = getConnection (c); String nickname = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.NICKNAME)); final String address = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.USERNAME)); DialogInterface.OnClickListener confirmListener = new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { try { if (conn != null) { IContactListManager manager = conn.getContactListManager(); int res = manager.removeContact(address); if (res != ImErrorInfo.NO_ERROR) { mHandler.showAlert(R.string.error, ErrorResUtils.getErrorRes(getResources(), res, address)); } } } catch (RemoteException e) { mHandler.showServiceErrorAlert(e.getLocalizedMessage()); LogCleaner.error(ImApp.LOG_TAG, "remote error",e); } } }; Resources r = getResources(); new AlertDialog.Builder(mContext).setTitle(R.string.confirm) .setMessage(r.getString(R.string.confirm_delete_contact, nickname)) .setPositiveButton(R.string.yes, confirmListener) // default button .setNegativeButton(R.string.no, null).setCancelable(false).show(); } private IImConnection getConnection (Cursor c) { return ImApp.sImApp.getConnection(c.getLong(ContactView.COLUMN_CONTACT_PROVIDER)); } public void blockContactAtPosition(int packedPosition) { blockContact((Cursor)mFilterList.getItemAtPosition(packedPosition)); } void blockContact(Cursor c) { final IImConnection conn = getConnection (c); String nickname = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.NICKNAME)); final String address = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.USERNAME)); DialogInterface.OnClickListener confirmListener = new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { try { IContactListManager manager = conn.getContactListManager(); int res = -1; if (manager.isBlocked(address)) res = manager.unBlockContact(address); else { res = manager.blockContact(address); if (res != ImErrorInfo.NO_ERROR) { mHandler.showAlert(R.string.error, ErrorResUtils.getErrorRes(getResources(), res, address)); } } } catch (RemoteException e) { mHandler.showServiceErrorAlert(e.getLocalizedMessage()); LogCleaner.error(ImApp.LOG_TAG, "remote error",e); } } }; Resources r = getResources(); new AlertDialog.Builder(mContext).setTitle(R.string.confirm) .setMessage(r.getString(R.string.confirm_block_contact, nickname)) .setPositiveButton(R.string.yes, confirmListener) // default button .setNegativeButton(R.string.no, null).setCancelable(false).show(); } public void setLoaderManager(LoaderManager loaderManager, int loaderId) { mLoaderManager = loaderManager; mLoaderId = loaderId; } class MyLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> { @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { StringBuilder buf = new StringBuilder(); if (mSearchString != null) { buf.append(Imps.Contacts.NICKNAME); buf.append(" LIKE "); DatabaseUtils.appendValueToSql(buf, "%" + mSearchString + "%"); buf.append(" OR "); buf.append(Imps.Contacts.USERNAME); buf.append(" LIKE "); DatabaseUtils.appendValueToSql(buf, "%" + mSearchString + "%"); } CursorLoader loader = new CursorLoader(getContext(), mUri, ContactView.CONTACT_PROJECTION, buf == null ? null : buf.toString(), null, Imps.Contacts.DEFAULT_SORT_ORDER); // loader.setUpdateThrottle(10L); return loader; } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor newCursor) { if (newCursor == null) return; // the app was quit or something while this was working newCursor.setNotificationUri(getContext().getContentResolver(), mUri); mContactAdapter.changeCursor(newCursor); if (newCursor != null && newCursor.getCount() == 0) { if (mUri.getPath().contains("/contacts/chatting")) mEmptyView.setText(R.string.empty_conversation_group); else mEmptyView.setText(R.string.empty_contact_list); } } @Override public void onLoaderReset(Loader<Cursor> loader) { mContactAdapter.swapCursor(null); } } }