Skip to content
Snippets Groups Projects
Commit b96a7d98 authored by Adrien Béraud's avatar Adrien Béraud
Browse files

HomeActivity: replace NavigationDrawer with NavigationBottom

Change-Id: I7903f2b4d5505b6366d4e9a8cbdc8b26bb31831e
parent 19ce4446
Branches
Tags
No related merge requests found
Showing
with 1140 additions and 635 deletions
......@@ -148,11 +148,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
android:name=".account.AccountWizardActivity"
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"
android:theme="@style/AppThemeBase.Light" />
<activity
android:name=".account.AccountEditionActivity"
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize"
android:label="@string/app_name"
android:theme="@style/AppTheme" />
<activity
android:name=".client.RingtoneActivity"
android:configChanges="screenSize|screenLayout|smallestScreenSize"
......
......@@ -21,6 +21,7 @@ package cx.ring.about;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
......@@ -30,9 +31,15 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import butterknife.BindView;
import butterknife.OnClick;
import cx.ring.BuildConfig;
......@@ -41,6 +48,7 @@ import cx.ring.client.HomeActivity;
import cx.ring.dependencyinjection.JamiInjectionComponent;
import cx.ring.mvp.BaseSupportFragment;
import cx.ring.mvp.RootPresenter;
import cx.ring.utils.DeviceUtils;
public class AboutFragment extends BaseSupportFragment<RootPresenter> {
......@@ -58,7 +66,6 @@ public class AboutFragment extends BaseSupportFragment<RootPresenter> {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
((HomeActivity) getActivity()).setToolbarState(false, R.string.menu_item_about);
return super.onCreateView(inflater, parent, savedInstanceState);
}
......@@ -71,6 +78,29 @@ public class AboutFragment extends BaseSupportFragment<RootPresenter> {
@Override
public void onResume() {
super.onResume();
if (DeviceUtils.isTablet(getContext())) {
Toolbar toolbar = getActivity().findViewById(R.id.main_toolbar);
TextView title = toolbar.findViewById(R.id.contact_title);
ImageView logo = toolbar.findViewById(R.id.contact_image);
logo.setVisibility(View.GONE);
title.setText(R.string.menu_item_about);
title.setTextSize(19);
title.setTypeface(null, Typeface.BOLD);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) title.getLayoutParams();
params.removeRule(RelativeLayout.ALIGN_TOP);
params.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
title.setLayoutParams(params);
} else {
((HomeActivity) getActivity()).setToolbarState(R.string.menu_item_about);
}
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
Fragment existingFragment = fragmentManager.findFragmentByTag(AboutFragment.TAG);
if (existingFragment == null) {
((HomeActivity) getActivity()).goToAbout();
}
}
@Override
......
......@@ -5,6 +5,7 @@
* Alexandre Savard <alexandre.savard@savoirfairelinux.com>
* Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Loïc Siret <loic.siret@savoirfairelinux.com>
* AmirHossein Naghshzan <amirhossein.naghshzan@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
......@@ -23,6 +24,7 @@ package cx.ring.account;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
......@@ -31,43 +33,55 @@ import androidx.annotation.StringRes;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.tabs.TabLayout;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.ViewPager;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import javax.inject.Inject;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import cx.ring.R;
import cx.ring.application.JamiApplication;
import cx.ring.client.HomeActivity;
import cx.ring.contactrequests.BlackListFragment;
import cx.ring.dependencyinjection.JamiInjectionComponent;
import cx.ring.fragments.AdvancedAccountFragment;
import cx.ring.fragments.GeneralAccountFragment;
import cx.ring.fragments.MediaPreferenceFragment;
import cx.ring.fragments.SecurityAccountFragment;
import cx.ring.interfaces.BackHandlerInterface;
import cx.ring.mvp.BaseSupportFragment;
import cx.ring.utils.DeviceUtils;
public class AccountEditionActivity extends AppCompatActivity implements AccountEditionView {
public class AccountEditionFragment extends BaseSupportFragment<AccountEditionPresenter> implements
BackHandlerInterface,
AccountEditionView,
ViewTreeObserver.OnScrollChangedListener {
public static final String ACCOUNT_ID_KEY = AccountEditionActivity.class.getCanonicalName() + "accountid";
public static final String ACCOUNT_HAS_PASSWORD_KEY = AccountEditionActivity.class.getCanonicalName() + "hasPassword";
public static final String ACCOUNT_ID_KEY = AccountEditionFragment.class.getCanonicalName() + "accountid";
static final String ACCOUNT_HAS_PASSWORD_KEY = AccountEditionFragment.class.getCanonicalName() + "hasPassword";
private static final String TAG = AccountEditionFragment.class.getSimpleName();
public static final String ACCOUNT_ID = TAG + "accountID";
public static final String TAG = AccountEditionActivity.class.getSimpleName();
private static final int SCROLL_DIRECTION_UP = -1;
@Inject
protected AccountEditionPresenter mEditionPresenter;
private boolean mIsVisible;
@BindView(R.id.pager)
protected ViewPager mViewPager;
......@@ -81,42 +95,66 @@ public class AccountEditionActivity extends AppCompatActivity implements Account
private MenuItem mItemAdvanced;
private MenuItem mItemBlacklist;
private BackHandlerInterface mBackHandlerInterface;
private String mAccountId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
setHasOptionsMenu(true);
super.onViewCreated(view, savedInstanceState);
setContentView(R.layout.activity_account_settings);
mAccountId = getArguments().getString(ACCOUNT_ID);
ButterKnife.bind(this);
presenter.init(mAccountId);
presenter.onAccountChanged();
// dependency injection
JamiApplication.getInstance().getRingInjectionComponent().inject(this);
mEditionPresenter.bindView(this);
String accountId = getIntent().getData().getLastPathSegment();
mEditionPresenter.init(accountId);
if (DeviceUtils.isTablet(requireContext())) {
Toolbar toolbar = getActivity().findViewById(R.id.main_toolbar);
TextView title = toolbar.findViewById(R.id.contact_title);
ImageView logo = toolbar.findViewById(R.id.contact_image);
logo.setVisibility(View.GONE);
title.setText(R.string.navigation_item_account);
title.setTextSize(19);
title.setTypeface(null, Typeface.BOLD);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) title.getLayoutParams();
params.removeRule(RelativeLayout.ALIGN_TOP);
params.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
title.setLayoutParams(params);
}
frameLayout.getViewTreeObserver().addOnScrollChangedListener(this);
}
@Override
public void displaySummary(String accountId) {
mSlidingTabLayout.setVisibility(View.GONE);
mViewPager.setVisibility(View.GONE);
toggleView(accountId);
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
Fragment existingFragment = fragmentManager.findFragmentByTag(RingAccountSummaryFragment.TAG);
if (existingFragment == null) {
RingAccountSummaryFragment ringAccountSummaryFragment = new RingAccountSummaryFragment();
Bundle args = new Bundle();
args.putString(ACCOUNT_ID_KEY, accountId);
ringAccountSummaryFragment.setArguments(args);
getSupportFragmentManager().beginTransaction()
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, ringAccountSummaryFragment, RingAccountSummaryFragment.TAG)
.addToBackStack(RingAccountSummaryFragment.TAG)
.commit();
} else {
((HomeActivity) getActivity()).selectNavigationItem(R.id.navigation_settings);
}
}
@Override
public void displaySIPView(String accountId) {
toggleView(accountId);
}
@Override
public void initViewPager(String accountId, boolean isRing) {
mViewPager.setOffscreenPageLimit(4);
mViewPager.setAdapter(new PreferencesPagerAdapter(getSupportFragmentManager(), AccountEditionActivity.this, accountId, isRing));
mSlidingTabLayout.setupWithViewPager(mViewPager);
mViewPager.setAdapter(new PreferencesPagerAdapter(getActivity().getSupportFragmentManager(), getActivity(), accountId, isRing));
}
@Override
......@@ -139,7 +177,7 @@ public class AccountEditionActivity extends AppCompatActivity implements Account
Bundle args = new Bundle();
args.putString(ACCOUNT_ID_KEY, accountId);
blackListFragment.setArguments(args);
getSupportFragmentManager().beginTransaction()
getActivity().getSupportFragmentManager().beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.addToBackStack(BlackListFragment.TAG)
.replace(R.id.fragment_container, blackListFragment, BlackListFragment.TAG)
......@@ -147,61 +185,78 @@ public class AccountEditionActivity extends AppCompatActivity implements Account
mSlidingTabLayout.setVisibility(View.GONE);
mViewPager.setVisibility(View.GONE);
frameLayout.setVisibility(View.VISIBLE);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
inflater.inflate(R.menu.account_edition, menu);
mItemAdvanced = menu.findItem(R.id.menuitem_advanced);
mItemBlacklist = menu.findItem(R.id.menuitem_blacklist);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
mEditionPresenter.prepareOptionsMenu();
return true;
presenter.prepareOptionsMenu();
}
@Override
protected void onResume() {
public void onResume() {
super.onResume();
mEditionPresenter.bindView(this);
presenter.bindView(this);
}
@Override
protected void onPause() {
public void onPause() {
super.onPause();
mEditionPresenter.unbindView();
presenter.unbindView();
setBackListenerEnabled(false);
}
@Override
public void onBackPressed() {
if (mBackHandlerInterface != null && mBackHandlerInterface.onBackPressed()) {
return;
public boolean onBackPressed() {
mIsVisible = false;
((HomeActivity) getActivity()).setToolbarOutlineState(true);
if (frameLayout.getVisibility() != View.VISIBLE) {
toggleView(mAccountId);
return true;
}
if (frameLayout.getVisibility() == View.VISIBLE) {
super.onBackPressed();
} else {
frameLayout.setVisibility(View.VISIBLE);
mViewPager.setVisibility(View.GONE);
mSlidingTabLayout.setVisibility(View.GONE);
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
RingAccountSummaryFragment summaryFragment = (RingAccountSummaryFragment) fragmentManager.findFragmentByTag(RingAccountSummaryFragment.TAG);
if (summaryFragment.onBackPressed()){
return true;
}
fragmentManager.popBackStackImmediate();
List<Fragment> fragments = fragmentManager.getFragments();
Fragment fragment = fragments.get(fragments.size() - 1);
return fragment instanceof RingAccountSummaryFragment;
}
@Override
protected void onDestroy() {
super.onDestroy();
mBackHandlerInterface = null;
private void toggleView(String accountId) {
mAccountId = accountId;
boolean isRing = presenter.getAccount(mAccountId).isRing();
mSlidingTabLayout.setVisibility(isRing? View.GONE : View.VISIBLE);
mViewPager.setVisibility(isRing? View.GONE : View.VISIBLE);
frameLayout.setVisibility(isRing? View.VISIBLE : View.GONE);
presenter.prepareOptionsMenu();
setBackListenerEnabled(isRing);
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
RingAccountSummaryFragment fragment = (RingAccountSummaryFragment) fragmentManager.findFragmentByTag(RingAccountSummaryFragment.TAG);
if (fragment != null) {
fragment.setFragmentVisibility(isRing);
fragment.onScrollChanged();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
getActivity().onBackPressed();
return true;
case R.id.menuitem_delete:
AlertDialog deleteDialog = createDeleteDialog();
......@@ -211,9 +266,15 @@ public class AccountEditionActivity extends AppCompatActivity implements Account
mSlidingTabLayout.setVisibility(View.VISIBLE);
mViewPager.setVisibility(View.VISIBLE);
frameLayout.setVisibility(View.GONE);
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
RingAccountSummaryFragment fragment = (RingAccountSummaryFragment) fragmentManager.findFragmentByTag(RingAccountSummaryFragment.TAG);
fragment.setFragmentVisibility(false);
mIsVisible = true;
setupElevation();
break;
case R.id.menuitem_blacklist:
mEditionPresenter.goToBlackList();
presenter.goToBlackList();
((HomeActivity) getActivity()).setToolbarElevation(false);
default:
break;
}
......@@ -222,19 +283,19 @@ public class AccountEditionActivity extends AppCompatActivity implements Account
@NonNull
private AlertDialog createDeleteDialog() {
AlertDialog alertDialog = new MaterialAlertDialogBuilder(this)
AlertDialog alertDialog = new MaterialAlertDialogBuilder(getActivity())
.setMessage(R.string.account_delete_dialog_message)
.setTitle(R.string.account_delete_dialog_title)
.setPositiveButton(android.R.string.ok, (dialog, whichButton) -> mEditionPresenter.removeAccount())
.setPositiveButton(android.R.string.ok, (dialog, whichButton) -> presenter.removeAccount())
.setNegativeButton(android.R.string.cancel, null)
.create();
alertDialog.setOwnerActivity(AccountEditionActivity.this);
alertDialog.setOwnerActivity(getActivity());
return alertDialog;
}
@Override
public void goToWizardActivity() {
Intent intent = new Intent(this, AccountWizardActivity.class);
Intent intent = new Intent(getActivity(), AccountWizardActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
......@@ -242,26 +303,33 @@ public class AccountEditionActivity extends AppCompatActivity implements Account
@Override
public void exit() {
finish();
getActivity().onBackPressed();
}
@Override
public int getLayout() {
return R.layout.frag_account_settings;
}
@Override
public void displayAccountName(final String name) {
Toolbar toolbar = findViewById(R.id.main_toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle(name);
public void injectFragment(JamiInjectionComponent component) {
component.inject(this);
}
private void setBackListenerEnabled(boolean enable) {
if (enable) {
((HomeActivity) getActivity()).setAccountFragmentOnBackPressedListener(this);
} else {
((HomeActivity) getActivity()).setAccountFragmentOnBackPressedListener(null);
}
}
private static class PreferencesPagerAdapter extends FragmentPagerAdapter {
private static class PreferencesPagerAdapter extends FragmentStatePagerAdapter {
private Context mContext;
private String accountId;
private boolean isRing;
public PreferencesPagerAdapter(FragmentManager fm, Context mContext, String accountId, boolean isRing) {
PreferencesPagerAdapter(FragmentManager fm, Context mContext, String accountId, boolean isRing) {
super(fm);
this.mContext = mContext;
this.accountId = accountId;
......@@ -353,8 +421,30 @@ public class AccountEditionActivity extends AppCompatActivity implements Account
}
}
public void setOnBackPressedListener(BackHandlerInterface backPressedListener) {
mBackHandlerInterface = backPressedListener;
@Override
public void onScrollChanged() {
setupElevation();
}
private void setupElevation() {
if (mViewPager == null || !mIsVisible) {
return;
}
LinearLayout ll = (LinearLayout) mViewPager.getChildAt(mViewPager.getCurrentItem());
if (ll == null) { return; }
RecyclerView rv = (RecyclerView)((FrameLayout) ll.getChildAt(0)).getChildAt(0);
if (rv == null) { return; }
if (rv.canScrollVertically(SCROLL_DIRECTION_UP)) {
float elevation = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 4, getContext().getResources().getDisplayMetrics());
mSlidingTabLayout.setElevation(elevation);
((HomeActivity) getActivity()).setToolbarElevation(true);
((HomeActivity) getActivity()).setToolbarOutlineState(false);
} else {
mSlidingTabLayout.setElevation(0);
((HomeActivity) getActivity()).setToolbarElevation(false);
((HomeActivity) getActivity()).setToolbarOutlineState(true);
}
}
}
......@@ -41,20 +41,28 @@ public class AccountEditionPresenter extends RootPresenter<AccountEditionView> {
public void init(String accountId) {
final AccountEditionView view = getView();
mAccount = accountId == null ? null : mAccountService.getAccount(accountId);
mAccount = getAccount(accountId);
if (mAccount == null) {
if (view != null)
view.exit();
return;
}
view.displayAccountName(mAccount.getAlias());
if (mAccount.isRing()) {
view.displaySummary(mAccount.getAccountID());
} else {
view.displaySIPView(mAccount.getAccountID());
}
view.initViewPager(mAccount.getAccountID(), mAccount.isRing());
mCompositeDisposable.add(mAccountService.getObservableAccount(accountId)
}
public void onAccountChanged() {
mCompositeDisposable.add(mAccountService.getCurrentAccountSubject()
.observeOn(mUiScheduler)
.subscribe(account -> getView().displayAccountName(account.getAlias())));
.subscribe(account -> {
if (mAccount.getAccountID() != account.getAccountID()) {
init(account.getAccountID());
}
}));
}
public void goToBlackList() {
......@@ -77,4 +85,9 @@ public class AccountEditionPresenter extends RootPresenter<AccountEditionView> {
getView().showBlacklistOption(mAccount.isRing());
}
}
public Account getAccount(String accountId) {
return accountId == null ? null : mAccountService.getAccount(accountId);
}
}
......@@ -24,8 +24,6 @@ public interface AccountEditionView {
void exit();
void displayAccountName(String name);
void displaySummary(String accountId);
void initViewPager(String accountId, boolean isRing);
......@@ -35,4 +33,7 @@ public interface AccountEditionView {
void showBlacklistOption(boolean show);
void goToBlackList(String accountId);
void displaySIPView(String accountID);
}
/*
* Copyright (C) 2004-2019 Savoir-faire Linux Inc.
*
* Author: Aline Bonnet <aline.bonnet@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.account;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
import cx.ring.R;
import cx.ring.adapters.AccountView;
import cx.ring.model.Account;
public class AccountsAdapter extends RecyclerView.Adapter<AccountView> {
static final String TAG = AccountsAdapter.class.getSimpleName();
private final ArrayList<Account> accounts = new ArrayList<>();
private final AccountView.OnAccountActionListener mListeners;
public AccountsAdapter(AccountView.OnAccountActionListener listeners) {
mListeners = listeners;
}
@Override
public int getItemCount() {
return accounts.size();
}
@NonNull
@Override
public AccountView onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View holderView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_account_pref, parent, false);
return new AccountView(holderView, mListeners);
}
@Override
public void onBindViewHolder(@NonNull AccountView entryView, int position) {
final Account item = accounts.get(position);
entryView.update(item);
}
public void replaceAll(List<Account> results) {
accounts.clear();
accounts.addAll(results);
notifyDataSetChanged();
}
public void replaceAccount(Account account) {
for (int i=0; i<accounts.size(); i++) {
if (accounts.get(i) == account) {
notifyItemChanged(i);
return;
}
}
}
}
......@@ -68,7 +68,7 @@ public class BackupAccountDialog extends DialogFragment {
Bundle args = getArguments();
if (args != null) {
mAccountId = args.getString(AccountEditionActivity.ACCOUNT_ID_KEY);
mAccountId = args.getString(AccountEditionFragment.ACCOUNT_ID_KEY);
}
final AlertDialog result = new MaterialAlertDialogBuilder(requireContext())
......
......@@ -79,8 +79,8 @@ public class ChangePasswordDialog extends DialogFragment {
boolean hasPassword = true;
Bundle args = getArguments();
if (args != null) {
accountId = args.getString(AccountEditionActivity.ACCOUNT_ID_KEY, accountId);
hasPassword = args.getBoolean(AccountEditionActivity.ACCOUNT_HAS_PASSWORD_KEY, true);
accountId = args.getString(AccountEditionFragment.ACCOUNT_ID_KEY, accountId);
hasPassword = args.getBoolean(AccountEditionFragment.ACCOUNT_HAS_PASSWORD_KEY, true);
}
int passwordMessage = hasPassword ? R.string.account_password_change : R.string.account_password_set;
mPasswordTxtBox.setVisibility(hasPassword ? View.VISIBLE : View.GONE);
......
......@@ -128,8 +128,8 @@ public class RegisterNameDialog extends DialogFragment {
boolean hasPassword = true;
Bundle args = getArguments();
if (args != null) {
accountId = args.getString(AccountEditionActivity.ACCOUNT_ID_KEY, accountId);
hasPassword = args.getBoolean(AccountEditionActivity.ACCOUNT_HAS_PASSWORD_KEY, true);
accountId = args.getString(AccountEditionFragment.ACCOUNT_ID_KEY, accountId);
hasPassword = args.getBoolean(AccountEditionFragment.ACCOUNT_HAS_PASSWORD_KEY, true);
}
mUsernameTxt.setFilters(new InputFilter[]{new RegisteredNameFilter()});
......
......@@ -20,10 +20,13 @@
*/
package cx.ring.account;
import android.Manifest;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
......@@ -38,6 +41,7 @@ import com.google.android.material.textfield.TextInputLayout;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.SwitchCompat;
import android.provider.MediaStore;
import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableString;
......@@ -46,39 +50,60 @@ import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.LinearLayout;
import android.widget.Toast;
import java.io.File;
import java.util.Map;
import javax.inject.Inject;
import androidx.core.content.FileProvider;
import androidx.core.util.Pair;
import butterknife.BindView;
import butterknife.OnClick;
import butterknife.OnEditorAction;
import cx.ring.R;
import cx.ring.client.HomeActivity;
import cx.ring.dependencyinjection.JamiInjectionComponent;
import cx.ring.interfaces.BackHandlerInterface;
import cx.ring.model.Account;
import cx.ring.mvp.BaseSupportFragment;
import cx.ring.services.AccountService;
import cx.ring.services.VCardServiceImpl;
import cx.ring.utils.AndroidFileUtils;
import cx.ring.utils.BitmapUtils;
import cx.ring.utils.ContentUriHandler;
import cx.ring.utils.KeyboardVisibilityManager;
import cx.ring.views.AvatarDrawable;
import ezvcard.VCard;
import ezvcard.property.FormattedName;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
public class RingAccountSummaryFragment extends BaseSupportFragment<RingAccountSummaryPresenter> implements BackHandlerInterface,
public class RingAccountSummaryFragment extends BaseSupportFragment<RingAccountSummaryPresenter> implements
RegisterNameDialog.RegisterNameDialogListener,
RenameDeviceDialog.RenameDeviceListener,
DeviceAdapter.DeviceRevocationListener,
ConfirmRevocationDialog.ConfirmRevocationListener,
RingAccountSummaryView, ChangePasswordDialog.PasswordChangedListener, BackupAccountDialog.UnlockAccountListener {
RingAccountSummaryView, ChangePasswordDialog.PasswordChangedListener,
BackupAccountDialog.UnlockAccountListener,
ViewTreeObserver.OnScrollChangedListener {
public static final String TAG = RingAccountSummaryFragment.class.getSimpleName();
private static final String FRAGMENT_DIALOG_REVOCATION = TAG + ".dialog.deviceRevocation";
......@@ -87,6 +112,10 @@ public class RingAccountSummaryFragment extends BaseSupportFragment<RingAccountS
private static final String FRAGMENT_DIALOG_BACKUP = TAG + ".dialog.backup";
private static final int WRITE_REQUEST_CODE = 43;
private static final int SCROLL_DIRECTION_UP = -1;
private boolean mIsVisible = true;
/*
UI Bindings
*/
......@@ -97,6 +126,15 @@ public class RingAccountSummaryFragment extends BaseSupportFragment<RingAccountS
@BindView(R.id.btn_end_export)
Button mEndBtn;
@BindView(R.id.user_photo)
ImageView mUserImage;
@BindView(R.id.username)
TextView mUsername;
@BindView(R.id.subtitle)
TextView mSubtitle;
@BindView(R.id.btn_start_export)
Button mStartBtn;
......@@ -148,6 +186,9 @@ public class RingAccountSummaryFragment extends BaseSupportFragment<RingAccountS
@BindView(R.id.account_status)
Chip mAccountStatus;
@BindView(R.id.scrollview)
ScrollView mScrollView;
/*
Declarations
*/
......@@ -160,6 +201,12 @@ public class RingAccountSummaryFragment extends BaseSupportFragment<RingAccountS
private File mCacheArchive = null;
private BottomSheetBehavior mSheetBehavior;
private ImageView mProfilePhoto;
private Bitmap mSourcePhoto;
private Uri tmpProfilePhotoUri;
private final CompositeDisposable mDisposableBag = new CompositeDisposable();
@Inject
AccountService mAccountService;
......@@ -170,14 +217,12 @@ public class RingAccountSummaryFragment extends BaseSupportFragment<RingAccountS
hidePopWizard();
if (getArguments() != null) {
String accountId = getArguments().getString(AccountEditionActivity.ACCOUNT_ID_KEY);
String accountId = getArguments().getString(AccountEditionFragment.ACCOUNT_ID_KEY);
if (accountId != null) {
presenter.setAccountId(accountId);
}
}
((AccountEditionActivity) getActivity()).setOnBackPressedListener(this);
mSheetBehavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View view, int i) {
......@@ -194,17 +239,43 @@ public class RingAccountSummaryFragment extends BaseSupportFragment<RingAccountS
}
});
updateUserView();
mScrollView.getViewTreeObserver().addOnScrollChangedListener(this);
}
@Override
public void updateUserView() {
if (getActivity() == null || mAccountService.getCurrentAccount() == null) {
Log.e(TAG, "Not able to update navigation view");
return;
}
mDisposableBag.add(mAccountService
.getCurrentAccountSubject()
.switchMapSingle(account -> AvatarDrawable.load(getActivity(), account)
.map(avatar -> new Pair<>(account, avatar)))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(d -> {
mUsername.setText(getAccountAlias(d.first));
mSubtitle.setText(getUri(d.first, getActivity().getString(R.string.account_type_ip2ip)));
mUserImage.setImageDrawable(d.second);
accountChanged(d.first);
}, e -> Log.e(TAG, "Error loading avatar", e)));
}
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
if (requestCode == WRITE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
switch (requestCode) {
case WRITE_REQUEST_CODE:
if (resultCode == Activity.RESULT_OK) {
if (resultData != null) {
Uri uri = resultData.getData();
if (uri != null) {
if (mCacheArchive != null) {
AndroidFileUtils.moveToUri(requireContext().getContentResolver(), mCacheArchive, uri)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(() -> {}, e -> {
.subscribe(() -> {
}, e -> {
View v = getView();
if (v != null)
Snackbar.make(v, "Can't export archive: " + e.getMessage(), Snackbar.LENGTH_LONG).show();
......@@ -213,6 +284,24 @@ public class RingAccountSummaryFragment extends BaseSupportFragment<RingAccountS
}
}
}
break;
case HomeActivity.REQUEST_CODE_PHOTO:
if (resultCode == Activity.RESULT_OK) {
if (tmpProfilePhotoUri == null) {
if (resultData != null)
updatePhoto((Bitmap) resultData.getExtras().get("data"));
} else {
updatePhoto(tmpProfilePhotoUri);
}
}
tmpProfilePhotoUri = null;
break;
case HomeActivity.REQUEST_CODE_GALLERY:
if (resultCode == Activity.RESULT_OK && resultData != null) {
updatePhoto(resultData.getData());
}
break;
}
}
@Override
......@@ -242,7 +331,7 @@ public class RingAccountSummaryFragment extends BaseSupportFragment<RingAccountS
mChangePasswordBtn.setText(mAccountHasPassword ? R.string.account_password_change : R.string.account_password_set);
mAccountSwitch.setChecked(account.isEnabled());
mAccountNameTxt.setText(account.getAlias());
mAccountNameTxt.setText(getString(R.string.profile));
mAccountIdTxt.setText(account.getUsername());
mAccountId = account.getAccountID();
mBestName = account.getRegisteredName();
......@@ -293,10 +382,6 @@ public class RingAccountSummaryFragment extends BaseSupportFragment<RingAccountS
mAccountOptionsLayout.setVisibility(mAccountHasManager ? View.GONE : View.VISIBLE);
}
/*
BackHandlerInterface
*/
@Override
public boolean onBackPressed() {
if (isDisplayingWizard()) {
hideWizard();
......@@ -379,6 +464,38 @@ public class RingAccountSummaryFragment extends BaseSupportFragment<RingAccountS
return false;
}
@OnClick({R.id.profile_container, R.id.user_profile_edit})
public void profileContainerClicked() {
LayoutInflater inflater = LayoutInflater.from(getActivity());
ViewGroup view = (ViewGroup) inflater.inflate(R.layout.dialog_profile, null);
final EditText editText = view.findViewById(R.id.user_name);
editText.setText(presenter.getAlias(mAccountService.getCurrentAccount()));
mProfilePhoto = view.findViewById(R.id.profile_photo);
mDisposableBag.add(AvatarDrawable.load(inflater.getContext(), mAccountService.getCurrentAccount())
.subscribe(a -> mProfilePhoto.setImageDrawable(a)));
ImageButton cameraView = view.findViewById(R.id.camera);
cameraView.setOnClickListener(v -> presenter.cameraClicked());
ImageButton gallery = view.findViewById(R.id.gallery);
gallery.setOnClickListener(v -> presenter.galleryClicked());
new MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.profile)
.setView(view)
.setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.cancel())
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
if (mSourcePhoto != null) {
presenter.saveVCard(mAccountService.getCurrentAccount(), editText.getText().toString().trim(), Single.just(mSourcePhoto).map(BitmapUtils::bitmapToPhoto));
mSourcePhoto = null;
} else {
presenter.saveVCardFormattedName(editText.getText().toString().trim());
}
})
.show();
}
@OnClick(R.id.btn_start_export)
void onClickStart() {
mPasswordLayout.setError(null);
......@@ -403,8 +520,8 @@ public class RingAccountSummaryFragment extends BaseSupportFragment<RingAccountS
@OnClick(R.id.register_name_btn)
void showUsernameRegistrationPopup() {
Bundle args = new Bundle();
args.putString(AccountEditionActivity.ACCOUNT_ID_KEY, getArguments().getString(AccountEditionActivity.ACCOUNT_ID_KEY));
args.putBoolean(AccountEditionActivity.ACCOUNT_HAS_PASSWORD_KEY, mAccountHasPassword);
args.putString(AccountEditionFragment.ACCOUNT_ID_KEY, getArguments().getString(AccountEditionFragment.ACCOUNT_ID_KEY));
args.putBoolean(AccountEditionFragment.ACCOUNT_HAS_PASSWORD_KEY, mAccountHasPassword);
RegisterNameDialog registrationDialog = new RegisterNameDialog();
registrationDialog.setArguments(args);
registrationDialog.setListener(this);
......@@ -549,7 +666,7 @@ public class RingAccountSummaryFragment extends BaseSupportFragment<RingAccountS
public void onBackupAccount() {
BackupAccountDialog dialog = new BackupAccountDialog();
Bundle args = new Bundle();
args.putString(AccountEditionActivity.ACCOUNT_ID_KEY, getArguments().getString(AccountEditionActivity.ACCOUNT_ID_KEY));
args.putString(AccountEditionFragment.ACCOUNT_ID_KEY, getArguments().getString(AccountEditionFragment.ACCOUNT_ID_KEY));
dialog.setArguments(args);
dialog.setListener(this);
dialog.show(requireFragmentManager(), FRAGMENT_DIALOG_BACKUP);
......@@ -581,8 +698,8 @@ public class RingAccountSummaryFragment extends BaseSupportFragment<RingAccountS
public void onPasswordChangeAsked() {
ChangePasswordDialog dialog = new ChangePasswordDialog();
Bundle args = new Bundle();
args.putString(AccountEditionActivity.ACCOUNT_ID_KEY, getArguments().getString(AccountEditionActivity.ACCOUNT_ID_KEY));
args.putBoolean(AccountEditionActivity.ACCOUNT_HAS_PASSWORD_KEY, mAccountHasPassword);
args.putString(AccountEditionFragment.ACCOUNT_ID_KEY, getArguments().getString(AccountEditionFragment.ACCOUNT_ID_KEY));
args.putBoolean(AccountEditionFragment.ACCOUNT_HAS_PASSWORD_KEY, mAccountHasPassword);
dialog.setArguments(args);
dialog.setListener(this);
dialog.show(requireFragmentManager(), FRAGMENT_DIALOG_PASSWORD);
......@@ -611,4 +728,128 @@ public class RingAccountSummaryFragment extends BaseSupportFragment<RingAccountS
dest.delete();
presenter.downloadAccountsArchive(dest, password);
}
@Override
public void gotToImageCapture() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
try {
Context context = requireContext();
File file = AndroidFileUtils.createImageFile(context);
Uri uri = FileProvider.getUriForFile(context, ContentUriHandler.AUTHORITY_FILES, file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
tmpProfilePhotoUri = uri;
} catch (Exception e) {
Log.e(TAG, "Can't create temp file", e);
}
startActivityForResult(intent, HomeActivity.REQUEST_CODE_PHOTO);
}
@Override
public void askCameraPermission() {
requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, HomeActivity.REQUEST_PERMISSION_CAMERA);
}
@Override
public void goToGallery() {
try {
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, HomeActivity.REQUEST_CODE_GALLERY);
} catch (Exception e) {
Toast.makeText(requireContext(), R.string.gallery_error_message, Toast.LENGTH_SHORT).show();
}
}
@Override
public void askGalleryPermission() {
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, HomeActivity.REQUEST_PERMISSION_READ_STORAGE);
}
public void updatePhoto(Uri uriImage) {
mDisposableBag.add(AndroidFileUtils.loadBitmap(getActivity(), uriImage)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::updatePhoto, e -> Log.e(TAG, "Error loading image " + uriImage, e)));
updateUserView();
}
public void updatePhoto(Bitmap image) {
mSourcePhoto = image;
AvatarDrawable avatarDrawable = new AvatarDrawable.Builder()
.withPhoto(image)
.withNameData(null, mAccountService.getCurrentAccount().getRegisteredName())
.withId(mAccountService.getCurrentAccount().getUri())
.withCircleCrop(true)
.build(getContext());
mDisposableBag.add(VCardServiceImpl.loadProfile(mAccountService.getCurrentAccount())
.map(profile -> avatarDrawable)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(avatar -> mProfilePhoto.setImageDrawable(avatar), e-> Log.e(TAG, "Error loading image", e)));
updateUserView();
}
public String getAccountAlias(Account account) {
if (account == null) {
cx.ring.utils.Log.e(TAG, "Not able to get account alias");
return null;
}
String alias = getAlias(account);
return (alias == null) ? account.getAlias() : alias;
}
public String getAlias(Account account) {
if (account == null) {
cx.ring.utils.Log.e(TAG, "Not able to get alias");
return null;
}
VCard vcard = account.getProfile();
if (vcard != null) {
FormattedName name = vcard.getFormattedName();
if (name != null) {
String name_value = name.getValue();
if (name_value != null && !name_value.isEmpty()) {
return name_value;
}
}
}
return null;
}
public String getUri(Account account, CharSequence defaultNameSip) {
if (account.isIP2IP()) {
return defaultNameSip.toString();
}
return account.getDisplayUri();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case HomeActivity.REQUEST_PERMISSION_CAMERA:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
presenter.cameraClicked();
}
break;
case HomeActivity.REQUEST_PERMISSION_READ_STORAGE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
presenter.galleryClicked();
}
break;
}
}
@Override
public void onScrollChanged() {
if (mIsVisible && mScrollView != null) {
((HomeActivity) getActivity()).setToolbarElevation(mScrollView.canScrollVertically(SCROLL_DIRECTION_UP));
}
}
public void setFragmentVisibility(boolean isVisible) {
mIsVisible = isVisible;
}
}
......@@ -33,7 +33,6 @@ import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
......@@ -52,7 +51,7 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import cx.ring.R;
import cx.ring.account.AccountEditionActivity;
import cx.ring.account.AccountEditionFragment;
import cx.ring.adapters.RingtoneAdapter;
import cx.ring.application.JamiApplication;
import cx.ring.model.Account;
......@@ -87,7 +86,7 @@ public class RingtoneActivity extends AppCompatActivity {
JamiApplication.getInstance().getRingInjectionComponent().inject(this);
setContentView(R.layout.activity_ringtone);
super.onCreate(savedInstanceState);
mAccount = mAccountService.getAccount(getIntent().getExtras().getString(AccountEditionActivity.ACCOUNT_ID_KEY));
mAccount = mAccountService.getAccount(getIntent().getExtras().getString(AccountEditionFragment.ACCOUNT_ID_KEY));
/*Toolbar toolbar = findViewById(R.id.ringtoneToolbar);
toolbar.setNavigationOnClickListener(view -> finish());*/
......
/*
* Copyright (C) 2004-2020 Savoir-faire Linux Inc.
*
* Author: AmirHossein Naghshzan <amirhossein.naghshzan@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.client;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.List;
import javax.inject.Inject;
import cx.ring.R;
import cx.ring.model.Account;
import cx.ring.services.AccountService;
import cx.ring.views.AvatarDrawable;
import ezvcard.VCard;
import ezvcard.property.FormattedName;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
public class ToolbarSpinnerAdapter extends ArrayAdapter<Account> {
public static final int TYPE_ACCOUNT = 0;
public static final int TYPE_CREATE_JAMI = 1;
public static final int TYPE_CREATE_SIP = 2;
private static final String TAG = ToolbarSpinnerAdapter.class.getSimpleName();
private final CompositeDisposable mDisposable = new CompositeDisposable();
@Inject
AccountService mAccountService;
private Context mContext;
private List<Account> mAccounts;
public ToolbarSpinnerAdapter(@NonNull Context context, int resource, List<Account> accounts){
super(context, resource, accounts);
mContext = context;
mAccounts = accounts;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
return selectedView(convertView, position);
}
@Override
public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
return dropDownView(convertView, position);
}
@Override
public int getItemViewType(int position) {
if (position == mAccounts.size()) {
return TYPE_CREATE_JAMI;
}
if (position == mAccounts.size() + 1) {
return TYPE_CREATE_SIP;
}
return TYPE_ACCOUNT;
}
@Override
public int getCount() {
return mAccounts.size() + 2;
}
private View selectedView(View convertView , int position){
int type = getItemViewType(position);
ViewHolder holder ;
View rowView = convertView;
if (rowView == null) {
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.item_toolbar_spinner, null, false);
holder.title = rowView.findViewById(R.id.title);
holder.subTitle = rowView.findViewById(R.id.subtitle);
holder.logo = rowView.findViewById(R.id.logo);
holder.logo.setVisibility(View.GONE);
holder.subTitle.setVisibility(View.GONE);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) holder.title.getLayoutParams();
params.leftMargin = 0;
holder.title.setLayoutParams(params);
rowView.setTag(holder);
} else {
holder = (ViewHolder) rowView.getTag();
}
if (type == TYPE_ACCOUNT) {
Account account = getItem(position);
holder.title.setText(getAccountAlias(account));
}
return rowView;
}
private View dropDownView(View convertView , int position){
int type = getItemViewType(position);
ViewHolder holder ;
View rowView = convertView;
if (rowView == null) {
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.item_toolbar_spinner, null, false);
holder.title = rowView.findViewById(R.id.title);
holder.subTitle = rowView.findViewById(R.id.subtitle);
holder.logo = rowView.findViewById(R.id.logo);
rowView.setTag(holder);
} else {
holder = (ViewHolder) rowView.getTag();
}
if (type == TYPE_ACCOUNT) {
Account account = getItem(position);
holder.title.setText(getAccountAlias(account));
holder.subTitle.setText(getUri(account, mContext.getString(R.string.account_type_ip2ip)));
mDisposable.add(AvatarDrawable.load(mContext, account)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(avatar -> holder.logo.setImageDrawable(avatar), e -> Log.e(TAG, "Error loading avatar", e)));
} else {
if (type == TYPE_CREATE_JAMI)
holder.title.setText(R.string.add_ring_account_title);
else
holder.title.setText(R.string.add_sip_account_title);
holder.subTitle.setVisibility(View.GONE);
holder.logo.setImageResource(R.drawable.baseline_add_24);
ViewGroup.LayoutParams logoParam = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
holder.logo.setLayoutParams(logoParam);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) holder.title.getLayoutParams();
params.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
holder.title.setLayoutParams(params);
}
return rowView;
}
private static class ViewHolder {
TextView title;
TextView subTitle;
ImageView logo;
}
private String getAccountAlias(Account account) {
if (account == null) {
cx.ring.utils.Log.e(TAG, "Not able to get account alias");
return null;
}
String alias = getAlias(account);
return (alias == null) ? account.getAlias() : alias;
}
private String getAlias(Account account) {
if (account == null) {
cx.ring.utils.Log.e(TAG, "Not able to get alias");
return null;
}
VCard vcard = account.getProfile();
if (vcard != null) {
FormattedName name = vcard.getFormattedName();
if (name != null) {
String name_value = name.getValue();
if (name_value != null && !name_value.isEmpty()) {
return name_value;
}
}
}
return null;
}
private String getUri(Account account, CharSequence defaultNameSip) {
if (account.isIP2IP()) {
return defaultNameSip.toString();
}
return account.getDisplayUri();
}
}
......@@ -35,7 +35,7 @@ import java.util.Collection;
import butterknife.BindView;
import cx.ring.R;
import cx.ring.account.AccountEditionActivity;
import cx.ring.account.AccountEditionFragment;
import cx.ring.dependencyinjection.JamiInjectionComponent;
import cx.ring.model.CallContact;
import cx.ring.mvp.BaseSupportFragment;
......@@ -74,10 +74,10 @@ public class BlackListFragment extends BaseSupportFragment<BlackListPresenter> i
public void onResume() {
super.onResume();
if (getArguments() == null || getArguments().getString(AccountEditionActivity.ACCOUNT_ID_KEY) == null) {
if (getArguments() == null || getArguments().getString(AccountEditionFragment.ACCOUNT_ID_KEY) == null) {
return;
}
presenter.setAccountId(getArguments().getString(AccountEditionActivity.ACCOUNT_ID_KEY));
presenter.setAccountId(getArguments().getString(AccountEditionFragment.ACCOUNT_ID_KEY));
}
@Override
......
......@@ -34,6 +34,7 @@ import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
import java.util.Objects;
import butterknife.BindView;
import cx.ring.R;
......@@ -53,6 +54,8 @@ public class ContactRequestsFragment extends BaseSupportFragment<ContactRequests
private static final String TAG = ContactRequestsFragment.class.getSimpleName();
public static final String ACCOUNT_ID = TAG + "accountID";
private static final int SCROLL_DIRECTION_UP = -1;
@BindView(R.id.requests_list)
protected RecyclerView mRequestsList;
......@@ -62,7 +65,7 @@ public class ContactRequestsFragment extends BaseSupportFragment<ContactRequests
@BindView(R.id.emptyTextView)
protected TextView mEmptyTextView;
private SmartListAdapter mAdapter;
public SmartListAdapter mAdapter;
@Override
public int getLayout() {
......@@ -77,7 +80,6 @@ public class ContactRequestsFragment extends BaseSupportFragment<ContactRequests
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
setHasOptionsMenu(true);
((HomeActivity) getActivity()).setToolbarState(false, R.string.menu_item_contact_request);
return super.onCreateView(inflater, parent, savedInstanceState);
}
......@@ -100,11 +102,6 @@ public class ContactRequestsFragment extends BaseSupportFragment<ContactRequests
}
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
......@@ -135,6 +132,20 @@ public class ContactRequestsFragment extends BaseSupportFragment<ContactRequests
LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
mRequestsList.setLayoutManager(mLayoutManager);
}
mRequestsList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
((HomeActivity) getActivity()).setToolbarElevation(mRequestsList.canScrollVertically(SCROLL_DIRECTION_UP));
}
});
updateBadge();
}
@Override
......@@ -166,4 +177,8 @@ public class ContactRequestsFragment extends BaseSupportFragment<ContactRequests
public void onItemLongClick(SmartListViewModel smartListViewModel) {
}
private void updateBadge() {
((HomeActivity) Objects.requireNonNull(getActivity())).setBadge(R.id.navigation_requests, mAdapter.getItemCount());
}
}
......@@ -21,7 +21,7 @@ package cx.ring.dependencyinjection;
import javax.inject.Singleton;
import cx.ring.account.AccountEditionActivity;
import cx.ring.account.AccountEditionFragment;
import cx.ring.account.AccountWizardActivity;
import cx.ring.account.HomeAccountCreationFragment;
import cx.ring.account.JamiAccountConnectFragment;
......@@ -38,7 +38,6 @@ import cx.ring.contactrequests.BlackListFragment;
import cx.ring.contactrequests.ContactRequestsFragment;
import cx.ring.facades.ConversationFacade;
import cx.ring.fragments.AccountMigrationFragment;
import cx.ring.fragments.AccountsManagementFragment;
import cx.ring.fragments.AdvancedAccountFragment;
import cx.ring.fragments.CallFragment;
import cx.ring.fragments.ConversationFragment;
......@@ -51,7 +50,6 @@ import cx.ring.fragments.ShareWithFragment;
import cx.ring.fragments.SmartListFragment;
import cx.ring.history.DatabaseHelper;
import cx.ring.launch.LaunchActivity;
import cx.ring.navigation.HomeNavigationFragment;
import cx.ring.service.BootReceiver;
import cx.ring.service.CallNotificationService;
import cx.ring.service.DRingService;
......@@ -93,15 +91,13 @@ import dagger.Component;
public interface JamiInjectionComponent {
void inject(JamiApplication app);
void inject(HomeNavigationFragment view);
void inject(HomeActivity activity);
void inject(DatabaseHelper helper);
void inject(AccountWizardActivity activity);
void inject(AccountEditionActivity activity);
void inject(AccountEditionFragment activity);
void inject(RingtoneActivity activity);
......@@ -109,8 +105,6 @@ public interface JamiInjectionComponent {
void inject(SIPAccountCreationFragment fragment);
void inject(AccountsManagementFragment fragment);
void inject(RingAccountSummaryFragment fragment);
void inject(CallFragment fragment);
......
/*
* Copyright (C) 2004-2019 Savoir-faire Linux Inc.
*
* Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
* Alexandre Lision <alexandre.lision@savoirfairelinux.com>
* Adrien Béraud <adrien.beraud@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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package cx.ring.fragments;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import java.util.List;
import butterknife.BindView;
import cx.ring.R;
import cx.ring.account.AccountEditionActivity;
import cx.ring.account.AccountWizardActivity;
import cx.ring.account.AccountsAdapter;
import cx.ring.account.AccountsManagementPresenter;
import cx.ring.account.AccountsManagementView;
import cx.ring.adapters.AccountView;
import cx.ring.application.JamiApplication;
import cx.ring.client.HomeActivity;
import cx.ring.dependencyinjection.JamiInjectionComponent;
import cx.ring.model.Account;
import cx.ring.mvp.BaseSupportFragment;
import cx.ring.utils.ContentUriHandler;
public class AccountsManagementFragment extends BaseSupportFragment<AccountsManagementPresenter> implements AccountsManagementView,
AccountView.OnAccountActionListener {
public static final int ACCOUNT_CREATE_REQUEST = 1;
public static final int ACCOUNT_EDIT_REQUEST = 2;
static final String TAG = AccountsManagementFragment.class.getSimpleName();
@BindView(R.id.accounts_list)
protected RecyclerView mDnDListView;
@BindView(R.id.empty_account_list)
protected View mEmptyView;
private AccountsAdapter mAccountsAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate: Create Account Management Fragment");
// dependency injection
((JamiApplication) getActivity().getApplication()).getRingInjectionComponent().inject(this);
mAccountsAdapter = new AccountsAdapter(this);
}
@Override
public int getLayout() {
return R.layout.frag_accounts_list;
}
@Override
public void injectFragment(JamiInjectionComponent component) {
component.inject(this);
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
setHasOptionsMenu(true);
mDnDListView.setFocusable(false);
mDnDListView.setHasFixedSize(true);
mDnDListView.setLayoutManager(new LinearLayoutManager(getActivity()));
mDnDListView.setAdapter(mAccountsAdapter);
((HomeActivity) getActivity()).setToolbarState(true, R.string.menu_item_accounts);
super.onViewCreated(view, savedInstanceState);
}
@Override
public void onResume() {
super.onResume();
Log.w(TAG, "onResume()");
FloatingActionButton button = ((HomeActivity) requireActivity()).getActionButton();
button.setOnClickListener(v -> presenter.addClicked());
button.show();
}
@Override
public void onPause() {
super.onPause();
Log.w(TAG, "onPause()");
}
@Override
public void onStop() {
super.onStop();
Log.w(TAG, "onStop()");
FloatingActionButton button = ((HomeActivity) requireActivity()).getActionButton();
button.setOnClickListener(null);
button.hide();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
menu.clear();
}
@Override
public void launchAccountEditActivity(Account account) {
Log.d(TAG, "launchAccountEditActivity: Launch account edit activity");
Intent intent = new Intent(getActivity(), AccountEditionActivity.class)
.setAction(Intent.ACTION_EDIT)
.setData(Uri.withAppendedPath(ContentUriHandler.ACCOUNTS_CONTENT_URI, account.getAccountID()));
startActivityForResult(intent, ACCOUNT_EDIT_REQUEST);
}
@Override
public void launchAccountMigrationActivity(Account account) {
Log.d(TAG, "launchAccountMigrationActivity: Launch account migration activity");
Intent intent = new Intent()
.setClass(getActivity(), AccountWizardActivity.class)
.setData(Uri.withAppendedPath(ContentUriHandler.ACCOUNTS_CONTENT_URI, account.getAccountID()));
startActivityForResult(intent, ACCOUNT_EDIT_REQUEST);
}
@Override
public void launchWizardActivity() {
Intent intent = new Intent(getActivity(), AccountWizardActivity.class);
startActivityForResult(intent, ACCOUNT_CREATE_REQUEST);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public void refresh(final List<Account> accounts) {
mAccountsAdapter.replaceAll(accounts);
if (accounts.isEmpty()) {
mDnDListView.setVisibility(View.GONE);
mEmptyView.setVisibility(View.VISIBLE);
} else {
mDnDListView.setVisibility(View.VISIBLE);
mEmptyView.setVisibility(View.GONE);
}
}
@Override
public void refreshAccount(final Account account) {
mAccountsAdapter.replaceAccount(account);
}
@Override
public void onAccountSelected(Account account) {
presenter.clickAccount(account);
}
@Override
public void onAccountEnabled(Account account) {
presenter.accountEnabled(account);
}
}
......@@ -32,7 +32,7 @@ import android.view.inputmethod.EditorInfo;
import java.util.ArrayList;
import cx.ring.R;
import cx.ring.account.AccountEditionActivity;
import cx.ring.account.AccountEditionFragment;
import cx.ring.application.JamiApplication;
import cx.ring.model.AccountConfig;
import cx.ring.model.ConfigKey;
......@@ -54,7 +54,7 @@ public class AdvancedAccountFragment extends BasePreferenceFragment<AdvancedAcco
addPreferencesFromResource(R.xml.account_advanced_prefs);
Bundle args = getArguments();
presenter.init(args == null ? null : args.getString(AccountEditionActivity.ACCOUNT_ID_KEY));
presenter.init(args == null ? null : args.getString(AccountEditionFragment.ACCOUNT_ID_KEY));
}
@Override
......
......@@ -27,7 +27,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.Typeface;
import android.os.Bundle;
import android.provider.MediaStore;
import android.text.Editable;
......@@ -41,7 +41,10 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.snackbar.Snackbar;
......@@ -53,6 +56,7 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.menu.MenuBuilder;
import androidx.appcompat.view.menu.MenuPopupHelper;
import androidx.appcompat.widget.PopupMenu;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.ViewCompat;
import androidx.recyclerview.widget.DefaultItemAnimator;
......@@ -90,6 +94,7 @@ import cx.ring.services.NotificationService;
import cx.ring.utils.ActionHelper;
import cx.ring.utils.AndroidFileUtils;
import cx.ring.utils.ContentUriHandler;
import cx.ring.utils.DeviceUtils;
import cx.ring.utils.MediaButtonsHelper;
import cx.ring.views.AvatarDrawable;
import io.reactivex.Completable;
......@@ -213,8 +218,15 @@ public class ConversationFragment extends BaseSupportFragment<ConversationPresen
insets.consumeSystemWindowInsets();
return insets;
});
int paddingTop = binding.conversationLayout.getPaddingTop();
ViewCompat.setOnApplyWindowInsetsListener(binding.conversationLayout, (v, insets) -> {
View layout = binding.conversationLayout;
// remove action bar height for tablet layout
if (DeviceUtils.isTablet(getContext())) {
layout.setPadding(layout.getPaddingLeft(), 0, layout.getPaddingRight(), layout.getPaddingBottom());
}
int paddingTop = layout.getPaddingTop();
ViewCompat.setOnApplyWindowInsetsListener(layout, (v, insets) -> {
v.setPadding(
v.getPaddingLeft(),
paddingTop + insets.getSystemWindowInsetTop(),
......@@ -636,6 +648,9 @@ public class ConversationFragment extends BaseSupportFragment<ConversationPresen
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (!this.isVisible()) {
return;
}
inflater.inflate(R.menu.conversation_actions, menu);
mAudioCallBtn = menu.findItem(R.id.conv_action_audiocall);
mVideoCallBtn = menu.findItem(R.id.conv_action_videocall);
......@@ -771,13 +786,55 @@ public class ConversationFragment extends BaseSupportFragment<ConversationPresen
}
private void setupActionbar(CallContact contact) {
if (!this.isVisible()) {
return;
}
ActionBar actionBar = ((AppCompatActivity) requireActivity()).getSupportActionBar();
if (actionBar == null) {
return;
}
Context context = actionBar.getThemedContext();
String displayName = contact.getDisplayName();
String identity = contact.getRingUsername();
if (DeviceUtils.isTablet(getContext())) {
Toolbar toolbar = getActivity().findViewById(R.id.main_toolbar);
TextView title = toolbar.findViewById(R.id.contact_title);
TextView subtitle = toolbar.findViewById(R.id.contact_subtitle);
ImageView logo = toolbar.findViewById(R.id.contact_image);
if (!((HomeActivity) getActivity()).isConversationSelected()) {
title.setText("");
subtitle.setText("");
logo.setImageDrawable(null);
return;
}
logo.setVisibility(View.VISIBLE);
title.setText(displayName);
title.setTextSize(15);
title.setTypeface(null, Typeface.NORMAL);
if (identity != null && !identity.equals(displayName)) {
subtitle.setText(identity);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) title.getLayoutParams();
params.addRule(RelativeLayout.ALIGN_TOP, R.id.contact_image);
title.setLayoutParams(params);
} else {
subtitle.setText("");
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) title.getLayoutParams();
params.removeRule(RelativeLayout.ALIGN_TOP);
params.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
title.setLayoutParams(params);
}
logo.setImageDrawable(mConversationAvatar);
} else {
if (identity != null && !identity.equals(displayName)) {
actionBar.setSubtitle(identity);
}
......@@ -787,6 +844,7 @@ public class ConversationFragment extends BaseSupportFragment<ConversationPresen
actionBar.setLogo(null);
actionBar.setLogo(mConversationAvatar);
}
}
public void blockContactRequest() {
presenter.onBlockIncomingContactRequest();
......
......@@ -35,7 +35,7 @@ import android.text.format.Formatter;
import android.view.inputmethod.EditorInfo;
import cx.ring.R;
import cx.ring.account.AccountEditionActivity;
import cx.ring.account.AccountEditionFragment;
import cx.ring.application.JamiApplication;
import cx.ring.model.Account;
import cx.ring.model.AccountConfig;
......@@ -79,7 +79,7 @@ public class GeneralAccountFragment extends BasePreferenceFragment<GeneralAccoun
public static GeneralAccountFragment newInstance(@NonNull String accountId) {
Bundle bundle = new Bundle();
bundle.putString(AccountEditionActivity.ACCOUNT_ID_KEY, accountId);
bundle.putString(AccountEditionFragment.ACCOUNT_ID_KEY, accountId);
GeneralAccountFragment generalAccountFragment = new GeneralAccountFragment();
generalAccountFragment.setArguments(bundle);
return generalAccountFragment;
......@@ -147,7 +147,7 @@ public class GeneralAccountFragment extends BasePreferenceFragment<GeneralAccoun
super.onCreatePreferences(bundle, rootKey);
Bundle args = getArguments();
presenter.init(args == null ? null : args.getString(AccountEditionActivity.ACCOUNT_ID_KEY));
presenter.init(args == null ? null : args.getString(AccountEditionFragment.ACCOUNT_ID_KEY));
SeekBarPreference filePref = findPreference("acceptIncomingFilesMaxSize");
if (filePref != null) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment