diff --git a/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java b/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java index 9a9589423020c591fb5ff32ab8b8e2ddcab71d9c..0917f600d64e516097b5b0cee4471da8a2921251 100644 --- a/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java +++ b/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java @@ -475,6 +475,10 @@ public class HomeActivity extends AppCompatActivity implements LocalService.Call if (fContent == null) { fContent = new SmartListFragment(); fragmentManager.beginTransaction().replace(R.id.main_frame, fContent, HOME_TAG).addToBackStack(HOME_TAG).commit(); + + if (fMenuHead != null) { + fMenuHead.registerAccountSelectionListener((MenuHeaderView.MenuHeaderAccountSelectionListener) fContent); + } } else if (fContent instanceof Refreshable) { fragmentManager.beginTransaction().replace(R.id.main_frame, fContent).addToBackStack(HOME_TAG).commit(); ((Refreshable) fContent).refresh(); diff --git a/ring-android/app/src/main/java/cx/ring/fragments/ShareFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/ShareFragment.java index 248ab4baea3774725175e8d62f149f27c4375449..f63d5100e4f8930fe712f7a281929b081d1b4682 100644 --- a/ring-android/app/src/main/java/cx/ring/fragments/ShareFragment.java +++ b/ring-android/app/src/main/java/cx/ring/fragments/ShareFragment.java @@ -83,7 +83,7 @@ public class ShareFragment extends Fragment implements MenuHeaderView.MenuHeader } private void updateView() { - if (!TextUtils.isEmpty(mUriToShow)) { + if (!TextUtils.isEmpty(mUriToShow) && mQrImage != null) { Bitmap qrBitmap = QRCodeUtils.encodeStringAsQrBitmap(mUriToShow, mQrImage.getMeasuredWidth()); mQrImage.setImageBitmap(qrBitmap); } diff --git a/ring-android/app/src/main/java/cx/ring/fragments/SmartListFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/SmartListFragment.java index cdd05f23005d157318cf2af5365c7980535af06b..0d3141ac0661656aded35273ae903dcc43849311 100644 --- a/ring-android/app/src/main/java/cx/ring/fragments/SmartListFragment.java +++ b/ring-android/app/src/main/java/cx/ring/fragments/SmartListFragment.java @@ -59,6 +59,8 @@ import android.widget.Toast; import com.google.zxing.integration.android.IntentIntegrator; import com.google.zxing.integration.android.IntentResult; +import java.lang.ref.WeakReference; + import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; @@ -70,14 +72,19 @@ import cx.ring.client.QRCodeScannerActivity; import cx.ring.model.CallContact; import cx.ring.model.Conference; import cx.ring.model.Conversation; +import cx.ring.model.account.Account; import cx.ring.service.LocalService; +import cx.ring.utils.BlockchainInputHandler; import cx.ring.utils.ClipboardHelper; +import cx.ring.views.MenuHeaderView; public class SmartListFragment extends Fragment implements SearchView.OnQueryTextListener, HomeActivity.Refreshable, SmartListAdapter.SmartListAdapterCallback, Conversation.ConversationActionCallback, - ClipboardHelper.ClipboardHelperCallback { + ClipboardHelper.ClipboardHelperCallback, + LocalService.NameLookupCallback, + MenuHeaderView.MenuHeaderAccountSelectionListener { private static final String TAG = SmartListFragment.class.getSimpleName(); private static final int USER_INPUT_DELAY = 300; @@ -85,6 +92,8 @@ public class SmartListFragment extends Fragment implements SearchView.OnQueryTex private LocalService.Callbacks mCallbacks = LocalService.DUMMY_CALLBACKS; private SmartListAdapter mSmartListAdapter; + private BlockchainInputHandler mBlockchainInputHandler; + private Account mCurrentAccount; @BindView(R.id.newconv_fab) FloatingActionButton mFloatingActionButton; @@ -286,26 +295,46 @@ public class SmartListFragment extends Fragment implements SearchView.OnQueryTex if (TextUtils.isEmpty(query)) { mNewContact.setVisibility(View.GONE); } else { - ((TextView) mNewContact.findViewById(R.id.display_name)).setText(query); - CallContact contact = CallContact.buildUnknown(query); - mNewContact.setTag(contact); - mNewContact.setVisibility(View.VISIBLE); - } - mUserInputHandler.removeCallbacksAndMessages(null); - mUserInputHandler.postDelayed(new Runnable() { - @Override - public void run() { - if (mCallbacks.getService() == null) { - Log.d(TAG, "onQueryTextChange: null service"); - } else { - mSmartListAdapter.updateDataset( - mCallbacks.getService().getConversations(), - query - ); + if (mCurrentAccount == null) { + return false; + } + + if (mCurrentAccount.isSip()) { + // sip search + ((TextView) mNewContact.findViewById(R.id.display_name)).setText(query); + CallContact contact = CallContact.buildUnknown(query); + mNewContact.setTag(contact); + mNewContact.setVisibility(View.VISIBLE); + } else { + // Ring search + if (mBlockchainInputHandler == null) { + mBlockchainInputHandler = new BlockchainInputHandler(new WeakReference<>(mCallbacks.getService()), this); + } + + // searching for a ringId or a blockchained username + if (!mBlockchainInputHandler.isAlive()) { + mBlockchainInputHandler = new BlockchainInputHandler(new WeakReference<>(mCallbacks.getService()), this); } + + mBlockchainInputHandler.enqueueNextLookup(query); } - }, USER_INPUT_DELAY); + + mUserInputHandler.removeCallbacksAndMessages(null); + mUserInputHandler.postDelayed(new Runnable() { + @Override + public void run() { + if (mCallbacks.getService() == null) { + Log.d(TAG, "onQueryTextChange: null service"); + } else { + mSmartListAdapter.updateDataset( + mCallbacks.getService().getConversations(), + query + ); + } + } + }, USER_INPUT_DELAY); + } return true; } @@ -637,4 +666,27 @@ public class SmartListFragment extends Fragment implements SearchView.OnQueryTex mErrorImageView.setImageResource(imageResId); } } + + @Override + public void onFound(String name, String address) { + ((TextView) mNewContact.findViewById(R.id.display_name)).setText(name); + CallContact contact = CallContact.buildUnknown(name); + mNewContact.setTag(contact); + mNewContact.setVisibility(View.VISIBLE); + } + + @Override + public void onInvalidName(String name) { + mNewContact.setVisibility(View.GONE); + } + + @Override + public void onError(String name, String address) { + mNewContact.setVisibility(View.GONE); + } + + @Override + public void accountSelected(Account account) { + mCurrentAccount = account; + } } diff --git a/ring-android/app/src/main/java/cx/ring/service/LocalService.java b/ring-android/app/src/main/java/cx/ring/service/LocalService.java index 79c15b5a43df12d336e8499177cc62a39b727eb8..e3517bd9c4d98847dd1e1a8a5a9652ed6ec910a3 100644 --- a/ring-android/app/src/main/java/cx/ring/service/LocalService.java +++ b/ring-android/app/src/main/java/cx/ring/service/LocalService.java @@ -290,7 +290,7 @@ public class LocalService extends Service implements SharedPreferences.OnSharedP currentAddressLookup.put(address, cbs); } cbs.add(cb); - mService.lookupAddress(account, null, address); + mService.lookupAddress(account == null ? "" : account, "", address); } catch (RemoteException e) { cb.onError(null, address); } diff --git a/ring-android/app/src/main/java/cx/ring/utils/BlockchainInputHandler.java b/ring-android/app/src/main/java/cx/ring/utils/BlockchainInputHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..11c827bec7cd96bb64831254d70b284345df8e94 --- /dev/null +++ b/ring-android/app/src/main/java/cx/ring/utils/BlockchainInputHandler.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2016 Savoir-faire Linux Inc. + * + * Author: Thibault Wittemberg <thibault.wittemberg@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 cx.ring.utils; + +import android.support.annotation.NonNull; +import android.util.Log; + +import java.lang.ref.WeakReference; + +import cx.ring.service.LocalService; + +public class BlockchainInputHandler extends Thread { + + private static final String TAG = BlockchainInputHandler.class.getName(); + + private static final String RINGID_PATTERN = "^[a-f0-9]{40}$"; + private static final int WAIT_DELAY= 2000; + private static final int KILL_DELAY = 6000; + + private WeakReference<LocalService> mLocalService; + private String mTextToLookup; + private LocalService.NameLookupCallback mLookupCallback; + + private boolean mIsWaitingForInputs = false; + private long mLastEnqueuedInputTimeStamp = -1; + + public BlockchainInputHandler(@NonNull WeakReference<LocalService> localService, @NonNull LocalService.NameLookupCallback lookupCallback) { + mLocalService = localService; + mLookupCallback = lookupCallback; + } + + public void enqueueNextLookup(String text) { + + if (mLocalService.get() == null) { + return; + } + + mLastEnqueuedInputTimeStamp = System.currentTimeMillis(); + mTextToLookup = text; + + if (!mIsWaitingForInputs) { + mIsWaitingForInputs = true; + start(); + } + } + + private boolean isRingId(String text) { + return text.matches(RINGID_PATTERN); + } + + @Override + public void run() { + while (mIsWaitingForInputs) { + try { + Thread.sleep(100); + + long timeFromLastEnqueuedInput = System.currentTimeMillis() - mLastEnqueuedInputTimeStamp; + if (timeFromLastEnqueuedInput >= KILL_DELAY) { + // we've been waiting for a long time, stop the wait + // the next user input will trigger the next wait + mIsWaitingForInputs = false; + } else if (timeFromLastEnqueuedInput >= WAIT_DELAY) { + // trigger the blockchain lookup + final LocalService localService = mLocalService.get(); + if (isRingId(mTextToLookup)) { + localService.lookupAddress("", mTextToLookup, mLookupCallback); + } else { + localService.lookupName("", mTextToLookup, mLookupCallback); + } + // stop the wait + mIsWaitingForInputs = false; + } + + } catch (InterruptedException e) { + Log.e(TAG, "Error while waiting for next Blockchain lookup", e); + } + } + + } +} \ No newline at end of file diff --git a/ring-android/app/src/main/java/cx/ring/utils/BlockchainTextWatcher.java b/ring-android/app/src/main/java/cx/ring/utils/BlockchainTextWatcher.java index 6e43d3e240c36958988292312fab2e35c935ce3a..6ac79e0ab15d74b3a986713d5609dcffbf2363cf 100644 --- a/ring-android/app/src/main/java/cx/ring/utils/BlockchainTextWatcher.java +++ b/ring-android/app/src/main/java/cx/ring/utils/BlockchainTextWatcher.java @@ -18,7 +18,6 @@ */ package cx.ring.utils; -import android.support.annotation.NonNull; import android.support.design.widget.TextInputLayout; import android.text.Editable; import android.text.TextUtils; @@ -130,67 +129,10 @@ public class BlockchainTextWatcher implements TextWatcher, LocalService.NameLook mInputLayout.get().setError(mLookinForAvailability); } - if (mBlockchainInputHandler.isAlive()) { - mBlockchainInputHandler.enqueueNextLookup(name); - } else { + if (!mBlockchainInputHandler.isAlive()) { mBlockchainInputHandler = new BlockchainInputHandler(mLocalService, this); - mBlockchainInputHandler.enqueueNextLookup(name); - } - } - - private class BlockchainInputHandler extends Thread { - - private WeakReference<LocalService> mLocalService; - private String mTextToLookup; - private LocalService.NameLookupCallback mLookupCallback; - - private boolean mIsWaitingForInputs = false; - private long mLastEnqueuedInputTimeStamp = -1; - - public BlockchainInputHandler(@NonNull WeakReference<LocalService> localService, @NonNull LocalService.NameLookupCallback lookupCallback) { - mLocalService = localService; - mLookupCallback = lookupCallback; - } - - public void enqueueNextLookup(String text) { - - if (mLocalService.get() == null) { - return; - } - - mLastEnqueuedInputTimeStamp = System.currentTimeMillis(); - mTextToLookup = text; - - if (!mIsWaitingForInputs) { - mIsWaitingForInputs = true; - start(); - } } - @Override - public void run() { - while (mIsWaitingForInputs) { - try { - Thread.sleep(100); - - long timeFromLastEnqueuedInput = System.currentTimeMillis() - mLastEnqueuedInputTimeStamp; - if (timeFromLastEnqueuedInput >= 6000) { - // we've been waiting for a long time, stop the wait - // the next user input will trigger the next wait - mIsWaitingForInputs = false; - } else if (timeFromLastEnqueuedInput >= 3000) { - // trigger the blockchain lookup - final LocalService localService = mLocalService.get(); - localService.lookupName("", mTextToLookup, mLookupCallback); - // stop the wait - mIsWaitingForInputs = false; - } - - } catch (InterruptedException e) { - Log.e(TAG, "Error while waiting for next Blockchain lookup", e); - } - } - - } + mBlockchainInputHandler.enqueueNextLookup(name); } } \ No newline at end of file diff --git a/ring-android/app/src/main/java/cx/ring/views/MenuHeaderView.java b/ring-android/app/src/main/java/cx/ring/views/MenuHeaderView.java index 7a2fcfe037e8d84376156e3b3763d741a41d5d2f..778a0fdca25a00bed42680b161404b6d9f38bc94 100644 --- a/ring-android/app/src/main/java/cx/ring/views/MenuHeaderView.java +++ b/ring-android/app/src/main/java/cx/ring/views/MenuHeaderView.java @@ -135,6 +135,7 @@ public class MenuHeaderView extends FrameLayout { public void registerAccountSelectionListener(MenuHeaderAccountSelectionListener listener) { mListeners.add(new WeakReference<>(listener)); + listener.accountSelected(getSelectedAccount()); } public void updateUserView() {