This commit is contained in:
2023-08-14 21:18:50 +05:30
parent 45622f247a
commit 335402cf06
22 changed files with 487 additions and 166 deletions

View File

@@ -2,15 +2,6 @@
<project version="4">
<component name="deploymentTargetDropDown">
<runningDeviceTargetsSelectedWithDialog>
<Target>
<type value="RUNNING_DEVICE_TARGET" />
<deviceKey>
<Key>
<type value="SERIAL_NUMBER" />
<value value="RZCW41EJRPN" />
</Key>
</deviceKey>
</Target>
<Target>
<type value="RUNNING_DEVICE_TARGET" />
<deviceKey>
@@ -25,7 +16,7 @@
<deviceKey>
<Key>
<type value="SERIAL_NUMBER" />
<value value="1215fc6afbbb1205" />
<value value="5203ae2be8ec4353" />
</Key>
</deviceKey>
</Target>

View File

@@ -51,6 +51,8 @@ public class CaregiverDashActivity extends AppCompatActivity implements
startActivity(intent);
finish();
return;
}else{
Toast.makeText(this, "Subscription on.", Toast.LENGTH_SHORT).show();
}
}

View File

@@ -8,7 +8,6 @@ import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.viewpager2.widget.ViewPager2;
import com.ssb.simplitend.R;
@@ -19,7 +18,6 @@ import com.ssb.simplitend.cg_subscription.mvp.SubscriptionContracts;
import com.ssb.simplitend.cg_subscription.mvp.SubscriptionCredentials;
import com.ssb.simplitend.cg_subscription.mvp.SubscriptionPresenter;
import com.ssb.simplitend.databinding.CgSubscriptionLayoutBinding;
import com.ssb.simplitend.welcome.welcomecg.mvvm.CareGiverData;
import com.stripe.android.PaymentConfiguration;
import com.stripe.android.paymentsheet.PaymentSheet;
import com.stripe.android.paymentsheet.PaymentSheetResult;
@@ -31,8 +29,10 @@ import java.util.Map;
import okhttp3.MediaType;
import okhttp3.RequestBody;
public class CgSubscriptionActivity extends AppCompatActivity
implements SubscriptionContracts.GetSubPlansCallback, SubscriptionContracts.PaySubscriptionCallback {
public class CgSubscriptionActivity extends AppCompatActivity
implements SubscriptionContracts.GetSubPlansCallback,
SubscriptionContracts.PaySubscriptionCallback,
SubscriptionContracts.CreateSubscriptionCallback {
private static final String TAG = "CgSubscriptionActivity";
@@ -46,6 +46,8 @@ public class CgSubscriptionActivity extends AppCompatActivity
private PaymentSheet paymentSheet;
private String payment_intent_id, stripe_price_id;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -59,7 +61,8 @@ public class CgSubscriptionActivity extends AppCompatActivity
"Testing!",
"Payment is in testing phase. So each time u open app it ill bring to subsription screen. This ill be updated in next build.",
"Ok, got it.",
((dialogInterface, i) -> {}),
((dialogInterface, i) -> {
}),
null, null);
initViews();
@@ -81,7 +84,7 @@ public class CgSubscriptionActivity extends AppCompatActivity
}
int position = binding.viewPager.getCurrentItem();
if (subscriptionPlans == null || position < 0 || position >= subscriptionPlans.size()){
if (subscriptionPlans == null || position < 0 || position >= subscriptionPlans.size()) {
Toast.makeText(this, "Couldn't load plan.", Toast.LENGTH_SHORT).show();
return;
}
@@ -101,10 +104,21 @@ public class CgSubscriptionActivity extends AppCompatActivity
RequestBody email_body = RequestBody.create(UserDataCache.careGiverData.email, MediaType.parse("text/plain"));
body.put("email", email_body);
RequestBody price_body = RequestBody.create("595", MediaType.parse("text/plain"));
// important part
String plan_price;
try {
float plan_price_float = Float.parseFloat(plan.plan_value);
plan_price_float *= 100; // converting from dollars to cents
plan_price = "" + (int) plan_price_float; // converting to int to remove leading ".0"
} catch (Exception e) {
plan_price = getString(R.string.default_price);
}
RequestBody price_body = RequestBody.create(plan_price, MediaType.parse("text/plain"));
body.put("price", price_body);
RequestBody subscription_xid_body = RequestBody.create("4", MediaType.parse("text/plain"));
RequestBody subscription_xid_body = RequestBody.create(plan.id + "", MediaType.parse("text/plain"));
body.put("subscription_xid", subscription_xid_body);
RequestBody caregiver_xid_body = RequestBody.create("" + UserDataCache.careGiverData.caregiver_xid, MediaType.parse("text/plain"));
@@ -112,6 +126,8 @@ public class CgSubscriptionActivity extends AppCompatActivity
String token = "Bearer " + AppUtil.getCgToken(this);
this.stripe_price_id = plan.stripe_price_id;
presenter.getPaymentCred(token, body, this);
}
@@ -122,13 +138,13 @@ public class CgSubscriptionActivity extends AppCompatActivity
public void onPageSelected(int position) {
super.onPageSelected(position);
if (subscriptionPlans == null
|| position < 0 || position >= subscriptionPlans.size()) return;
|| position < 0 || position >= subscriptionPlans.size()) return;
String btn_text = "Make payment $" + subscriptionPlans.get(position).plan_value;
binding.makePayment.setText(btn_text);
}
});
// loading subscription plans
progressDialog = new ProgressDialog(this);
@@ -157,28 +173,49 @@ public class CgSubscriptionActivity extends AppCompatActivity
Log.d(TAG, "Payment successful");
Toast.makeText(this, "Payment successful.", Toast.LENGTH_SHORT).show();
// TODO: 11-08-2023 do the api call
if (UserDataCache.careGiverData != null){
UserDataCache.careGiverData.isCaregiverTakeSubscription = 1;
Intent intent = new Intent(this, CaregiverDashActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
}
// creating subscription
createSubscription();
}
}
private void createSubscription() {
if (this.stripe_price_id == null || this.payment_intent_id == null){
// something went wrong
Toast.makeText(this, "Something went wrong", Toast.LENGTH_SHORT).show();
return;
}
progressDialog.setTitle("Almost there...");
progressDialog.setMessage("We are verifying your payment.\nDon't leave the app screen.");
progressDialog.setCancelable(false);
progressDialog.show();
Map<String, RequestBody> bodyMap = new HashMap<>();
RequestBody pay_intent_id_body = RequestBody.create(this.payment_intent_id, MediaType.parse("text/plain"));
bodyMap.put("payment_intent_id", pay_intent_id_body);
RequestBody price_id_body = RequestBody.create(this.stripe_price_id, MediaType.parse("text/plain"));
bodyMap.put("price_id", price_id_body);
presenter.createSubscription(bodyMap,
"Bearer " + AppUtil.getCgToken(this),
this);
}
// get payment credentials callback
@Override
public void onPaymentCredFetched(SubscriptionCredentials credentials) {
if (credentials == null){
if (credentials == null) {
progressDialog.dismiss();
Toast.makeText(this, "Something went wrong.", Toast.LENGTH_SHORT).show();
return;
}
this.payment_intent_id = credentials.payment_intent_id;
final PaymentSheet.CustomerConfiguration customerConfig = new PaymentSheet.CustomerConfiguration(
credentials.customerId,
credentials.ephemeralKey
@@ -222,4 +259,33 @@ public class CgSubscriptionActivity extends AppCompatActivity
progressDialog.dismiss();
Toast.makeText(this, "" + message, Toast.LENGTH_SHORT).show();
}
// subscription create callback
@Override
public void onSubscriptionCreated() {
// statically changing the flag of subscription to 1
if (UserDataCache.careGiverData != null){
UserDataCache.careGiverData.isCaregiverTakeSubscription = 1;
}
Intent intent = new Intent(this, CaregiverDashActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
progressDialog.dismiss();
startActivity(intent);
finish();
}
@Override
public void onSubscriptionCreateFailed(Throwable throwable, String message) {
progressDialog.dismiss();
AppUtil.showAlert(this,
getString(R.string.something_went_wrong),
message + "\nNegative response will be handled properly.",
"OK",
((dialogInterface, i) -> {
}), null, null);
}
}

View File

@@ -5,6 +5,7 @@ import com.ssb.simplitend.welcome.welcomepatient.mvvm.models.CallResponse;
import java.util.ArrayList;
import java.util.Map;
import java.util.Objects;
import okhttp3.RequestBody;
import retrofit2.Call;
@@ -25,4 +26,11 @@ public interface SubscriptionApiService {
@Header("Authorization") String token,
@PartMap Map<String, RequestBody> body);
@Multipart
@POST("api/create-subscription")
Call<CallResponse<Object>> createSubscription(
@Header("Authorization") String token,
@PartMap Map<String, RequestBody> bodyMap
);
}

View File

@@ -22,4 +22,10 @@ public interface SubscriptionContracts {
}
interface CreateSubscriptionCallback{
void onSubscriptionCreated();
void onSubscriptionCreateFailed(Throwable throwable, String message);
}
}

View File

@@ -6,5 +6,7 @@ public class SubscriptionCredentials{
public String ephemeralKey;
public String stripe_publish_key;
public String payment_intent_id;
public SubscriptionCredentials(){}
}

View File

@@ -86,4 +86,30 @@ public class SubscriptionPresenter {
}
public void createSubscription(Map<String, RequestBody> bodyMap,
@NonNull String token,
@NonNull SubscriptionContracts.CreateSubscriptionCallback createSubscriptionCallback){
apiService.createSubscription(token, bodyMap)
.enqueue(new Callback<CallResponse<Object>>() {
@Override
public void onResponse(Call<CallResponse<Object>> call, Response<CallResponse<Object>> response) {
if (response.body() != null){
if (response.body().status != 200){
createSubscriptionCallback.onSubscriptionCreateFailed(new Exception(), response.body().message);
return;
}
createSubscriptionCallback.onSubscriptionCreated();
}else{
createSubscriptionCallback.onSubscriptionCreateFailed(new Exception(), "Please try again later.");
}
}
@Override
public void onFailure(Call<CallResponse<Object>> call, Throwable t) {
createSubscriptionCallback.onSubscriptionCreateFailed(new Exception(), "Please try again later.");
}
});
}
}

View File

@@ -425,7 +425,7 @@ ReminderAdapter.ReminderCheckClickListener{
if (today_date == selected_date){
AppUtil.showAlert(requireContext(),
"Are you sure?",
"Do yuo want to check this routine?\nThis cannot be undone.",
"Do yuo want to check this reminder?\nThis cannot be undone.",
getString(R.string.yes),
(dialog, which) -> {
dialog.dismiss();

View File

@@ -90,36 +90,40 @@ public class ReminderAdapter extends RecyclerView.Adapter<ReminderAdapter.Remind
SimpleDateFormat input_sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
SimpleDateFormat output_sdf = new SimpleDateFormat("hh:mm a", Locale.getDefault());
String refill_time;
String refill_time = selectNextReminder(reminder.time1, reminder.time2, reminder.time3);
try {
Date date = input_sdf.parse(reminder.time1);
Date date = input_sdf.parse(refill_time);
refill_time = output_sdf.format(date);
}catch (Exception e){
refill_time = reminder.time1;
// do nothing
}
binding.time.setText(refill_time);
String quantity = reminder.medication_quantity + " capsules";
binding.quantity.setText(quantity);
String quantity = "";
if (reminder.medication_type != null && reminder.medication_type.size() > 0) {
switch (reminder.medication_type.get(0).title){
case "Capsule":
binding.medImg.setImageResource(R.drawable.ic_capsules);
quantity = reminder.medication_quantity + " capsules";
break;
case "Pill":
binding.medImg.setImageResource(R.drawable.ic_pills);
quantity = reminder.medication_quantity + " pills";
break;
case "Drops":
binding.medImg.setImageResource(R.drawable.ic_drops);
quantity = reminder.medication_quantity + " drops";
break;
}
}else{
binding.medImg.setImageResource(R.drawable.ic_capsules);
}
binding.quantity.setText(quantity);
if (reminder.reminder_marked != null){
/*
This routine is done for some day.
@@ -172,6 +176,118 @@ public class ReminderAdapter extends RecyclerView.Adapter<ReminderAdapter.Remind
}
}
@NonNull
private String selectNextReminder(String time1, String time2, String time3) {
ReminderAdapter routineAdapter = (ReminderAdapter) getBindingAdapter();
if (routineAdapter == null) return time1;
// getting selected calendar
Date selected_date = routineAdapter.getSelected_date();
Calendar selected_calendar = Calendar.getInstance();
selected_calendar.setTime(selected_date);
Calendar cur_cal = Calendar.getInstance();
String upcoming_reminder;
if (cur_cal.get(Calendar.DAY_OF_MONTH) == selected_calendar.get(Calendar.DAY_OF_MONTH)) {
// Current date is selected by user
// thus, selecting the upcoming reminder time
upcoming_reminder= selectNextReminder(time1, selectNextReminder(time2, time3));
}else{
// some other day is selected
// thus, showing the first reminder for a day
upcoming_reminder = smallestTime(time1, smallestTime(time2, time3));
}
return upcoming_reminder == null?"None":upcoming_reminder;
}
private String selectNextReminder(String time1, String time2) {
if (time1 == null && time2 == null) return null;
if (time1 == null) return time2;
if (time2 == null) return time1;
// comparing this 2 times with current time
// first converting time string to calendar
SimpleDateFormat input_sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
try {
Date date1 = input_sdf.parse(time1);
Date date2 = input_sdf.parse(time2);
if (date2 == null || date1 == null) throw new Exception();
Calendar cur_cal = Calendar.getInstance();
Date cur_date = new Date(date1.getYear(), date1.getMonth(), date1.getDate(), cur_cal.get(Calendar.HOUR_OF_DAY), cur_cal.get(Calendar.MINUTE), cur_cal.get(Calendar.SECOND));
// All three above dates are of same date 01 Jan 1970
// but, of different times i.e. hh:mm:ss
long t1 = date1.getTime();
long t2 = date2.getTime();
long c_t = cur_date.getTime();
if (t1 < c_t && t2 > c_t){
// t1 time is passed and t2 time is yet to come for the same day
// thus, returning t2
return time2;
}else if (t1 > c_t && t2 < c_t){
// t1 is yet to come for this day, and t2 has already been passed
// thus, returning t1
return time1;
}else if (t1 > c_t && t2 > c_t){
// Both the times are greater than current time, yet to come
// In this case, we show the smallest time
if (t1 < t2) return time1;
else return time2;
}else{
// Last case would be both the times has passed the current time
// thus, showing the last reminder for this day
if (t1 < t2) return time2;
else return time1;
}
}catch (Exception e){
// if something goes wrong, returning the time1
return time1;
}
}
private String smallestTime(String time1, String time2) {
if (time1 == null && time2 == null) return null;
if (time1 == null) return time2;
if (time2 == null) return time1;
// comparing this 2 times with current time
// first converting time string to calendar
SimpleDateFormat input_sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
try {
Date date1 = input_sdf.parse(time1);
Date date2 = input_sdf.parse(time2);
if (date2 == null || date1 == null) throw new Exception();
// All times above dates are of same date 01 Jan 1970
// but, of different times i.e. hh:mm:ss
long t1 = date1.getTime();
long t2 = date2.getTime();
if (t2 < t1) return time2;
else return time1;
}catch (Exception e){
// if something goes wrong, returning the time1
return time1;
}
}
}
public interface ReminderCheckClickListener{

View File

@@ -2,6 +2,7 @@ package com.ssb.simplitend.welcome.welcomecg;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Lifecycle;
import androidx.viewpager2.adapter.FragmentStateAdapter;
@@ -12,8 +13,8 @@ import com.ssb.simplitend.welcome.welcomecg.fragments.onboardfragemts.OnBoardTwo
public class CgOnBoardAdapter extends FragmentStateAdapter {
public CgOnBoardAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
super(fragmentManager, lifecycle);
public CgOnBoardAdapter(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
}
@NonNull

View File

@@ -1,10 +1,13 @@
package com.ssb.simplitend.welcome.welcomecg.fragments;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -58,8 +61,11 @@ public class CgOnBoardFragment extends Fragment {
}
private void initViews() {
setUpDynamicTextSizes();
// initiating view pager
CgOnBoardAdapter adapter = new CgOnBoardAdapter(getChildFragmentManager(), getLifecycle());
CgOnBoardAdapter adapter = new CgOnBoardAdapter(requireActivity());
binding.viewPager.setAdapter(adapter);
binding.indicators.setViewPager(binding.viewPager);
@@ -92,8 +98,7 @@ public class CgOnBoardFragment extends Fragment {
break;
default:
title = getString(R.string.reinventing_connected_ncaregiving);
subtitle = getString(R.string.you_are_always_connected_and_will_be_notified_when_your_loved_ones_need_you);
break;
subtitle = getString(R.string.no_new_gadgets_monitor_your_loved_one_s_activity_using_his_or_her_smartphone);
}
binding.title.setText(title);
@@ -101,6 +106,31 @@ public class CgOnBoardFragment extends Fragment {
}
});
}
private void setUpDynamicTextSizes() {
// Calculate screen dimensions in pixels
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
int screenWidth = displayMetrics.widthPixels;
int screenHeight = displayMetrics.heightPixels;
// Calculate aspect ratio
float aspectRatio = (float) screenHeight / (float) screenWidth;
if (aspectRatio > 2.1){
// screen is taller
binding.title.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.cg_title_tall));
binding.subTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.cg_sub_title_tall));
}else if (aspectRatio > 2){
// screen is normal size
binding.title.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.cg_title_tall_medium));
binding.subTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.cg_sub_title_tall_medium));
}else {
// screen is smaller
binding.title.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.cg_title_small));
binding.subTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.cg_sub_title_small));
}
}
}

View File

@@ -32,6 +32,7 @@ import com.google.i18n.phonenumbers.Phonenumber;
import com.ssb.simplitend.R;
import com.ssb.simplitend.apputils.AppUtil;
import com.ssb.simplitend.apputils.EditTextErrorRemover;
import com.ssb.simplitend.apputils.UserDataCache;
import com.ssb.simplitend.databinding.CgRegisterFragmentBinding;
import com.ssb.simplitend.databinding.PasswordPopUpBinding;
import com.ssb.simplitend.welcome.welcomecg.WelcomeContracts;
@@ -425,6 +426,8 @@ public class CgRegisterFragment extends Fragment implements WelcomeContracts.Reg
public void onCareGiverRegistered(CareGiverData careGiverData, String token) {
Toast.makeText(requireContext(), "Caregiver registered successfully.", Toast.LENGTH_SHORT).show();
UserDataCache.careGiverData = careGiverData;
AppUtil.saveCgData(token, requireContext());
Bundle bundle = new Bundle();

View File

@@ -82,7 +82,13 @@ public class ContactInfoFragment extends Fragment implements WelcomeContracts.De
binding.name.setText(contactData.first_name);
binding.phoneNumber.setText(contactData.phone_number);
binding.email.setText(contactData.email_address);
if (contactData.email_address != null)
{
binding.email.setText(contactData.email_address);
}else{
binding.email.setText("None");
}
if (contactData.relationship == null || contactData.relationship.trim().isEmpty()){
binding.relationship.setVisibility(View.GONE);

View File

@@ -352,7 +352,7 @@ public class CreateContactFragment extends Fragment implements WelcomeContracts.
}
}
if (binding.email.getText().toString().trim().isEmpty()) {
if (mustBeeCaregiver && binding.email.getText().toString().trim().isEmpty()) {
allOkay = false;
binding.email.setError("Required");
}

View File

@@ -7,6 +7,8 @@ import android.view.LayoutInflater;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.bumptech.glide.Glide;
import com.google.android.material.bottomsheet.BottomSheetDialog;
@@ -23,6 +25,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
@@ -40,15 +44,24 @@ public class ContactViewModel extends AndroidViewModel {
private SOSCheckInterface sosCheckInterface;
private final MutableLiveData<ArrayList<ArrayList<Contact>>> mutableContactList;
private final LiveData<ArrayList<ArrayList<Contact>>> live_contact_list;
public ContactViewModel(Application application){
super(application);
this.contactRepository = UserContactRepository.getContactRepository();
mutableContactList = new MutableLiveData<>(null);
live_contact_list = mutableContactList;
}
public LiveData<ArrayList<ArrayList<Contact>>> getLive_contact_list() {
return live_contact_list;
}
public ArrayList<ArrayList<Contact>> getContactList(Context context) {
ArrayList<ArrayList<Contact>> contactLIst = new ArrayList<>();
TreeMap<String, ArrayList<Contact>> contactMap = this.contactRepository.getContactList(context);
HashMap<String, ArrayList<Contact>> contactMap = this.contactRepository.getContactList(context);
for (ArrayList<Contact> contacts: contactMap.values()){
if (contacts != null && contacts.size() > 0){
@@ -56,6 +69,8 @@ public class ContactViewModel extends AndroidViewModel {
}
}
Collections.sort(contactLIst, (contacts, t1) -> contacts.get(0).first_name.compareTo(t1.get(0).first_name));
return contactLIst;
}

View File

@@ -3,14 +3,12 @@ package com.ssb.simplitend.welcome.welcomepatient.fragments.contacts.mvvm;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.telephony.PhoneNumberUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;
import com.ssb.simplitend.apputils.RetrofitHelper;
import com.ssb.simplitend.welcome.welcomepatient.fragments.contacts.mvvm.models.ContactListResponse;
import com.ssb.simplitend.welcome.welcomepatient.mvvm.WelcomeApiService;
@@ -19,11 +17,8 @@ import com.ssb.simplitend.welcome.welcomepatient.mvvm.models.CallResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
@@ -38,35 +33,35 @@ public class UserContactRepository {
private static final String[] PROJECTION = new String[]{
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.NUMBER
};
private static UserContactRepository contactRepository;
private final WelcomeApiService apiService;
private UserContactRepository(){
private UserContactRepository() {
apiService = RetrofitHelper.getRetrofit().create(WelcomeApiService.class);
}
public static synchronized UserContactRepository getContactRepository(){
if (contactRepository == null){
public static synchronized UserContactRepository getContactRepository() {
if (contactRepository == null) {
contactRepository = new UserContactRepository();
}
return contactRepository;
}
public void getRemoteContactList(WelcomeContracts.ContactListContracts contactListContracts, String token){
public void getRemoteContactList(WelcomeContracts.ContactListContracts contactListContracts, String token) {
apiService.getContactList(token).enqueue(new Callback<CallResponse<List<ContactListResponse>>>() {
@Override
public void onResponse(Call<CallResponse<List<ContactListResponse>>> call, Response<CallResponse<List<ContactListResponse>>> response) {
if (response.isSuccessful() && response.body() != null && response.body().result != null){
if (response.isSuccessful() && response.body() != null && response.body().result != null) {
contactListContracts.onResponse(response.body().result);
}else if (response.body() != null && response.body().result != null){
} else if (response.body() != null && response.body().result != null) {
Log.e(TAG, "onResponse: get contact list" + response);
contactListContracts.onFailure(new Exception(response.toString()), response.body().message, response.code());
}else{
} else {
Log.e(TAG, "onResponse: no success response and also response body is null");
contactListContracts.onFailure(new Exception("no success response and also response body is null"), "It's not you, it's us.\nPlease try again later", 1);
}
@@ -87,41 +82,39 @@ public class UserContactRepository {
MultipartBody.Part userImage,
WelcomeContracts.CreateContactInterface createContactInterface,
WelcomeContracts.UpdateContactContracts updateContactContracts,
@NonNull String token){
@NonNull String token) {
apiService.createEditContact(URL, body, intBody, userImage, token).enqueue(new Callback<CallResponse<Contact>>() {
@Override
public void onResponse(Call<CallResponse<Contact>> call, Response<CallResponse<Contact>> response) {
if (response.isSuccessful() && response.body() != null && response.body().result != null){
if (createContactInterface != null)
{
if (response.isSuccessful() && response.body() != null && response.body().result != null) {
if (createContactInterface != null) {
createContactInterface.onContactCreated(response.body().result);
}
if (updateContactContracts != null){
if (updateContactContracts != null) {
updateContactContracts.onContactUpdated();
}
}else if (response.body() != null){
} else if (response.body() != null) {
Log.e(TAG, "onResponse: contact create or edit contact " + response);
if (createContactInterface != null)
{
if (createContactInterface != null) {
createContactInterface.onContactCreateFailed(new Exception(response.toString()), response.body().message, response.code());
}
if (updateContactContracts != null){
if (updateContactContracts != null) {
updateContactContracts.onUpdateFailed();
}
}else{
} else {
Log.e(TAG, "onResponse: no success response and also response body is null");
if (createContactInterface != null){
if (createContactInterface != null) {
createContactInterface.onContactCreateFailed(new Exception("no success response and also response body is null"), "It's not you, it's us.\nPlease try again later", 1);
}
if (updateContactContracts != null){
if (updateContactContracts != null) {
updateContactContracts.onUpdateFailed();
}
@@ -132,12 +125,11 @@ public class UserContactRepository {
public void onFailure(Call<CallResponse<Contact>> call, Throwable t) {
Log.e(TAG, "onFailure: create or update contact ", t);
if (createContactInterface != null)
{
if (createContactInterface != null) {
createContactInterface.onContactCreateFailed(t, "It's not you, it's us.\nPlease try again later.", 1);
}
if (updateContactContracts != null){
if (updateContactContracts != null) {
updateContactContracts.onUpdateFailed();
}
}
@@ -146,14 +138,14 @@ public class UserContactRepository {
}
public void deleteContact(int contact_id, String token,
@NonNull WelcomeContracts.DeleteContactInterface deleteContactInterface){
@NonNull WelcomeContracts.DeleteContactInterface deleteContactInterface) {
apiService.deleteContact(token, contact_id)
.enqueue(new Callback<CallResponse<String>>() {
@Override
public void onResponse(Call<CallResponse<String>> call, Response<CallResponse<String>> response) {
if (response.isSuccessful()){
if (response.isSuccessful()) {
deleteContactInterface.onContactDelete();
}else{
} else {
deleteContactInterface.onContactDeleteFailed();
Log.e(TAG, "onResponse: delete contact message " + response.message() + " " +
"code " + response.code());
@@ -168,13 +160,13 @@ public class UserContactRepository {
});
}
public TreeMap<String, ArrayList<Contact>> getContactList(Context context) {
public HashMap<String, ArrayList<Contact>> getContactList(Context context) {
/*
key -> name
values -> different contacts with same name
*/
TreeMap<String, ArrayList<Contact>> contactMap = new TreeMap<>();
HashMap<String, ArrayList<Contact>> contactMap = new HashMap<>();
ContentResolver cr = context.getContentResolver();
@@ -187,12 +179,14 @@ public class UserContactRepository {
if (cursor != null) {
try {
final int c_id_index = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID);
final int nameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
final int numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
while (cursor.moveToNext()) {
String name = cursor.getString(nameIndex);
String number = cursor.getString(numberIndex);
String c_id = cursor.getString(c_id_index);
if (number == null) continue;
if (name == null || name.isEmpty()) name = "No name";
@@ -201,28 +195,65 @@ public class UserContactRepository {
ArrayList<Contact> contactList;
if (contactMap.containsKey(name)){
if (contactMap.containsKey(c_id)) {
// there is already number associate with this name
// thus, adding to the existing contact list against the name
contactList = contactMap.get(name);
}else{
contactList = contactMap.get(c_id);
} else {
contactList = new ArrayList<>();
}
if (contactList == null) contactList = new ArrayList<>();
contactList.add(contact);
contactMap.put(name, contactList);
contactMap.put(c_id, contactList);
}
}catch (Exception e){
} catch (Exception e) {
// do nothing
}
finally {
} finally {
cursor.close();
}
}
getEmailForContact(context, contactMap);
return contactMap;
}
private void getEmailForContact(Context context, HashMap<String, ArrayList<Contact>> contactMap) {
Uri emailUri = ContactsContract.CommonDataKinds.Email.CONTENT_URI;
String[] emailProjection = {
ContactsContract.CommonDataKinds.Email.ADDRESS,
ContactsContract.CommonDataKinds.Email.CONTACT_ID
};
try (Cursor emailCursor = context.getContentResolver().query(emailUri, emailProjection, null, null, null)) {
if (emailCursor != null) {
final int email_index = emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS);
final int c_id_index = emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.CONTACT_ID);
final int count = emailCursor.getCount();
if (emailCursor.moveToNext())
{
String email = emailCursor.getString(email_index);
String c_id = emailCursor.getString(c_id_index);
if (contactMap.containsKey(c_id)){
ArrayList<Contact> contacts = contactMap.get(c_id);
if (contacts != null){
for (Contact contact: contacts){
if (contact != null){
contact.email_address = email;
}
}
}
}
}
}
}catch (Exception e){
Log.e(TAG, "getEmailForContact: ", e);
}
}
}

View File

@@ -25,6 +25,7 @@ public class ContactData implements Serializable {
public ContactData(Contact contact){
this.first_name = contact.first_name;
this.phone_number = contact.phone_number;
this.email_address = contact.email_address;
}
public ContactData(int id) {

View File

@@ -179,7 +179,7 @@ public class SplashFragment extends Fragment
// patient is linked with the caregiver
int cg_security = AppUtil.getWantSecurityFlag(requireContext());
if (cg_security == AppUtil.NOT_ASKED_CG_SECURITY){
if (cg_security == AppUtil.NOT_ASKED_CG_SECURITY || cg_security == AppUtil.CG_SECURITY_NEEDED){
// user want their app to be secure
gotoCgAuthScreen();
}else{

View File

@@ -123,7 +123,7 @@
android:drawableStart="@drawable/ic_dosage"
android:drawablePadding="10dp"
android:maxLength="3"
android:maxLength="6"
android:autofillHints="@null"
android:inputType="numberDecimal"

View File

@@ -1,132 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:weightSum="10"
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
android:background="@color/white"
android:orientation="vertical"
android:weightSum="10">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="6"/>
android:layout_marginBottom="@dimen/_5sdp"
app:layout_constraintBottom_toTopOf="@+id/indicators"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<me.relex.circleindicator.CircleIndicator3
android:id="@+id/indicators"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5"
app:ci_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:ci_drawable="@drawable/selected_dot_primary"
app:ci_drawable_unselected="@drawable/unselected_dot_accent"
app:ci_gravity="center"
app:ci_width="@dimen/_6sdp"
app:ci_height="@dimen/_6sdp"
app:ci_width="@dimen/_6sdp"
/>
android:layout_marginBottom="@dimen/_10sdp"
<LinearLayout
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@+id/title"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2.5"
android:orientation="vertical"
android:gravity="center_vertical"
>
android:layout_height="wrap_content"
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/_15sdp"
android:layout_marginEnd="15dp"
android:layout_marginBottom="@dimen/_5sdp"
android:fontFamily="@font/nunito_semibold"
android:text="@string/reinventing_connected_ncaregiving"
android:fontFamily="@font/nunito_semibold"
android:textColor="@color/black"
android:textSize="@dimen/_20ssp"
android:textColor="@color/black"
android:textSize="@dimen/_22ssp"
app:layout_constraintBottom_toTopOf="@+id/sub_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:text="@string/reinventing_connected_ncaregiving" />
android:layout_marginHorizontal="15dp"
<TextView
android:id="@+id/sub_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
android:layout_marginStart="@dimen/_15sdp"
android:layout_marginEnd="@dimen/_15sdp"
android:layout_marginBottom="@dimen/_15sdp"
android:fontFamily="@font/nunito_regular"
<TextView
android:id="@+id/sub_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/no_new_gadgets_monitor_your_loved_one_s_activity_using_his_or_her_smartphone"
android:textColor="@color/black"
android:text="@string/be_notified_if_your_loved_one_ventures_too_far_from_home_or_a_designated_safe_area"
android:fontFamily="@font/nunito_regular"
android:textColor="@color/black"
android:textSize="@dimen/_18ssp"
android:layout_marginHorizontal="15dp"
android:layout_marginTop="5dp"
/>
</LinearLayout>
android:textSize="@dimen/_18ssp"
app:layout_constraintBottom_toTopOf="@+id/relativeLayout2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<RelativeLayout
android:id="@+id/relativeLayout2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
>
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:layout_marginBottom="@dimen/_5sdp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/next_btn"
android:layout_width="@dimen/_30sdp"
android:layout_height="@dimen/_30sdp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:src="@drawable/ic_next"
android:visibility="visible"
app:civ_circle_background_color="@color/color_primary"
/>
<TextView
android:id="@+id/skip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/skip"
android:layout_centerVertical="true"
android:fontFamily="@font/nunito_semibold"
android:text="@string/skip"
android:textColor="@color/black"
android:textSize="@dimen/_18ssp"
android:layout_centerVertical="true"
android:layout_margin="15dp"
/>
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/next_btn"
android:layout_width="@dimen/_40sdp"
android:layout_height="@dimen/_40sdp"
app:civ_circle_background_color="@color/color_primary"
android:src="@drawable/ic_next"
android:layout_centerVertical="true"
android:layout_alignParentEnd="true"
android:layout_margin="15dp"
android:paddingVertical="@dimen/_10sdp"
/>
<com.google.android.material.button.MaterialButton
android:id="@+id/gets_started"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:backgroundTint="@color/color_primary"
android:fontFamily="@font/nunito_regular"
android:paddingVertical="@dimen/_10sdp"
android:text="@string/get_started"
android:textAllCaps="false"
android:textAppearance="@style/TextAppearance.Material3.TitleMedium"
android:textColor="@color/white_bg"
android:visibility="visible"
android:layout_marginHorizontal="15dp"
android:layout_marginVertical="5dp"
android:visibility="gone"
app:cornerRadius="10dp" />
</RelativeLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -12,4 +12,12 @@
<dimen name="sub_title_tall_medium">@dimen/_16ssp</dimen>
<dimen name="sub_title_small">@dimen/_14ssp</dimen>
<dimen name="cg_title_tall">@dimen/_22ssp</dimen>
<dimen name="cg_title_tall_medium">@dimen/_20ssp</dimen>
<dimen name="cg_title_small">@dimen/_18ssp</dimen>
<dimen name="cg_sub_title_tall">@dimen/_18ssp</dimen>
<dimen name="cg_sub_title_tall_medium">@dimen/_16ssp</dimen>
<dimen name="cg_sub_title_small">@dimen/_14ssp</dimen>
</resources>

View File

@@ -249,10 +249,10 @@
<string name="sync_with_caregiver_app_to_proceed">Install Caregiver app to proceed.</string>
<string name="your_setup_is_in_proceed">Your profile is being updated</string>
<string name="reinventing_connected_ncaregiving">Reinventing connected\nCaregiving</string>
<string name="check_your_loved_one_s_medication_schedule">Check your loved ones medication schedule.</string>
<string name="check_your_loved_one_s_medication_schedule">Update your loved one\'s profile information.</string>
<string name="setup_a_geofence_to_protect_your_loved_one">Setup a geofence to\nprotect your loved one.</string>
<string name="you_are_always_connected_and_will_be_notified_when_your_loved_ones_need_you">You are always connected and will be notified when your loved ones need you.</string>
<string name="application_will_notify_you_when_it_is_time_for_your_loved_one_to_take_his_her_medication">Application will notify you when it is time for your loved one to take his/her medication.</string>
<string name="you_are_always_connected_and_will_be_notified_when_your_loved_ones_need_you">Be notified if your loved one ventures too far from home or a designated safe area</string>
<string name="application_will_notify_you_when_it_is_time_for_your_loved_one_to_take_his_her_medication">For example, you may use your phone to examine and verify your loved one\'s medication schedule.</string>
<string name="be_notified_if_your_loved_one_ventures_too_far_from_home_or_a_designated_safe_area">Be notified if your loved one ventures too far from home or a designated safe area.</string>
<string name="skip">Skip</string>
<string name="get_started">Get started</string>
@@ -260,7 +260,7 @@
<string name="enter_your_basic_details_like_name_number_email_address_pin"><![CDATA[Enter your basic details like Name, Number, Email, Address & Pin]]></string>
<string name="accept_invitation">Accept invitation</string>
<string name="accept_your_loved_one_s_invitation_to_connect">Accept your loved one\'s invitation to connect</string>
<string name="subscribe">Subscribe !</string>
<string name="subscribe">Subscribe</string>
<string name="complete_application_subscription">Complete application subscription</string>
<string name="you_are_ready">You are ready!</string>
<string name="your_phone_is_linked_to_your_loved_one">Your phone is linked to your loved one.</string>
@@ -307,5 +307,7 @@
<string name="security">Security</string>
<string name="to_enhance_the_security_of_your_account_please_add_biometric_authentication_using_either_face_id_or_fingerprint">To enhance the security of your account, please add biometric authentication using either Face ID or Fingerprint.</string>
<string name="setup_with_fingerprint_or_faceid">Setup security</string>
<string name="no_new_gadgets_monitor_your_loved_one_s_activity_using_his_or_her_smartphone">No new gadgets! monitor your loved one\'s activity using his or her smartphone</string>
<string name="default_price">595</string>
</resources>