blob: 4d3d6adad7f9e05b6a1de3797b2269e5a746a493 [file] [log] [blame]
Chiao Cheng6c712f42012-11-26 15:35:28 -08001/*
2 * Copyright (C) 2010 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 */
16package com.android.contacts.common.list;
17
18import android.content.Context;
19import android.content.SharedPreferences;
20import android.preference.PreferenceManager;
21
Walter Jang1bdef2f2016-07-19 16:00:26 -070022import com.android.contacts.common.logging.ListEvent;
Chiao Cheng6c712f42012-11-26 15:35:28 -080023import com.android.contacts.common.model.AccountTypeManager;
24import com.android.contacts.common.model.account.AccountWithDataSet;
25
26import java.util.ArrayList;
27import java.util.List;
28
29/**
30 * Manages {@link ContactListFilter}. All methods must be called from UI thread.
31 */
32public abstract class ContactListFilterController {
33
34 // singleton to cache the filter controller
35 private static ContactListFilterControllerImpl sFilterController = null;
36
37 public interface ContactListFilterListener {
38 void onContactListFilterChanged();
39 }
40
41 public static ContactListFilterController getInstance(Context context) {
42 // We may need to synchronize this in the future if background task will call this.
43 if (sFilterController == null) {
44 sFilterController = new ContactListFilterControllerImpl(context);
45 }
46 return sFilterController;
47 }
48
49 public abstract void addListener(ContactListFilterListener listener);
50
51 public abstract void removeListener(ContactListFilterListener listener);
52
53 /**
54 * Return the currently-active filter.
55 */
56 public abstract ContactListFilter getFilter();
57
Walter Jang1bdef2f2016-07-19 16:00:26 -070058 public abstract int getFilterListType();
59
Walter Jang398bca92016-08-02 14:37:57 -070060 /** Whether the persisted filter is a custom filter. */
Walter Jangf2cad222016-07-14 19:49:06 +000061 public abstract boolean isCustomFilterPersisted();
62
Walter Jang398bca92016-08-02 14:37:57 -070063 /** Returns the persisted filter. */
64 public abstract ContactListFilter getPersistedFilter();
65
Chiao Cheng6c712f42012-11-26 15:35:28 -080066 /**
67 * @param filter the filter
68 * @param persistent True when the given filter should be saved soon. False when the filter
69 * should not be saved. The latter case may happen when some Intent requires a certain type of
70 * UI (e.g. single contact) temporarily.
71 */
72 public abstract void setContactListFilter(ContactListFilter filter, boolean persistent);
73
74 public abstract void selectCustomFilter();
75
76 /**
77 * Checks if the current filter is valid and reset the filter if not. It may happen when
78 * an account is removed while the filter points to the account with
79 * {@link ContactListFilter#FILTER_TYPE_ACCOUNT} type, for example. It may also happen if
80 * the current filter is {@link ContactListFilter#FILTER_TYPE_SINGLE_CONTACT}, in
81 * which case, we should switch to the last saved filter in {@link SharedPreferences}.
82 */
83 public abstract void checkFilterValidity(boolean notifyListeners);
84}
85
86/**
87 * Stores the {@link ContactListFilter} selected by the user and saves it to
88 * {@link SharedPreferences} if necessary.
89 */
90class ContactListFilterControllerImpl extends ContactListFilterController {
91 private final Context mContext;
92 private final List<ContactListFilterListener> mListeners =
93 new ArrayList<ContactListFilterListener>();
94 private ContactListFilter mFilter;
95
96 public ContactListFilterControllerImpl(Context context) {
Wenyi Wang14cb7fa2016-06-09 16:50:20 -070097 mContext = context.getApplicationContext();
Chiao Cheng6c712f42012-11-26 15:35:28 -080098 mFilter = ContactListFilter.restoreDefaultPreferences(getSharedPreferences());
99 checkFilterValidity(true /* notify listeners */);
100 }
101
102 @Override
103 public void addListener(ContactListFilterListener listener) {
104 mListeners.add(listener);
105 }
106
107 @Override
108 public void removeListener(ContactListFilterListener listener) {
109 mListeners.remove(listener);
110 }
111
112 @Override
113 public ContactListFilter getFilter() {
114 return mFilter;
115 }
116
Walter Jangf2cad222016-07-14 19:49:06 +0000117 @Override
Walter Jang1bdef2f2016-07-19 16:00:26 -0700118 public int getFilterListType() {
119 return mFilter == null ? ListEvent.ListType.UNKNOWN_LIST : mFilter.toListType();
120 }
121
122 @Override
Walter Jangf2cad222016-07-14 19:49:06 +0000123 public boolean isCustomFilterPersisted() {
Walter Jang398bca92016-08-02 14:37:57 -0700124 final ContactListFilter filter = getPersistedFilter();
Walter Jangf2cad222016-07-14 19:49:06 +0000125 return filter != null && filter.filterType == ContactListFilter.FILTER_TYPE_CUSTOM;
126 }
127
Walter Jang398bca92016-08-02 14:37:57 -0700128 @Override
129 public ContactListFilter getPersistedFilter() {
130 return ContactListFilter.restoreDefaultPreferences(getSharedPreferences());
131 }
132
Chiao Cheng6c712f42012-11-26 15:35:28 -0800133 private SharedPreferences getSharedPreferences() {
134 return PreferenceManager.getDefaultSharedPreferences(mContext);
135 }
136
137 @Override
138 public void setContactListFilter(ContactListFilter filter, boolean persistent) {
Walter Jangf2cad222016-07-14 19:49:06 +0000139 setContactListFilter(filter, persistent, /* notifyListeners */ true);
Chiao Cheng6c712f42012-11-26 15:35:28 -0800140 }
141
Marcus Hagerottd6d5ad52016-10-25 19:25:38 -0700142 private void setContactListFilter(ContactListFilter filter, boolean persistent,
Chiao Cheng6c712f42012-11-26 15:35:28 -0800143 boolean notifyListeners) {
144 if (!filter.equals(mFilter)) {
145 mFilter = filter;
146 if (persistent) {
147 ContactListFilter.storeToPreferences(getSharedPreferences(), mFilter);
148 }
149 if (notifyListeners && !mListeners.isEmpty()) {
150 notifyContactListFilterChanged();
151 }
152 }
153 }
154
155 @Override
156 public void selectCustomFilter() {
157 setContactListFilter(ContactListFilter.createFilterWithType(
Walter Jangf2cad222016-07-14 19:49:06 +0000158 ContactListFilter.FILTER_TYPE_CUSTOM), /* persistent */ true);
Chiao Cheng6c712f42012-11-26 15:35:28 -0800159 }
160
161 private void notifyContactListFilterChanged() {
162 for (ContactListFilterListener listener : mListeners) {
163 listener.onContactListFilterChanged();
164 }
165 }
166
167 @Override
168 public void checkFilterValidity(boolean notifyListeners) {
169 if (mFilter == null) {
170 return;
171 }
172
173 switch (mFilter.filterType) {
174 case ContactListFilter.FILTER_TYPE_SINGLE_CONTACT:
175 setContactListFilter(
176 ContactListFilter.restoreDefaultPreferences(getSharedPreferences()),
177 false, notifyListeners);
178 break;
179 case ContactListFilter.FILTER_TYPE_ACCOUNT:
180 if (!filterAccountExists()) {
181 // The current account filter points to invalid account. Use "all" filter
182 // instead.
183 setContactListFilter(ContactListFilter.createFilterWithType(
184 ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS), true, notifyListeners);
185 }
Tingting Wang0ac73ba2016-07-05 22:33:01 -0700186 break;
Chiao Cheng6c712f42012-11-26 15:35:28 -0800187 }
188 }
189
190 /**
191 * @return true if the Account for the current filter exists.
192 */
193 private boolean filterAccountExists() {
194 final AccountTypeManager accountTypeManager = AccountTypeManager.getInstance(mContext);
195 final AccountWithDataSet filterAccount = new AccountWithDataSet(
196 mFilter.accountName, mFilter.accountType, mFilter.dataSet);
Tingting Wang0ac73ba2016-07-05 22:33:01 -0700197 return accountTypeManager.contains(filterAccount, /* contactWritableOnly */ false);
198 }
Chiao Cheng6c712f42012-11-26 15:35:28 -0800199}