Skip to content

Commit

Permalink
Add fragment of recent calls
Browse files Browse the repository at this point in the history
  • Loading branch information
ZhiruiLi committed Jul 12, 2017
1 parent bbf91fd commit 27b2427
Show file tree
Hide file tree
Showing 14 changed files with 433 additions and 30 deletions.
4 changes: 4 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ dependencies {
compile 'com.tencent.ilivesdk:ilivesdk:1.5.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.1.0'
compile 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
compile 'com.jakewharton.rxbinding2:rxbinding-appcompat-v7:2.0.0'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile 'com.android.support:support-v4:25.3.1'
compile 'com.google.android:flexbox:0.3.0'
testCompile 'junit:junit:4.12'
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.design.widget.Snackbar;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;

Expand All @@ -25,6 +22,12 @@
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;

import static com.example.zhiruili.videoconf.utils.TextUtils.isPasswordValid;
import static com.example.zhiruili.videoconf.utils.TextUtils.isUserNameValid;

/**
* 注册登录页
*/
public class LoginActivity extends AppCompatActivity {

private static final String TAG = LoginActivity.class.getSimpleName();
Expand Down Expand Up @@ -170,31 +173,20 @@ private void attemptRegister() {
}
mLoginDisposable = null;
}

);
}

private void gotoMain() {
Intent intent = new Intent();
intent.setClass(this, MainActivity.class);
intent.putExtra(getString(R.string.intent_extra_has_login), true);
startActivity(intent);
}

private boolean isUserNameValid(String userName) {
return userName.length() >= 4 &&
userName.length() <= 24 &&
userName.matches("^[A-Za-z0-9]*[A-Za-z][A-Za-z0-9]*$");
}

private boolean isPasswordValid(String password) {
return password.length() >= 8 && password.length() <= 16 && password.matches("^[A-Za-z0-9]*$");
}

private void showProgress(final boolean show) {
int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
ViewUtils.animShowOrHideView(mLoginFormView, !show, shortAnimTime);
ViewUtils.animShowOrHideView(mProgressView, show, shortAnimTime);
}

}

126 changes: 116 additions & 10 deletions app/src/main/java/com/example/zhiruili/videoconf/MainActivity.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,59 @@
package com.example.zhiruili.videoconf;


import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.design.widget.BottomNavigationView;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.ViewGroup;

import com.example.zhiruili.videoconf.account.ILiveHelper;

import java.util.List;

import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;

public class MainActivity extends AppCompatActivity {
/**
* 应用主界面
*/
public class MainActivity
extends AppCompatActivity
implements RecentCallsFragment.OnFragmentInteractionListener {

private static final String TAG = MainActivity.class.getSimpleName();

private ViewGroup mMainContainer;

// 是否登录
private boolean mHasLogin = false;
// 当前导航 tab id
private int mCurrNavItemId = -1;
// 导航 tab 点击事件监听器
private BottomNavigationView.OnNavigationItemSelectedListener
mOnNavigationItemSelectedListener = item -> {

Log.d(TAG, "Select item " + item.getItemId());
int itemId = item.getItemId();
if (itemId == mCurrNavItemId) {
return false;
}
if (itemId == R.id.navigation_recent_calls) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content_container, RecentCallsFragment.newInstance())
.commit();
} else if (itemId == R.id.navigation_contacts) {

private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = item -> {
Log.d(TAG, "select item " + item.getItemId());
return false;
} else {
return false;
}
return true;
};

@Override
Expand All @@ -36,8 +64,17 @@ protected void onCreate(Bundle savedInstanceState) {
if (ILiveHelper.initSdk(getApplicationContext(), AppConstants.APP_ID, AppConstants.ACCOUNT_TYPE)) {
Log.v(TAG, "Init iLive SDK success");
} else {
Log.v(TAG, "Call init multi time");
Log.v(TAG, "Call init multi times");
}
Intent intent = getIntent();
// 从 LoginActivity 登录后跳转而来
mHasLogin = intent.getBooleanExtra(getString(R.string.intent_extra_has_login), false);
if (mHasLogin) {
Log.v(TAG, "User has login");
initViews();
return;
}
// 确认是否有登录信息
SharedPreferences pref = getSharedPreferences(getString(R.string.shared_pref_id_user_account), MODE_PRIVATE);
String userName = pref.getString(getString(R.string.shared_pref_key_user_name), null);
String sign = pref.getString(getString(R.string.shared_pref_key_signature), null);
Expand All @@ -50,18 +87,25 @@ protected void onCreate(Bundle savedInstanceState) {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
_ignore -> {
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
navigation.setSelectedItemId(0);
Log.v(TAG, "login success");
mHasLogin = true;
initViews();
},
err -> {
Log.e(TAG, "login fail", err);
err.printStackTrace();
Snackbar.make(mMainContainer, getString(R.string.label_login_fail), Snackbar.LENGTH_SHORT).show();
gotoLogin();
});
}
}

private void initViews() {
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
navigation.setSelectedItemId(R.id.navigation_recent_calls);
}

private void bindViews() {
mMainContainer = (ViewGroup) findViewById(R.id.main_container);
}
Expand All @@ -73,12 +117,74 @@ private void gotoLogin() {
finish();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_logout) {
logout();
return true;
} else {
return super.onOptionsItemSelected(item);
}
}

/**
* 注销并跳转到登录页
*/
private void logout() {
ILiveHelper
.logout()
.map(_ignore -> getSharedPreferences(getString(R.string.shared_pref_id_user_account), MODE_PRIVATE)
.edit()
.remove(getString(R.string.shared_pref_key_user_name))
.remove(getString(R.string.shared_pref_key_password))
.remove(getString(R.string.shared_pref_key_signature))
.commit())
.subscribeOn(Schedulers.io())
.subscribe(
_ignore -> {
Log.v(TAG, "logout success");
Snackbar.make(mMainContainer, getString(R.string.label_logout_success), Snackbar.LENGTH_SHORT).show();
gotoLogin();
},
err -> {
Log.e(TAG, "logout error", err);
err.printStackTrace();
gotoLogin();
}
);
}

@Override
protected void onDestroy() {
super.onDestroy();
if (mHasLogin) {
// TODO: logout
ILiveHelper
.logout()
.subscribeOn(Schedulers.io())
.subscribe(
_ignore -> Log.v(TAG, "logout success"),
err -> {
Log.e(TAG, "logout error", err);
err.printStackTrace();
}
);
mHasLogin = false;
}
}

@Override
public void startCalling(List<String> calledAccounts) {
StringBuilder builder = new StringBuilder();
for (String s : calledAccounts) {
builder.append(s).append(", ");
}
Snackbar.make(mMainContainer, builder.toString(), Snackbar.LENGTH_SHORT).show();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package com.example.zhiruili.videoconf;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.AppCompatButton;
import android.support.v7.widget.AppCompatImageButton;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;

import com.example.zhiruili.videoconf.utils.TextUtils;
import com.example.zhiruili.videoconf.utils.ViewCreator;
import com.google.android.flexbox.FlexboxLayout;
import com.jakewharton.rxbinding2.view.RxView;
import com.jakewharton.rxbinding2.view.RxViewGroup;
import com.jakewharton.rxbinding2.widget.RxTextView;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.example.zhiruili.videoconf.utils.TextUtils.isUserNameValid;

public class RecentCallsFragment extends Fragment {

private OnFragmentInteractionListener mInteractionListener;

private FlexboxLayout mWaitedToCalledBuffer;
private EditText mCalledAccountEditText;
private AppCompatImageButton mAddCalledAccountButton;
private AppCompatButton mStartCallingButton;
private RecyclerView mRecentCallsList;

public RecentCallsFragment() { }

public static RecentCallsFragment newInstance() {
RecentCallsFragment fragment = new RecentCallsFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) { }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_recent_calls, container, false);
bindViews(rootView);
initViews();
return rootView;
}

private void bindViews(View rootView) {
mWaitedToCalledBuffer = (FlexboxLayout) rootView.findViewById(R.id.fbl_waited_to_called_buffer);
mCalledAccountEditText = (EditText) rootView.findViewById(R.id.et_called_account_input);
mAddCalledAccountButton = (AppCompatImageButton) rootView.findViewById(R.id.ib_add_called_account);
mStartCallingButton = (AppCompatButton) rootView.findViewById(R.id.btn_start_calling);
mRecentCallsList = (RecyclerView) rootView.findViewById(R.id.rv_recent_calls_list);
}

private void initViews() {

RxViewGroup
.changeEvents(mWaitedToCalledBuffer)
.map(ignore -> mWaitedToCalledBuffer.getFlexItemCount() > 0)
.subscribe(show -> mStartCallingButton.setVisibility(show ? View.VISIBLE : View.GONE));

RxTextView
.afterTextChangeEvents(mCalledAccountEditText)
.map(_ignore -> mCalledAccountEditText.getText().toString().trim())
.map(text -> text.length() > 0)
.subscribe(show -> mAddCalledAccountButton.setVisibility(show ? View.VISIBLE : View.GONE));

RxView
.clicks(mAddCalledAccountButton)
.throttleFirst(500, TimeUnit.MILLISECONDS)
.map(_ignore -> mCalledAccountEditText.getText().toString().trim())
.doOnNext(account -> {
if (!isUserNameValid(account)) {
mCalledAccountEditText.setError(getString(R.string.error_invalid_user_name));
}
})
.filter(TextUtils::isUserNameValid)
.map(account -> ViewCreator.createTag(getActivity(), account, account, mWaitedToCalledBuffer::removeView))
.doOnNext(_ignore -> mCalledAccountEditText.setText(""))
.subscribe(tag -> mWaitedToCalledBuffer.addView(tag));

RxView
.clicks(mStartCallingButton)
.throttleFirst(500, TimeUnit.MILLISECONDS)
.filter(_ignore -> mWaitedToCalledBuffer.getFlexItemCount() > 0)
.map(_ignore -> mWaitedToCalledBuffer.getChildCount())
.map(count ->
new ArrayList<String>() {{
for (int i = 0; i < count; ++i) {
add(mWaitedToCalledBuffer.getFlexItemAt(i).getTag().toString());
}
}}
)
.subscribe(mInteractionListener::startCalling);
}

@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mInteractionListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}

@Override
public void onDetach() {
super.onDetach();
mInteractionListener = null;
}

public interface OnFragmentInteractionListener {
void startCalling(List<String> calledAccounts);
}
}
Loading

0 comments on commit 27b2427

Please sign in to comment.