1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.car.dialer.ui.favorite;
18 
19 import android.content.Context;
20 import android.content.res.Resources;
21 import android.graphics.Rect;
22 import android.os.Bundle;
23 import android.view.View;
24 
25 import androidx.annotation.NonNull;
26 import androidx.annotation.Nullable;
27 import androidx.lifecycle.ViewModelProvider;
28 import androidx.recyclerview.widget.GridLayoutManager;
29 import androidx.recyclerview.widget.RecyclerView;
30 
31 import com.android.car.dialer.Constants;
32 import com.android.car.dialer.R;
33 import com.android.car.dialer.telecom.UiCallManager;
34 import com.android.car.dialer.ui.common.DialerListBaseFragment;
35 import com.android.car.dialer.ui.common.DialerUtils;
36 import com.android.car.telephony.common.Contact;
37 import com.android.car.ui.recyclerview.DelegatingContentLimitingAdapter;
38 
39 import javax.inject.Inject;
40 
41 import dagger.hilt.android.AndroidEntryPoint;
42 
43 /**
44  * Contains a list of favorite contacts.
45  */
46 @AndroidEntryPoint(DialerListBaseFragment.class)
47 public class FavoriteFragment extends Hilt_FavoriteFragment {
48     @Inject UiCallManager mUiCallManager;
49 
50     private DelegatingContentLimitingAdapter<FavoriteContactViewHolder>
51             mContentLimitingAdapter;
52 
53     /**
54      * Constructs a new {@link FavoriteFragment}
55      */
newInstance()56     public static FavoriteFragment newInstance() {
57         return new FavoriteFragment();
58     }
59 
60     @Override
onViewCreated(@onNull View view, @Nullable Bundle savedInstanceState)61     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
62         super.onViewCreated(view, savedInstanceState);
63         getRecyclerView().addItemDecoration(new ItemSpacingDecoration());
64         getRecyclerView().setItemAnimator(null);
65 
66         FavoriteAdapter favoriteAdapter = new FavoriteAdapter();
67         favoriteAdapter.setOnAddFavoriteClickedListener(this::onAddFavoriteClicked);
68 
69         FavoriteViewModel favoriteViewModel = new ViewModelProvider(getActivity()).get(
70                 FavoriteViewModel.class);
71         favoriteAdapter.setOnListItemClickedListener(this::onItemClicked);
72         favoriteViewModel.getFavoriteContacts().observe(this, contacts -> {
73             if (contacts.isLoading()) {
74                 showLoading();
75             } else if (contacts.getData() == null) {
76                 showEmpty(Constants.INVALID_RES_ID, R.string.favorites_empty,
77                         R.string.no_favorites_added, R.string.add_favorite_button,
78                         v -> onAddFavoriteClicked(), true);
79             } else {
80                 favoriteAdapter.setFavoriteContacts(contacts.getData());
81                 int contactCount = contacts.getData().size();
82                 mContentLimitingAdapter.updateUnderlyingDataChanged(contactCount,
83                         DialerUtils.validateListLimitingAnchor(
84                                 contactCount,
85                                 favoriteAdapter.getLastLimitingAnchorIndex()));
86                 showContent();
87             }
88         });
89         favoriteViewModel.getSortOrderLiveData().observe(this,
90                 v -> favoriteAdapter.setSortMethod(v));
91 
92         mContentLimitingAdapter =
93                 new DelegatingContentLimitingAdapter<>(
94                         favoriteAdapter,
95                         R.id.favorite_list_uxr_config);
96         getRecyclerView().setAdapter(mContentLimitingAdapter);
97         getUxrContentLimiter().setAdapter(mContentLimitingAdapter);
98     }
99 
100     @NonNull
101     @Override
createLayoutManager()102     protected RecyclerView.LayoutManager createLayoutManager() {
103         return new FavoriteLayoutManager(getContext());
104     }
105 
onItemClicked(Contact contact)106     private void onItemClicked(Contact contact) {
107         DialerUtils.promptForPrimaryNumber(getContext(), contact, (phoneNumber, always) ->
108                 mUiCallManager.placeCall(phoneNumber.getRawNumber()));
109     }
110 
onAddFavoriteClicked()111     private void onAddFavoriteClicked() {
112         pushContentFragment(AddFavoriteFragment.newInstance(), null);
113     }
114 
115     private class ItemSpacingDecoration extends RecyclerView.ItemDecoration {
116 
117         @Override
getItemOffsets(@onNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state)118         public void getItemOffsets(@NonNull Rect outRect, @NonNull View view,
119                 @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
120             super.getItemOffsets(outRect, view, parent, state);
121             Resources resources = FavoriteFragment.this.getContext().getResources();
122             int numColumns = resources.getInteger(R.integer.favorite_fragment_grid_column);
123             int leftPadding =
124                     resources.getDimensionPixelOffset(R.dimen.favorite_card_space_horizontal);
125             int verticalPadding =
126                     resources.getDimensionPixelOffset(R.dimen.favorite_card_space_vertical);
127 
128             if (parent.getChildAdapterPosition(view) % numColumns == 0) {
129                 leftPadding = 0;
130             }
131 
132             outRect.set(leftPadding, verticalPadding, 0, verticalPadding);
133         }
134     }
135 
136     private class FavoriteLayoutManager extends GridLayoutManager {
FavoriteLayoutManager(Context context)137         private FavoriteLayoutManager(Context context) {
138             super(context,
139                     context.getResources().getInteger(R.integer.favorite_fragment_grid_column));
140             SpanSizeLookup spanSizeLookup = new SpanSizeLookup() {
141                 @Override
142                 public int getSpanSize(int position) {
143                     if (mContentLimitingAdapter.getItemViewType(position)
144                             == FavoriteAdapter.TYPE_HEADER
145                             || mContentLimitingAdapter.getItemViewType(position)
146                             == mContentLimitingAdapter.getScrollingLimitedMessageViewType()) {
147                         return getSpanCount();
148                     }
149                     return 1;
150                 }
151             };
152             setSpanSizeLookup(spanSizeLookup);
153         }
154     }
155 }
156