| /* |
| * Copyright (C) 2004-2020 Savoir-faire Linux Inc. |
| * |
| * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com> |
| * Author: 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.model; |
| |
| import java.util.ArrayList; |
| import java.util.Date; |
| |
| import cx.ring.utils.StringUtils; |
| import io.reactivex.Emitter; |
| import io.reactivex.Observable; |
| import io.reactivex.subjects.BehaviorSubject; |
| import io.reactivex.subjects.Subject; |
| |
| public class CallContact { |
| protected static final String TAG = CallContact.class.getSimpleName(); |
| |
| public static final int UNKNOWN_ID = -1; |
| public static final int DEFAULT_ID = 0; |
| public static final String PREFIX_RING = Uri.RING_URI_SCHEME; |
| |
| public enum Status {BANNED, REQUEST_SENT, CONFIRMED, NO_REQUEST} |
| |
| private long mId; |
| private String mKey; |
| private String mUsername = null; |
| private long mPhotoId; |
| private final ArrayList<Phone> mPhones; |
| private final boolean isUser; |
| private boolean stared = false; |
| private boolean isFromSystem = false; |
| private Status mStatus = Status.NO_REQUEST; |
| private Date mAddedDate = null; |
| private boolean mOnline = false; |
| |
| private boolean usernameLoaded = false; |
| public boolean detailsLoaded = false; |
| |
| // Profile |
| private String mDisplayName; |
| private Object mContactPhoto = null; |
| |
| private final Subject<CallContact> mContactUpdates = BehaviorSubject.create(); |
| private Observable<CallContact> mContactObservable; |
| |
| private Observable<Boolean> mContactPresenceObservable; |
| private Emitter<Boolean> mContactPresenceEmitter; |
| |
| public CallContact(long cID) { |
| this(cID, null, null, UNKNOWN_ID); |
| } |
| |
| public CallContact(long cID, String k, String displayName, long photoID) { |
| this(cID, k, displayName, photoID, new ArrayList<>(), false); |
| } |
| |
| private CallContact(long cID, String k, String displayName, long photoID, ArrayList<Phone> p, boolean user) { |
| mId = cID; |
| mKey = k; |
| mDisplayName = displayName; |
| mPhones = p; |
| mPhotoId = photoID; |
| isUser = user; |
| if (cID != UNKNOWN_ID && (displayName == null || !displayName.contains(PREFIX_RING))) { |
| mStatus = Status.CONFIRMED; |
| } |
| } |
| |
| public static CallContact buildSIP(Uri to) { |
| ArrayList<Phone> phones = new ArrayList<>(); |
| phones.add(new Phone(to, 0)); |
| CallContact contact = new CallContact(UNKNOWN_ID, null, null, 0, phones, false); |
| contact.usernameLoaded = true; |
| return contact; |
| } |
| |
| public static CallContact build(String to) { |
| ArrayList<Phone> phones = new ArrayList<>(); |
| phones.add(new Phone(to, 0)); |
| return new CallContact(UNKNOWN_ID, null, null, 0, phones, false); |
| } |
| |
| public Observable<CallContact> getUpdatesSubject() { |
| return mContactUpdates; |
| } |
| public Observable<CallContact> getUpdates() { |
| return mContactObservable; |
| } |
| public void setUpdates(Observable<CallContact> observable) { |
| mContactObservable = observable; |
| } |
| |
| public Observable<Boolean> getPresenceUpdates() { |
| return mContactPresenceObservable; |
| } |
| public void setPresenceUpdates(Observable<Boolean> observable) { |
| mContactPresenceObservable = observable; |
| } |
| public void setPresenceEmitter(Emitter<Boolean> emitter) { |
| if (mContactPresenceEmitter != null && mContactPresenceEmitter != emitter) { |
| mContactPresenceEmitter.onComplete(); |
| } |
| mContactPresenceEmitter = emitter; |
| } |
| |
| public boolean matches(String query) { |
| return (mDisplayName != null && mDisplayName.toLowerCase().contains(query)) |
| || (mUsername != null && mUsername.contains(query)) |
| || (getPrimaryNumber().contains(query)); |
| } |
| |
| public boolean isOnline() { |
| return mOnline; |
| } |
| |
| public void setOnline(boolean present) { |
| if (mContactPresenceEmitter != null) |
| mContactPresenceEmitter.onNext(present); |
| mOnline = present; |
| mContactUpdates.onNext(this); |
| } |
| |
| public void setContactInfos(String k, String displayName, long photo_id) { |
| mKey = k; |
| mDisplayName = displayName; |
| this.mPhotoId = photo_id; |
| if (mUsername == null && displayName.contains(PREFIX_RING)) { |
| mUsername = displayName; |
| } |
| } |
| |
| public static String canonicalNumber(String number) { |
| if (number == null || number.isEmpty()) |
| return null; |
| return new Uri(number).getRawUriString(); |
| } |
| |
| public ArrayList<String> getIds() { |
| ArrayList<String> ret = new ArrayList<>(mPhones.size() + (mId == UNKNOWN_ID ? 0 : 1)); |
| if (mId != UNKNOWN_ID) |
| ret.add("c:" + Long.toHexString(mId)); |
| for (Phone p : mPhones) |
| ret.add(p.getNumber().getRawUriString()); |
| return ret; |
| } |
| |
| public static long contactIdFromId(String id) { |
| if (!id.startsWith("c:")) |
| return UNKNOWN_ID; |
| try { |
| return Long.parseLong(id.substring(2), 16); |
| } catch (Exception e) { |
| return UNKNOWN_ID; |
| } |
| } |
| |
| public long getId() { |
| return mId; |
| } |
| |
| public String getDisplayName() { |
| return !StringUtils.isEmpty(mDisplayName) ? mDisplayName : getRingUsername(); |
| } |
| |
| public String getProfileName() { |
| return mDisplayName; |
| } |
| |
| public long getPhotoId() { |
| return mPhotoId; |
| } |
| |
| public ArrayList<Phone> getPhones() { |
| return mPhones; |
| } |
| |
| public boolean hasNumber(String number) { |
| return hasNumber(new Uri(number)); |
| } |
| |
| public boolean hasNumber(Uri number) { |
| if (number == null || number.isEmpty()) |
| return false; |
| for (Phone p : mPhones) |
| if (p.getNumber().equals(number)) |
| return true; |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return getRingUsername(); |
| } |
| |
| public void setId(long id) { |
| this.mId = id; |
| } |
| |
| public String getKey() { |
| return mKey; |
| } |
| |
| public String getPrimaryNumber() { |
| return getPrimaryUri().getRawRingId(); |
| } |
| public Uri getPrimaryUri() { |
| return getPhones().get(0).getNumber(); |
| } |
| |
| public void setStared() { |
| this.stared = true; |
| } |
| |
| public boolean isStared() { |
| return stared; |
| } |
| |
| public void addPhoneNumber(Uri tel, int cat, String label) { |
| if (!hasNumber(tel)) |
| mPhones.add(new Phone(tel, cat, label)); |
| } |
| |
| public void addNumber(String tel, int cat, String label, Phone.NumberType type) { |
| if (!hasNumber(tel)) |
| mPhones.add(new Phone(tel, cat, label, type)); |
| } |
| |
| public void addNumber(Uri tel, int cat, String label, Phone.NumberType type) { |
| if (!hasNumber(tel)) |
| mPhones.add(new Phone(tel, cat, label, type)); |
| } |
| |
| public boolean isUser() { |
| return isUser; |
| } |
| |
| public boolean hasPhoto() { |
| return mContactPhoto != null; |
| } |
| |
| public Object getPhoto() { |
| return mContactPhoto; |
| } |
| |
| public void setPhoto(Object externalArray) { |
| mContactPhoto = externalArray; |
| } |
| |
| public boolean isFromSystem() { |
| return isFromSystem; |
| } |
| |
| public Status getStatus() { |
| return mStatus; |
| } |
| |
| public void setStatus(Status status) { |
| mStatus = status; |
| } |
| |
| public boolean isBanned() { return mStatus == Status.BANNED; } |
| |
| public void setFromSystem(boolean fromSystem) { |
| isFromSystem = fromSystem; |
| } |
| |
| public void setAddedDate(Date addedDate) { |
| mAddedDate = addedDate; |
| } |
| public Date getAddedDate() { |
| return mAddedDate; |
| } |
| |
| /** |
| * A contact is Unknown when his name == his phone number |
| * |
| * @return true when Name == Number |
| */ |
| public boolean isUnknown() { |
| return mDisplayName == null || mDisplayName.contentEquals(mPhones.get(0).getNumber().getRawUriString()); |
| } |
| |
| public void setDisplayName(String displayName) { |
| mDisplayName = displayName; |
| } |
| |
| public String getRingUsername() { |
| if (!StringUtils.isEmpty(mUsername)) { |
| return mUsername; |
| } else if (usernameLoaded && !mPhones.isEmpty()) { |
| return getPrimaryUri().getRawUriString(); |
| } else { |
| return ""; |
| } |
| } |
| |
| public String getUsername() { |
| return mUsername; |
| } |
| |
| public boolean setUsername(String name) { |
| if (!usernameLoaded || (name != null && !name.equals(mUsername))) { |
| mUsername = name; |
| usernameLoaded = true; |
| mContactUpdates.onNext(this); |
| return true; |
| } |
| return false; |
| } |
| |
| public boolean isUsernameLoaded() { |
| return usernameLoaded; |
| } |
| |
| public void setProfile(String name, Object photo) { |
| if (!StringUtils.isEmpty(name) && !name.startsWith(Uri.RING_URI_SCHEME)) { |
| setDisplayName(name); |
| } |
| if (photo != null) { |
| setPhoto(photo); |
| } |
| detailsLoaded = true; |
| mContactUpdates.onNext(this); |
| } |
| } |