Skip to content
Snippets Groups Projects
Commit 9c6defe9 authored by Aline Bonnet's avatar Aline Bonnet Committed by Alexandre Lision
Browse files

create a conversation fragment

In the futur, we want to integrate the current conversation in the
home page. To do this, it is necessary to create a conversation
fragment.

The conversation activity calls the conversation fragment. The
activity manages the LocalService and the fragment manages the
conversation management.

Change-Id: If37d76840b0ada744d9da811092d23a5351a3847
Tuleap: #1431
parent 17f8b2c2
No related branches found
No related tags found
No related merge requests found
......@@ -231,7 +231,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
</activity>
<activity
android:name=".client.ConversationActivity"
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"
android:configChanges="screenSize|screenLayout|smallestScreenSize"
android:label="@string/app_name"
android:parentActivityName=".client.HomeActivity"
android:screenOrientation="fullUser"
......
......@@ -27,214 +27,62 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.SystemClock;
import android.support.design.widget.Snackbar;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.util.Pair;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import java.util.List;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.OnEditorAction;
import cx.ring.R;
import cx.ring.adapters.ContactDetailsTask;
import cx.ring.adapters.ConversationAdapter;
import cx.ring.adapters.NumberAdapter;
import cx.ring.application.RingApplication;
import cx.ring.model.Account;
import cx.ring.model.CallContact;
import cx.ring.model.Conference;
import cx.ring.model.Conversation;
import cx.ring.model.Phone;
import cx.ring.model.Uri;
import cx.ring.fragments.ConversationFragment;
import cx.ring.service.LocalService;
import cx.ring.services.AccountService;
import cx.ring.services.CallService;
import cx.ring.utils.ActionHelper;
import cx.ring.utils.ClipboardHelper;
import cx.ring.utils.ContentUriHandler;
public class ConversationActivity extends AppCompatActivity implements
Conversation.ConversationActionCallback,
ClipboardHelper.ClipboardHelperCallback,
ContactDetailsTask.DetailsLoadedCallback {
@Inject
CallService mCallService;
@Inject
AccountService mAccountService;
public class ConversationActivity extends AppCompatActivity {
@BindView(R.id.main_toolbar)
Toolbar mToolbar;
@BindView(R.id.msg_input_txt)
EditText mMsgEditTxt;
@BindView(R.id.msg_send)
View mMsgSendBtn;
@BindView(R.id.ongoingcall_pane)
ViewGroup mBottomPane;
@BindView(R.id.hist_list)
RecyclerView mHistList;
@BindView(R.id.number_selector)
Spinner mNumberSpinner;
private static final String TAG = ConversationActivity.class.getSimpleName();
private static final String CONVERSATION_DELETE = "CONVERSATION_DELETE";
public static final int REQ_ADD_CONTACT = 42;
static final long REFRESH_INTERVAL_MS = 30 * 1000;
private boolean mBound = false;
private boolean mVisible = false;
private AlertDialog mDeleteDialog;
private boolean mDeleteConversation = false;
private LocalService mService = null;
private Conversation mConversation = null;
private Uri mPreferredNumber = null;
private MenuItem mAddContactBtn = null;
private ConversationAdapter mAdapter = null;
private NumberAdapter mNumberAdapter = null;
private final Handler mRefreshTaskHandler = new Handler();
static private Pair<Conversation, Uri> getConversation(LocalService s, Intent i) {
if (s == null || i == null || i.getData() == null)
return new Pair<>(null, null);
String conv_id = i.getData().getLastPathSegment();
Uri number = new Uri(i.getStringExtra("number"));
Log.d(TAG, "getConversation " + conv_id + " " + number);
Conversation conv = s.getConversation(conv_id);
if (conv == null) {
long contact_id = CallContact.contactIdFromId(conv_id);
Log.d(TAG, "no conversation found, contact_id " + contact_id);
CallContact contact = null;
if (contact_id >= 0)
contact = s.findContactById(contact_id);
if (contact == null) {
Uri conv_uri = new Uri(conv_id);
if (!number.isEmpty()) {
contact = s.findContactByNumber(number);
if (contact == null)
contact = CallContact.buildUnknown(conv_uri);
} else {
contact = s.findContactByNumber(conv_uri);
if (contact == null) {
contact = CallContact.buildUnknown(conv_uri);
number = contact.getPhones().get(0).getNumber();
} else {
number = conv_uri;
}
}
}
conv = s.startConversation(contact);
}
Log.d(TAG, "returning " + conv.getContact().getDisplayName() + " " + number);
return new Pair<>(conv, number);
}
static private int getIndex(Spinner spinner, Uri myString) {
for (int i = 0, n = spinner.getCount(); i < n; i++)
if (((Phone) spinner.getItemAtPosition(i)).getNumber().equals(myString))
return i;
return 0;
}
private ConversationFragment mConversationFragment;
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
refreshView(0);
}
private void refreshView(long refreshed) {
Pair<Conversation, Uri> conv = getConversation(mService, getIntent());
mConversation = conv.first;
mPreferredNumber = conv.second;
if (mConversation == null) {
finish();
return;
mConversationFragment.refreshView(0);
}
ActionBar ab = getSupportActionBar();
if (ab != null) {
if (!mConversation.getContact().getPhones().isEmpty()) {
CallContact contact = mCallService.getContact(mConversation.getContact().getPhones().get(0).getNumber());
if (contact != null) {
mConversation.setContact(contact);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_conversation);
ab.setTitle(mConversation.getContact().getDisplayName());
}
ButterKnife.bind(this);
setSupportActionBar(mToolbar);
final CallContact contact = mConversation.getContact();
if (contact != null) {
new ContactDetailsTask(this, contact, this).run();
}
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Conference conf = mConversation.getCurrentCall();
mBottomPane.setVisibility(conf == null ? View.GONE : View.VISIBLE);
if (conf != null) {
Log.d(TAG, "ConversationActivity refreshView " + conf.getId() + " "
+ mConversation.getCurrentCall());
if (mConversationFragment == null) {
mConversationFragment = new ConversationFragment();
getFragmentManager().beginTransaction()
.replace(R.id.main_frame, mConversationFragment, null)
.commit();
}
mAdapter.updateDataset(mConversation.getAggregateHistory(), refreshed);
if (mConversation.getContact().getPhones().size() > 1) {
mNumberSpinner.setVisibility(View.VISIBLE);
mNumberAdapter = new NumberAdapter(ConversationActivity.this,
mConversation.getContact(),
false);
mNumberSpinner.setAdapter(mNumberAdapter);
if (mPreferredNumber == null || mPreferredNumber.isEmpty()) {
mPreferredNumber = new Uri(
mConversation.getLastNumberUsed(mConversation.getLastAccountUsed())
);
}
mNumberSpinner.setSelection(getIndex(mNumberSpinner, mPreferredNumber));
} else {
mNumberSpinner.setVisibility(View.GONE);
mPreferredNumber = mConversation.getContact().getPhones().get(0).getNumber();
if (!mBound) {
Log.d(TAG, "onCreate: Binding service...");
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
mService = null;
}
invalidateOptionsMenu();
}
private ServiceConnection mConnection = new ServiceConnection() {
......@@ -243,28 +91,15 @@ public class ConversationActivity extends AppCompatActivity implements
Log.d(TAG, "ConversationActivity onServiceConnected " + className.getClassName());
mService = ((LocalService.LocalBinder) binder).getService();
mAdapter = new ConversationAdapter(ConversationActivity.this,
mService.get40dpContactCache(),
mService.getThreadPool());
if (mHistList != null) {
mHistList.setAdapter(mAdapter);
}
refreshView(0);
IntentFilter filter = new IntentFilter(LocalService.ACTION_CONF_UPDATE);
registerReceiver(receiver, filter);
mBound = true;
if (mVisible && mConversation != null && !mConversation.isVisible()) {
mConversation.setVisible(true);
mService.readConversation(mConversation);
if (mConversationFragment != null) {
mConversationFragment.setCallback(mService);
mConversationFragment.refreshView(0);
}
if (mDeleteConversation) {
mDeleteDialog = ActionHelper.launchDeleteAction(ConversationActivity.this, mConversation, ConversationActivity.this);
}
mBound = true;
mRefreshTaskHandler.postDelayed(refreshTask, REFRESH_INTERVAL_MS);
}
......@@ -274,19 +109,6 @@ public class ConversationActivity extends AppCompatActivity implements
Log.d(TAG, "ConversationActivity onServiceDisconnected " + arg0.getClassName());
mBound = false;
mRefreshTaskHandler.removeCallbacks(refreshTask);
if (mConversation != null) {
mConversation.setVisible(false);
}
}
};
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive " + intent.getAction() + " " + intent.getDataString());
refreshView(intent.getLongExtra(LocalService.ACTION_CONF_UPDATE_EXTRA_MSG, 0));
if (mAdapter.getItemCount() > 0)
mHistList.smoothScrollToPosition(mAdapter.getItemCount() - 1);
}
};
......@@ -294,291 +116,49 @@ public class ConversationActivity extends AppCompatActivity implements
private long lastRefresh = 0;
public void run() {
if (lastRefresh == 0)
if (lastRefresh == 0) {
lastRefresh = SystemClock.uptimeMillis();
else
} else {
lastRefresh += REFRESH_INTERVAL_MS;
mAdapter.notifyDataSetChanged();
}
mRefreshTaskHandler.postAtTime(this, lastRefresh + REFRESH_INTERVAL_MS);
}
};
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_conversation);
ButterKnife.bind(this);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Dependency injection
((RingApplication) getApplication()).getRingInjectionComponent().inject(this);
if (mBottomPane != null) {
mBottomPane.setVisibility(View.GONE);
}
LinearLayoutManager mLayoutManager = new LinearLayoutManager(this);
mLayoutManager.setStackFromEnd(true);
if (mHistList != null) {
mHistList.setLayoutManager(mLayoutManager);
mHistList.setAdapter(mAdapter);
mHistList.setItemAnimator(new DefaultItemAnimator());
}
// reload delete conversation state (before rotation)
mDeleteConversation = savedInstanceState != null && savedInstanceState.getBoolean(CONVERSATION_DELETE);
if (!mBound) {
Log.d(TAG, "onCreate: Binding service...");
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
mService = null;
}
}
@OnClick(R.id.msg_send)
public void sendMessageText(View sender){
CharSequence txt = mMsgEditTxt.getText();
if (txt.length() > 0) {
onSendTextMessage(txt.toString());
mMsgEditTxt.setText("");
}
}
@OnEditorAction(R.id.msg_input_txt)
public boolean actionSendMsgText(TextView view, int actionId, KeyEvent event){
switch (actionId) {
case EditorInfo.IME_ACTION_SEND:
CharSequence txt = mMsgEditTxt.getText();
if (txt.length() > 0) {
onSendTextMessage(mMsgEditTxt.getText().toString());
mMsgEditTxt.setText("");
}
return true;
}
return false;
}
@OnClick(R.id.ongoingcall_pane)
public void onClick(View v) {
startActivity(new Intent(Intent.ACTION_VIEW)
.setClass(getApplicationContext(), CallActivity.class)
.setData(android.net.Uri.withAppendedPath(ContentUriHandler.CONFERENCE_CONTENT_URI,
mConversation.getCurrentCall().getId())));
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause");
mVisible = false;
if (mConversation != null) {
mService.readConversation(mConversation);
mConversation.setVisible(false);
}
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume " + mConversation);
mVisible = true;
if (mConversation != null) {
mConversation.setVisible(true);
if (mBound && mService != null) {
mService.readConversation(mConversation);
}
}
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive " + intent.getAction() + " " + intent.getDataString());
mConversationFragment.refreshView(intent.getLongExtra(LocalService.ACTION_CONF_UPDATE_EXTRA_MSG, 0));
}
};
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQ_ADD_CONTACT:
if (mService != null) mService.refreshConversations();
break;
}
}
@Override
protected void onDestroy() {
if (mBound) {
unregisterReceiver(receiver);
unbindService(mConnection);
mBound = false;
}
if (mDeleteConversation) {
mDeleteDialog.dismiss();
}
super.onDestroy();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// persist the delete popup state in case of Activity rotation
mDeleteConversation = mDeleteDialog != null && mDeleteDialog.isShowing();
outState.putBoolean(CONVERSATION_DELETE, mDeleteConversation);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (mAddContactBtn != null) {
mAddContactBtn.setVisible(mConversation != null && mConversation.getContact().getId() < 0);
case ConversationFragment.REQ_ADD_CONTACT:
if (mService != null) {
mService.refreshConversations();
}
return super.onPrepareOptionsMenu(menu);
break;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.conversation_actions, menu);
mAddContactBtn = menu.findItem(R.id.menuitem_addcontact);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
public void onBackPressed() {
startActivity(new Intent(this, HomeActivity.class));
finish();
return true;
case R.id.conv_action_audiocall:
onCallWithVideo(false);
return true;
case R.id.conv_action_videocall:
onCallWithVideo(true);
return true;
case R.id.menuitem_addcontact:
startActivityForResult(ActionHelper.getAddNumberIntentForContact(mConversation.getContact()), REQ_ADD_CONTACT);
return true;
case R.id.menuitem_delete:
mDeleteDialog = ActionHelper.launchDeleteAction(this, this.mConversation, this);
return true;
case R.id.menuitem_copy_content:
ActionHelper.launchCopyNumberToClipboardFromContact(this,
this.mConversation.getContact(), this);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/**
* Guess account and number to use to initiate a call
*/
private Pair<Account, Uri> guess() {
Uri number = mNumberAdapter == null ?
mPreferredNumber : ((Phone) mNumberSpinner.getSelectedItem()).getNumber();
Account a = mAccountService.getAccount(mConversation.getLastAccountUsed());
// Guess account from number
if (a == null && number != null)
a = mAccountService.guessAccount(number);
// Guess number from account/call history
if (a != null && (number == null/* || number.isEmpty()*/))
number = new Uri(mConversation.getLastNumberUsed(a.getAccountID()));
// If no account found, use first active
if (a == null) {
List<Account> accs = mAccountService.getAccounts();
if (accs.isEmpty()) {
finish();
return null;
} else
a = accs.get(0);
}
// If no number found, use first from contact
if (number == null || number.isEmpty())
number = mConversation.getContact().getPhones().get(0).getNumber();
return new Pair<>(a, number);
}
private void onSendTextMessage(String txt) {
Conference conf = mConversation == null ? null : mConversation.getCurrentCall();
if (conf == null || !conf.isOnGoing()) {
Pair<Account, Uri> g = guess();
if (g == null || g.first == null)
return;
mService.sendTextMessage(g.first.getAccountID(), g.second, txt);
} else {
mService.sendTextMessage(conf, txt);
}
}
private void onCallWithVideo(boolean has_video) {
Conference conf = mConversation.getCurrentCall();
if (conf != null) {
startActivity(new Intent(Intent.ACTION_VIEW)
.setClass(getApplicationContext(), CallActivity.class)
.setData(android.net.Uri.withAppendedPath(ContentUriHandler.CONFERENCE_CONTENT_URI, conf.getId())));
return;
}
Pair<Account, Uri> g = guess();
if (g == null || g.first == null)
return;
try {
Intent intent = new Intent(CallActivity.ACTION_CALL)
.setClass(getApplicationContext(), CallActivity.class)
.putExtra("account", g.first.getAccountID())
.putExtra("video", has_video)
.setData(android.net.Uri.parse(g.second.getRawUriString()));
startActivityForResult(intent, HomeActivity.REQUEST_CODE_CALL);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, e.toString());
}
}
@Override
public void deleteConversation(Conversation conversation) {
if (mService != null) {
mService.deleteConversation(conversation);
}
finish();
}
@Override
public void copyContactNumberToClipboard(String contactNumber) {
ClipboardHelper.copyNumberToClipboard(this, contactNumber, this);
}
@Override
public void clipBoardDidCopyNumber(String copiedNumber) {
View view = this.findViewById(android.R.id.content);
if (view != null) {
String snackbarText = getString(R.string.conversation_action_copied_peer_number_clipboard,
Phone.getShortenedNumber(copiedNumber));
Snackbar.make(view, snackbarText, Snackbar.LENGTH_LONG).show();
}
}
@Override
public void onDetailsLoaded(Bitmap bmp, String formattedName) {
ActionBar ab = getSupportActionBar();
if (ab != null && formattedName != null) {
ab.setTitle(formattedName);
}
public void onDestroy() {
super.onDestroy();
if (mBound) {
unregisterReceiver(receiver);
unbindService(mConnection);
mBound = false;
}
@Override
public void onBackPressed() {
startActivity(new Intent(this, HomeActivity.class));
finish();
}
}
......@@ -27,12 +27,12 @@ import cx.ring.application.RingApplication;
import cx.ring.client.AccountEditionActivity;
import cx.ring.client.AccountWizard;
import cx.ring.client.CallActivity;
import cx.ring.client.ConversationActivity;
import cx.ring.client.HomeActivity;
import cx.ring.fragments.AccountCreationFragment;
import cx.ring.fragments.AccountMigrationFragment;
import cx.ring.fragments.AccountsManagementFragment;
import cx.ring.fragments.CallFragment;
import cx.ring.fragments.ConversationFragment;
import cx.ring.fragments.DeviceAccountFragment;
import cx.ring.fragments.MediaPreferenceFragment;
import cx.ring.fragments.ProfileCreationFragment;
......@@ -69,8 +69,6 @@ public interface RingInjectionComponent {
void inject(CallActivity activity);
void inject(ConversationActivity activity);
void inject(HomeActivity activity);
void inject(AccountWizard activity);
......@@ -105,6 +103,8 @@ public interface RingInjectionComponent {
void inject(RegisterNameDialog dialog);
void inject(ConversationFragment fragment);
void inject(LocalService service);
void inject(DRingService service);
......
......@@ -452,7 +452,7 @@ public class CallFragment extends Fragment implements CallInterface, ContactDeta
break;
}
startActivityForResult(ActionHelper.getAddNumberIntentForContact(firstParticipant.getContact()),
ConversationActivity.REQ_ADD_CONTACT);
ConversationFragment.REQ_ADD_CONTACT);
break;
case R.id.menuitem_speaker:
audioManager.setSpeakerphoneOn(!audioManager.isSpeakerphoneOn());
......
package cx.ring.fragments;
import android.app.Fragment;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.util.Pair;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import java.util.List;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.OnEditorAction;
import cx.ring.R;
import cx.ring.adapters.ContactDetailsTask;
import cx.ring.adapters.ConversationAdapter;
import cx.ring.adapters.NumberAdapter;
import cx.ring.application.RingApplication;
import cx.ring.client.CallActivity;
import cx.ring.client.ConversationActivity;
import cx.ring.client.HomeActivity;
import cx.ring.model.Account;
import cx.ring.model.CallContact;
import cx.ring.model.Conference;
import cx.ring.model.Conversation;
import cx.ring.model.Phone;
import cx.ring.model.Uri;
import cx.ring.service.LocalService;
import cx.ring.services.AccountService;
import cx.ring.services.CallService;
import cx.ring.utils.ActionHelper;
import cx.ring.utils.ClipboardHelper;
import cx.ring.utils.ContentUriHandler;
public class ConversationFragment extends Fragment implements
Conversation.ConversationActionCallback,
ClipboardHelper.ClipboardHelperCallback,
ContactDetailsTask.DetailsLoadedCallback {
@Inject
CallService mCallService;
@Inject
AccountService mAccountService;
@BindView(R.id.msg_input_txt)
EditText mMsgEditTxt;
@BindView(R.id.ongoingcall_pane)
ViewGroup mBottomPane;
@BindView(R.id.hist_list)
RecyclerView mHistList;
@BindView(R.id.number_selector)
Spinner mNumberSpinner;
private static final String TAG = ConversationFragment.class.getSimpleName();
private static final String CONVERSATION_DELETE = "CONVERSATION_DELETE";
public static final int REQ_ADD_CONTACT = 42;
private boolean mVisible = false;
private AlertDialog mDeleteDialog;
private boolean mDeleteConversation = false;
private LocalService mService = null;
private Conversation mConversation = null;
private Uri mPreferredNumber = null;
private MenuItem mAddContactBtn = null;
private ConversationAdapter mAdapter = null;
private NumberAdapter mNumberAdapter = null;
private static Pair<Conversation, Uri> getConversation(LocalService service, Intent intent) {
if (service == null || intent == null || intent.getData() == null) {
return new Pair<>(null, null);
}
String conversationId = intent.getData().getLastPathSegment();
Uri number = new Uri(intent.getStringExtra("number"));
Log.d(TAG, "getConversation " + conversationId + " " + number);
Conversation conversation = service.getConversation(conversationId);
if (conversation == null) {
long contactId = CallContact.contactIdFromId(conversationId);
Log.d(TAG, "no conversation found, contact_id " + contactId);
CallContact contact = null;
if (contactId >= 0) {
contact = service.findContactById(contactId);
}
if (contact == null) {
Uri convUri = new Uri(conversationId);
if (!number.isEmpty()) {
contact = service.findContactByNumber(number);
if (contact == null) {
contact = CallContact.buildUnknown(convUri);
}
} else {
contact = service.findContactByNumber(convUri);
if (contact == null) {
contact = CallContact.buildUnknown(convUri);
number = contact.getPhones().get(0).getNumber();
} else {
number = convUri;
}
}
}
conversation = service.startConversation(contact);
}
Log.d(TAG, "returning " + conversation.getContact().getDisplayName() + " " + number);
return new Pair<>(conversation, number);
}
private static int getIndex(Spinner spinner, Uri myString) {
for (int i = 0, n = spinner.getCount(); i < n; i++)
if (((Phone) spinner.getItemAtPosition(i)).getNumber().equals(myString)) {
return i;
}
return 0;
}
public void refreshView(long refreshed) {
if (mService == null) {
return;
}
Pair<Conversation, Uri> conversation = getConversation(mService, getActivity().getIntent());
mConversation = conversation.first;
mPreferredNumber = conversation.second;
if (mConversation == null) {
return;
}
if (!mConversation.getContact().getPhones().isEmpty()) {
CallContact contact = mCallService.getContact(mConversation.getContact().getPhones().get(0).getNumber());
if (contact != null) {
mConversation.setContact(contact);
}
if (((ConversationActivity) getActivity()).getSupportActionBar() != null) {
((ConversationActivity) getActivity()).getSupportActionBar().setTitle(mConversation.getContact().getDisplayName());
}
}
final CallContact contact = mConversation.getContact();
if (contact != null) {
new ContactDetailsTask(getActivity(), contact, this).run();
}
Conference conference = mConversation.getCurrentCall();
mBottomPane.setVisibility(conference == null ? View.GONE : View.VISIBLE);
if (conference != null) {
Log.d(TAG, "ConversationFragment refreshView " + conference.getId() + " "
+ mConversation.getCurrentCall());
}
mAdapter.updateDataset(mConversation.getAggregateHistory(), refreshed);
if (mConversation.getContact().getPhones().size() > 1) {
mNumberSpinner.setVisibility(View.VISIBLE);
mNumberAdapter = new NumberAdapter(getActivity(),
mConversation.getContact(),
false);
mNumberSpinner.setAdapter(mNumberAdapter);
if (mPreferredNumber == null || mPreferredNumber.isEmpty()) {
mPreferredNumber = new Uri(
mConversation.getLastNumberUsed(mConversation.getLastAccountUsed())
);
}
mNumberSpinner.setSelection(getIndex(mNumberSpinner, mPreferredNumber));
} else {
mNumberSpinner.setVisibility(View.GONE);
mPreferredNumber = mConversation.getContact().getPhones().get(0).getNumber();
}
if (mAdapter.getItemCount() > 0) {
mHistList.smoothScrollToPosition(mAdapter.getItemCount() - 1);
}
getActivity().invalidateOptionsMenu();
}
public void setCallback(LocalService callback) {
mService = callback;
mAdapter = new ConversationAdapter(getActivity(),
mService.get40dpContactCache(),
mService.getThreadPool());
if (mHistList != null) {
mHistList.setAdapter(mAdapter);
}
if (mVisible && mConversation != null && !mConversation.isVisible()) {
mConversation.setVisible(true);
mService.readConversation(mConversation);
}
if (mDeleteConversation) {
mDeleteDialog = ActionHelper.launchDeleteAction(getActivity(), mConversation, this);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View inflatedView = inflater.inflate(R.layout.frag_conversation, container, false);
ButterKnife.bind(this, inflatedView);
// Dependency injection
((RingApplication) getActivity().getApplication()).getRingInjectionComponent().inject(this);
if (mBottomPane != null) {
mBottomPane.setVisibility(View.GONE);
}
LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
mLayoutManager.setStackFromEnd(true);
if (mHistList != null) {
mHistList.setLayoutManager(mLayoutManager);
mHistList.setAdapter(mAdapter);
mHistList.setItemAnimator(new DefaultItemAnimator());
}
// reload delete conversation state (before rotation)
mDeleteConversation = savedInstanceState != null && savedInstanceState.getBoolean(CONVERSATION_DELETE);
setHasOptionsMenu(true);
return inflatedView;
}
@OnClick(R.id.msg_send)
public void sendMessageText(View sender) {
CharSequence txt = mMsgEditTxt.getText();
if (txt.length() > 0) {
onSendTextMessage(txt.toString());
mMsgEditTxt.setText("");
}
}
@OnEditorAction(R.id.msg_input_txt)
public boolean actionSendMsgText(TextView view, int actionId, KeyEvent event) {
switch (actionId) {
case EditorInfo.IME_ACTION_SEND:
CharSequence txt = mMsgEditTxt.getText();
if (txt.length() > 0) {
onSendTextMessage(mMsgEditTxt.getText().toString());
mMsgEditTxt.setText("");
}
return true;
}
return false;
}
@OnClick(R.id.ongoingcall_pane)
public void onClick(View view) {
startActivity(new Intent(Intent.ACTION_VIEW)
.setClass(getActivity().getApplicationContext(), CallActivity.class)
.setData(android.net.Uri.withAppendedPath(ContentUriHandler.CONFERENCE_CONTENT_URI,
mConversation.getCurrentCall().getId())));
}
@Override
public void onPause() {
super.onPause();
Log.d(TAG, "onPause");
mVisible = false;
if (mConversation != null) {
mService.readConversation(mConversation);
mConversation.setVisible(false);
}
}
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume " + mConversation);
mVisible = true;
if (mConversation != null) {
mConversation.setVisible(true);
if (mService != null) {
mService.readConversation(mConversation);
}
}
}
@Override
public void onDestroy() {
if (mDeleteConversation) {
mDeleteDialog.dismiss();
}
super.onDestroy();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// persist the delete popup state in case of Activity rotation
mDeleteConversation = mDeleteDialog != null && mDeleteDialog.isShowing();
outState.putBoolean(CONVERSATION_DELETE, mDeleteConversation);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
if (mAddContactBtn != null) {
mAddContactBtn.setVisible(mConversation != null && mConversation.getContact().getId() < 0);
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.conversation_actions, menu);
mAddContactBtn = menu.findItem(R.id.menuitem_addcontact);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
startActivity(new Intent(getActivity(), HomeActivity.class));
return true;
case R.id.conv_action_audiocall:
onCallWithVideo(false);
return true;
case R.id.conv_action_videocall:
onCallWithVideo(true);
return true;
case R.id.menuitem_addcontact:
startActivityForResult(ActionHelper.getAddNumberIntentForContact(mConversation.getContact()), REQ_ADD_CONTACT);
return true;
case R.id.menuitem_delete:
mDeleteDialog = ActionHelper.launchDeleteAction(getActivity(),
this.mConversation,
this);
return true;
case R.id.menuitem_copy_content:
ActionHelper.launchCopyNumberToClipboardFromContact(getActivity(),
this.mConversation.getContact(),
this);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/**
* Guess account and number to use to initiate a call
*/
private Pair<Account, Uri> guess() {
Uri number = mNumberAdapter == null ?
mPreferredNumber : ((Phone) mNumberSpinner.getSelectedItem()).getNumber();
Account account = mAccountService.getAccount(mConversation.getLastAccountUsed());
// Guess account from number
if (account == null && number != null) {
account = mAccountService.guessAccount(number);
}
// Guess number from account/call history
if (account != null && number == null) {
number = new Uri(mConversation.getLastNumberUsed(account.getAccountID()));
}
// If no account found, use first active
if (account == null) {
List<Account> accounts = mAccountService.getAccounts();
if (accounts.isEmpty()) {
return null;
} else
account = accounts.get(0);
}
// If no number found, use first from contact
if (number == null || number.isEmpty()) {
number = mConversation.getContact().getPhones().get(0).getNumber();
}
return new Pair<>(account, number);
}
private void onCallWithVideo(boolean has_video) {
Conference conf = mConversation.getCurrentCall();
if (conf != null) {
startActivity(new Intent(Intent.ACTION_VIEW)
.setClass(getActivity().getApplicationContext(), CallActivity.class)
.setData(android.net.Uri.withAppendedPath(ContentUriHandler.CONFERENCE_CONTENT_URI, conf.getId())));
return;
}
Pair<Account, Uri> guess = guess();
if (guess == null || guess.first == null) {
return;
}
try {
Intent intent = new Intent(CallActivity.ACTION_CALL)
.setClass(getActivity().getApplicationContext(), CallActivity.class)
.putExtra("account", guess.first.getAccountID())
.putExtra("video", has_video)
.setData(android.net.Uri.parse(guess.second.getRawUriString()));
startActivityForResult(intent, HomeActivity.REQUEST_CODE_CALL);
} catch (Exception e) {
Log.e(TAG, "Error during call", e);
}
}
private void onSendTextMessage(String txt) {
Conference conference = mConversation == null ? null : mConversation.getCurrentCall();
if (conference == null || !conference.isOnGoing()) {
Pair<Account, Uri> guess = guess();
if (guess == null || guess.first == null) {
return;
}
mService.sendTextMessage(guess.first.getAccountID(), guess.second, txt);
} else {
mService.sendTextMessage(conference, txt);
}
}
@Override
public void deleteConversation(Conversation conversation) {
if (mService != null) {
mService.deleteConversation(conversation);
getActivity().finish();
}
}
@Override
public void copyContactNumberToClipboard(String contactNumber) {
ClipboardHelper.copyNumberToClipboard(getActivity(), contactNumber, this);
}
@Override
public void clipBoardDidCopyNumber(String copiedNumber) {
View view = getActivity().findViewById(android.R.id.content);
if (view != null) {
String snackbarText = getString(R.string.conversation_action_copied_peer_number_clipboard,
Phone.getShortenedNumber(copiedNumber));
Snackbar.make(view, snackbarText, Snackbar.LENGTH_LONG).show();
}
}
@Override
public void onDetailsLoaded(Bitmap bmp, String formattedName) {
ActionBar actionBar = ((ConversationActivity) getActivity()).getSupportActionBar();
if (actionBar != null && formattedName != null) {
actionBar.setTitle(formattedName);
}
}
}
\ No newline at end of file
......@@ -5,7 +5,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ebeff0"
android:orientation="vertical"
tools:context=".client.ConversationActivity">
<android.support.v7.widget.Toolbar
......@@ -25,90 +24,11 @@
app:elevation="4dp"
app:titleTextAppearance="@style/ToolbarTitle" />
<android.support.v7.widget.RecyclerView
android:id="@+id/hist_list"
<FrameLayout
android:id="@+id/main_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentStart="true"
android:layout_below="@id/main_toolbar"
android:clipToPadding="false"
android:divider="@null"
android:listSelector="@android:color/transparent"
android:paddingBottom="60dp"
android:paddingTop="8dp"
tools:listitem="@layout/item_conv_msg_peer" />
<RelativeLayout
android:id="@+id/ongoingcall_pane"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_below="@id/main_toolbar"
android:background="#e3c1c1">
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_margin="10dp"
android:text="@string/ongoing_call"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/text_color_primary" />
</RelativeLayout>
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/userInputMessageCardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentStart="true"
android:layout_marginBottom="16dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
card_view:cardCornerRadius="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Spinner
android:id="@+id/number_selector"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:visibility="visible"
tools:listitem="@layout/item_number_selected" />
<EditText
android:id="@+id/msg_input_txt"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@null"
android:hint="@string/write_a_message"
android:imeOptions="actionSend|flagNoExtractUi"
android:inputType="textShortMessage|textImeMultiLine|text|textMultiLine|textCapSentences"
android:maxLines="5"
android:padding="8dp" />
<ImageButton
android:id="@+id/msg_send"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/send_message"
android:padding="8dp"
android:src="@drawable/ic_send_black"
android:tint="@android:color/darker_gray" />
</LinearLayout>
</android.support.v7.widget.CardView>
android:layout_below="@+id/main_toolbar" />
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/hist_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:clipToPadding="false"
android:divider="@null"
android:listSelector="@android:color/transparent"
android:paddingBottom="60dp"
android:paddingTop="8dp"
tools:listitem="@layout/item_conv_msg_peer" />
<RelativeLayout
android:id="@+id/ongoingcall_pane"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_below="@id/main_toolbar"
android:background="#e3c1c1">
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_margin="10dp"
android:text="@string/ongoing_call"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/text_color_primary" />
</RelativeLayout>
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/userInputMessageCardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentStart="true"
android:layout_marginBottom="16dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
card_view:cardCornerRadius="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Spinner
android:id="@+id/number_selector"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:visibility="visible"
tools:listitem="@layout/item_number_selected" />
<EditText
android:id="@+id/msg_input_txt"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@null"
android:hint="@string/write_a_message"
android:imeOptions="actionSend|flagNoExtractUi"
android:inputType="textShortMessage|textImeMultiLine|text|textMultiLine|textCapSentences"
android:maxLines="5"
android:padding="8dp" />
<ImageButton
android:id="@+id/msg_send"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/send_message"
android:padding="8dp"
android:src="@drawable/ic_send_black"
android:tint="@android:color/darker_gray" />
</LinearLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment