Mukesh Dhungana
2 years ago
17 changed files with 1109 additions and 46 deletions
-
5app/src/main/AndroidManifest.xml
-
5app/src/main/java/com/remit/jmecustomer/features/home/view/HomeActivityV2.java
-
27app/src/main/java/com/remit/jmecustomer/features/mynotifications/MyNotificationViewModelFactory.java
-
71app/src/main/java/com/remit/jmecustomer/features/mynotifications/adapter/MyNotificationListingRVAdapter.java
-
33app/src/main/java/com/remit/jmecustomer/features/mynotifications/adapter/MyNotificationListingRVViewholder.java
-
100app/src/main/java/com/remit/jmecustomer/features/mynotifications/gateway/MyNotificationGateway.java
-
90app/src/main/java/com/remit/jmecustomer/features/mynotifications/model/MyNotificationDTO.java
-
53app/src/main/java/com/remit/jmecustomer/features/mynotifications/model/MyNotificationDetailDTO.java
-
28app/src/main/java/com/remit/jmecustomer/features/mynotifications/presenter/MyNotificationGatewayInterface.java
-
41app/src/main/java/com/remit/jmecustomer/features/mynotifications/presenter/MyNotificationPresenterInterface.java
-
233app/src/main/java/com/remit/jmecustomer/features/mynotifications/presenter/MyNotificationViewModel.java
-
127app/src/main/java/com/remit/jmecustomer/features/mynotifications/view/MyNotificationActivity.java
-
107app/src/main/java/com/remit/jmecustomer/features/mynotifications/view/MyNotificationFragment.java
-
97app/src/main/java/com/remit/jmecustomer/features/mynotifications/view/MyNotificationListingFragment.java
-
121app/src/main/res/layout/activity_home_v2.xml
-
13app/src/main/res/layout/activity_my_notifications.xml
-
4app/src/main/res/values/strings.xml
@ -0,0 +1,27 @@ |
|||||
|
package com.remit.jmecustomer.features.mynotifications; |
||||
|
|
||||
|
import androidx.annotation.NonNull; |
||||
|
import androidx.lifecycle.ViewModel; |
||||
|
import androidx.lifecycle.ViewModelProvider; |
||||
|
|
||||
|
import com.remit.jmecustomer.features.mynotifications.gateway.MyNotificationGateway; |
||||
|
import com.remit.jmecustomer.features.mynotifications.presenter.MyNotificationPresenterInterface; |
||||
|
import com.remit.jmecustomer.features.mynotifications.presenter.MyNotificationViewModel; |
||||
|
|
||||
|
|
||||
|
public class MyNotificationViewModelFactory implements ViewModelProvider.Factory { |
||||
|
private final MyNotificationPresenterInterface.NoticeViewContractInterface view; |
||||
|
|
||||
|
|
||||
|
public MyNotificationViewModelFactory(MyNotificationPresenterInterface.NoticeViewContractInterface view) { |
||||
|
this.view = view; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@SuppressWarnings("unchecked") |
||||
|
@NonNull |
||||
|
@Override |
||||
|
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { |
||||
|
return (T) new MyNotificationViewModel(view,new MyNotificationGateway()); |
||||
|
} |
||||
|
} |
@ -0,0 +1,71 @@ |
|||||
|
package com.remit.jmecustomer.features.mynotifications.adapter; |
||||
|
|
||||
|
import android.view.LayoutInflater; |
||||
|
import android.view.ViewGroup; |
||||
|
|
||||
|
import androidx.annotation.NonNull; |
||||
|
import androidx.recyclerview.widget.RecyclerView; |
||||
|
|
||||
|
import com.remit.jmecustomer.R; |
||||
|
import com.remit.jmecustomer.features.mynotifications.model.MyNotificationDTO; |
||||
|
|
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public class MyNotificationListingRVAdapter extends RecyclerView.Adapter<MyNotificationListingRVViewholder> { |
||||
|
|
||||
|
private final NoticeClickListener listener; |
||||
|
|
||||
|
private List<MyNotificationDTO> noticeList; |
||||
|
|
||||
|
public MyNotificationListingRVAdapter(NoticeClickListener listener) { |
||||
|
this.listener = listener; |
||||
|
noticeList = new ArrayList<>(); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@NonNull |
||||
|
@Override |
||||
|
public MyNotificationListingRVViewholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { |
||||
|
return new MyNotificationListingRVViewholder(LayoutInflater.from(parent.getContext()).inflate(R.layout.notice_list_viewholder_v3, parent, false)); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onBindViewHolder(@NonNull MyNotificationListingRVViewholder holder, int position) { |
||||
|
MyNotificationDTO myNotificationDTO = noticeList.get(holder.getAdapterPosition()); |
||||
|
|
||||
|
holder.notice_title.setText(myNotificationDTO.getTitle()); |
||||
|
holder.notice_date.setText(myNotificationDTO.getCreateDate()); |
||||
|
if ("1".equalsIgnoreCase(myNotificationDTO.getIsRead())) |
||||
|
holder.imgNotificationStat.setBackgroundResource(R.drawable.ic_read); |
||||
|
else |
||||
|
holder.imgNotificationStat.setBackgroundResource(R.drawable.ic_unread); |
||||
|
|
||||
|
holder.itemView.setOnClickListener(view -> { |
||||
|
if (listener != null) |
||||
|
listener.onNoticeClicked(noticeList.get(holder.getAdapterPosition())); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int getItemCount() { |
||||
|
return noticeList.size(); |
||||
|
} |
||||
|
|
||||
|
public void setData(List<MyNotificationDTO> data) { |
||||
|
if (data != null && data.size() > 0) { |
||||
|
this.noticeList.clear(); |
||||
|
this.noticeList.addAll(data); |
||||
|
notifyDataSetChanged(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void resetData() { |
||||
|
this.noticeList = null; |
||||
|
notifyDataSetChanged(); |
||||
|
} |
||||
|
|
||||
|
public interface NoticeClickListener { |
||||
|
void onNoticeClicked(MyNotificationDTO itemModel); |
||||
|
} |
||||
|
} |
@ -0,0 +1,33 @@ |
|||||
|
package com.remit.jmecustomer.features.mynotifications.adapter; |
||||
|
|
||||
|
import android.view.View; |
||||
|
import android.widget.ImageView; |
||||
|
import android.widget.TextView; |
||||
|
|
||||
|
import androidx.annotation.NonNull; |
||||
|
import androidx.recyclerview.widget.RecyclerView; |
||||
|
|
||||
|
import com.remit.jmecustomer.R; |
||||
|
|
||||
|
import butterknife.BindView; |
||||
|
import butterknife.ButterKnife; |
||||
|
|
||||
|
public class MyNotificationListingRVViewholder extends RecyclerView.ViewHolder { |
||||
|
|
||||
|
@BindView(R.id.tv_notification_title) |
||||
|
TextView notice_title; |
||||
|
|
||||
|
@BindView(R.id.tv_status) |
||||
|
TextView notice_status; |
||||
|
|
||||
|
@BindView(R.id.tv_notification_date) |
||||
|
TextView notice_date; |
||||
|
|
||||
|
@BindView(R.id.imgNotificationStat) |
||||
|
ImageView imgNotificationStat; |
||||
|
|
||||
|
public MyNotificationListingRVViewholder(@NonNull View itemView) { |
||||
|
super(itemView); |
||||
|
ButterKnife.bind(this,itemView); |
||||
|
} |
||||
|
} |
@ -0,0 +1,100 @@ |
|||||
|
package com.remit.jmecustomer.features.mynotifications.gateway; |
||||
|
|
||||
|
import com.google.gson.JsonObject; |
||||
|
import com.remit.jmecustomer.base.PrivilegedGateway; |
||||
|
import com.remit.jmecustomer.features.mynotifications.model.MyNotificationDTO; |
||||
|
import com.remit.jmecustomer.features.mynotifications.model.MyNotificationDetailDTO; |
||||
|
import com.remit.jmecustomer.features.mynotifications.presenter.MyNotificationGatewayInterface; |
||||
|
import com.remit.jmecustomer.utils.https.HttpClientV2; |
||||
|
|
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
import io.reactivex.Observable; |
||||
|
import okhttp3.ResponseBody; |
||||
|
|
||||
|
public class MyNotificationGateway extends PrivilegedGateway implements MyNotificationGatewayInterface { |
||||
|
|
||||
|
@Override |
||||
|
public Observable<ResponseBody> getNoticeList(String auth, String customerID) { |
||||
|
JsonObject jsonObject=new JsonObject() ; |
||||
|
jsonObject.addProperty("customerId",customerID); |
||||
|
return HttpClientV2.getInstance().getNoticeList(auth,jsonObject); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Observable<ResponseBody> getNoticeDetail(String auth, String noticeId) { |
||||
|
JsonObject jsonObject=new JsonObject() ; |
||||
|
jsonObject.addProperty("rowId",noticeId); |
||||
|
return HttpClientV2.getInstance().getNoticeDetail(auth,jsonObject); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Observable<ResponseBody> setNoticeStatus(String auth, String tranId, String yesNo) { |
||||
|
return HttpClientV2.getInstance().setNoticeReadStatus(auth,tranId,yesNo); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<MyNotificationDTO> mockNoticeList() { |
||||
|
List<MyNotificationDTO> noticeList=new ArrayList<>(); |
||||
|
|
||||
|
MyNotificationDTO myNotificationDTO0 =new MyNotificationDTO(); |
||||
|
myNotificationDTO0.setRowId("0"); |
||||
|
myNotificationDTO0.setTitle("Title 1"); |
||||
|
myNotificationDTO0.setCreateDate("2077/01/01"); |
||||
|
myNotificationDTO0.setIsRead("0"); |
||||
|
myNotificationDTO0.setType("1"); |
||||
|
myNotificationDTO0.setExtra("12"); |
||||
|
noticeList.add(myNotificationDTO0); |
||||
|
|
||||
|
MyNotificationDTO myNotificationDTO1 =new MyNotificationDTO(); |
||||
|
myNotificationDTO1.setRowId("1"); |
||||
|
myNotificationDTO1.setTitle("Title 2"); |
||||
|
myNotificationDTO1.setCreateDate("2077/01/02"); |
||||
|
myNotificationDTO1.setIsRead("1"); |
||||
|
myNotificationDTO1.setType("0"); |
||||
|
noticeList.add(myNotificationDTO1); |
||||
|
|
||||
|
|
||||
|
MyNotificationDTO myNotificationDTO2 =new MyNotificationDTO(); |
||||
|
myNotificationDTO2.setRowId("2"); |
||||
|
myNotificationDTO2.setTitle("Title 3"); |
||||
|
myNotificationDTO2.setCreateDate("2077/01/02"); |
||||
|
myNotificationDTO2.setIsRead("0"); |
||||
|
myNotificationDTO2.setType("1"); |
||||
|
myNotificationDTO2.setExtra("13"); |
||||
|
noticeList.add(myNotificationDTO2); |
||||
|
|
||||
|
|
||||
|
MyNotificationDTO myNotificationDTO3 =new MyNotificationDTO(); |
||||
|
myNotificationDTO3.setRowId("3"); |
||||
|
myNotificationDTO3.setTitle("Title 4"); |
||||
|
myNotificationDTO3.setCreateDate("2077/01/03"); |
||||
|
myNotificationDTO3.setIsRead("1"); |
||||
|
myNotificationDTO3.setType("1"); |
||||
|
myNotificationDTO3.setExtra("14"); |
||||
|
noticeList.add(myNotificationDTO3); |
||||
|
|
||||
|
|
||||
|
MyNotificationDTO myNotificationDTO4 =new MyNotificationDTO(); |
||||
|
myNotificationDTO4.setRowId("4"); |
||||
|
myNotificationDTO4.setTitle("Title 5"); |
||||
|
myNotificationDTO4.setCreateDate("2077/01/04"); |
||||
|
myNotificationDTO4.setIsRead("1"); |
||||
|
myNotificationDTO4.setType("0"); |
||||
|
noticeList.add(myNotificationDTO4); |
||||
|
|
||||
|
return noticeList; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public MyNotificationDetailDTO mockNoticeDetail() { |
||||
|
MyNotificationDetailDTO myNotificationDetailDTO =new MyNotificationDetailDTO(); |
||||
|
myNotificationDetailDTO.setTitle("Title 1"); |
||||
|
myNotificationDetailDTO.setBody("This is Detail body of Title 1"); |
||||
|
myNotificationDetailDTO.setCreateDate("2077/01/01"); |
||||
|
myNotificationDetailDTO.setImageURL("https://p18cdn4static.sharpschool.com/UserFiles/Servers/Server_414551/Image/News/District%20News/Title%201.jpg"); |
||||
|
return myNotificationDetailDTO; |
||||
|
} |
||||
|
} |
@ -0,0 +1,90 @@ |
|||||
|
package com.remit.jmecustomer.features.mynotifications.model; |
||||
|
|
||||
|
import com.google.gson.annotations.Expose; |
||||
|
import com.google.gson.annotations.SerializedName; |
||||
|
|
||||
|
public class MyNotificationDTO { |
||||
|
|
||||
|
@SerializedName("rowId") |
||||
|
@Expose |
||||
|
private String rowId; |
||||
|
@SerializedName("title") |
||||
|
@Expose |
||||
|
private String title; |
||||
|
@SerializedName("createDate") |
||||
|
@Expose |
||||
|
private String createDate; |
||||
|
@SerializedName("isRead")// 0 => Not Read, 1=> Read, |
||||
|
@Expose |
||||
|
private String isRead; |
||||
|
|
||||
|
@SerializedName("type")//0 => General Notice, 1=> Txn Notice |
||||
|
@Expose |
||||
|
private String type; |
||||
|
|
||||
|
@SerializedName("extra")//If type==1, then extra will have Txn id |
||||
|
@Expose |
||||
|
private String extra; |
||||
|
|
||||
|
@SerializedName("DisplayActions") |
||||
|
@Expose |
||||
|
private String displayActions; |
||||
|
|
||||
|
|
||||
|
|
||||
|
public String getRowId() { |
||||
|
return rowId; |
||||
|
} |
||||
|
|
||||
|
public void setRowId(String rowId) { |
||||
|
this.rowId = rowId; |
||||
|
} |
||||
|
|
||||
|
public String getTitle() { |
||||
|
return title; |
||||
|
} |
||||
|
|
||||
|
public void setTitle(String title) { |
||||
|
this.title = title; |
||||
|
} |
||||
|
|
||||
|
public String getCreateDate() { |
||||
|
return createDate; |
||||
|
} |
||||
|
|
||||
|
public void setCreateDate(String createDate) { |
||||
|
this.createDate = createDate; |
||||
|
} |
||||
|
|
||||
|
public String getIsRead() { |
||||
|
return isRead; |
||||
|
} |
||||
|
|
||||
|
public void setIsRead(String isRead) { |
||||
|
this.isRead = isRead; |
||||
|
} |
||||
|
|
||||
|
public String getType() { |
||||
|
return type; |
||||
|
} |
||||
|
|
||||
|
public void setType(String type) { |
||||
|
this.type = type; |
||||
|
} |
||||
|
|
||||
|
public String getExtra() { |
||||
|
return extra; |
||||
|
} |
||||
|
|
||||
|
public void setExtra(String extra) { |
||||
|
this.extra = extra; |
||||
|
} |
||||
|
|
||||
|
public String getDisplayActions() { |
||||
|
return displayActions; |
||||
|
} |
||||
|
|
||||
|
public void setDisplayActions(String displayActions) { |
||||
|
this.displayActions = displayActions; |
||||
|
} |
||||
|
} |
@ -0,0 +1,53 @@ |
|||||
|
package com.remit.jmecustomer.features.mynotifications.model; |
||||
|
|
||||
|
import com.google.gson.annotations.Expose; |
||||
|
import com.google.gson.annotations.SerializedName; |
||||
|
|
||||
|
public class MyNotificationDetailDTO { |
||||
|
|
||||
|
|
||||
|
@SerializedName("title") |
||||
|
@Expose |
||||
|
private String title; |
||||
|
@SerializedName("body") |
||||
|
@Expose |
||||
|
private String body; |
||||
|
@SerializedName("createDate") |
||||
|
@Expose |
||||
|
private String createDate; |
||||
|
@SerializedName("imageURL") |
||||
|
@Expose |
||||
|
private String imageURL; |
||||
|
|
||||
|
public String getTitle() { |
||||
|
return title; |
||||
|
} |
||||
|
|
||||
|
public void setTitle(String title) { |
||||
|
this.title = title; |
||||
|
} |
||||
|
|
||||
|
public String getBody() { |
||||
|
return body; |
||||
|
} |
||||
|
|
||||
|
public void setBody(String body) { |
||||
|
this.body = body; |
||||
|
} |
||||
|
|
||||
|
public String getCreateDate() { |
||||
|
return createDate; |
||||
|
} |
||||
|
|
||||
|
public void setCreateDate(String createDate) { |
||||
|
this.createDate = createDate; |
||||
|
} |
||||
|
|
||||
|
public String getImageURL() { |
||||
|
return imageURL; |
||||
|
} |
||||
|
|
||||
|
public void setImageURL(String imageURL) { |
||||
|
this.imageURL = imageURL; |
||||
|
} |
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
package com.remit.jmecustomer.features.mynotifications.presenter; |
||||
|
|
||||
|
|
||||
|
|
||||
|
import com.remit.jmecustomer.base.PrivilegedGatewayInterface; |
||||
|
import com.remit.jmecustomer.features.mynotifications.model.MyNotificationDTO; |
||||
|
import com.remit.jmecustomer.features.mynotifications.model.MyNotificationDetailDTO; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
import io.reactivex.Observable; |
||||
|
import okhttp3.ResponseBody; |
||||
|
|
||||
|
public interface MyNotificationGatewayInterface extends PrivilegedGatewayInterface { |
||||
|
|
||||
|
Observable<ResponseBody> getNoticeList(String auth, String customerID); |
||||
|
|
||||
|
Observable<ResponseBody> getNoticeDetail(String auth, String noticeId); |
||||
|
|
||||
|
Observable<ResponseBody> setNoticeStatus(String auth,String tranId,String noticeStat); |
||||
|
|
||||
|
List<MyNotificationDTO> mockNoticeList(); |
||||
|
|
||||
|
MyNotificationDetailDTO mockNoticeDetail(); |
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,41 @@ |
|||||
|
package com.remit.jmecustomer.features.mynotifications.presenter; |
||||
|
|
||||
|
import androidx.lifecycle.LiveData; |
||||
|
|
||||
|
import com.remit.jmecustomer.base.BaseContractInterface; |
||||
|
import com.remit.jmecustomer.base.BasePresenterInterface; |
||||
|
import com.remit.jmecustomer.features.mynotifications.model.MyNotificationDTO; |
||||
|
import com.remit.jmecustomer.features.mynotifications.model.MyNotificationDetailDTO; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface MyNotificationPresenterInterface extends BasePresenterInterface { |
||||
|
|
||||
|
void fetchNoticeListLiveData(); |
||||
|
|
||||
|
void fetchNoticeDetail(MyNotificationDTO selectedNotice); |
||||
|
|
||||
|
LiveData<List<MyNotificationDTO>> getNoticeListLiveData(); |
||||
|
|
||||
|
LiveData<MyNotificationDetailDTO> getNoticeDetailLiveData(); |
||||
|
|
||||
|
void changeNoticeStat(); |
||||
|
|
||||
|
MyNotificationDTO getSelectedNotice(); |
||||
|
|
||||
|
void setSelectedNotice(MyNotificationDTO noticeState); |
||||
|
|
||||
|
interface NoticeViewContractInterface extends BaseContractInterface { |
||||
|
|
||||
|
|
||||
|
void lazyInitViews(); |
||||
|
|
||||
|
void showDetailScreen(); |
||||
|
|
||||
|
NoticeListContractInterface getNoticeListContract(); |
||||
|
|
||||
|
interface NoticeListContractInterface extends BaseContractInterface { |
||||
|
void showTranSendComplete(); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,233 @@ |
|||||
|
package com.remit.jmecustomer.features.mynotifications.presenter; |
||||
|
|
||||
|
import androidx.lifecycle.LiveData; |
||||
|
import androidx.lifecycle.MutableLiveData; |
||||
|
|
||||
|
import com.google.gson.reflect.TypeToken; |
||||
|
import com.remit.jmecustomer.R; |
||||
|
import com.remit.jmecustomer.base.BaseViewModel; |
||||
|
import com.remit.jmecustomer.common.customwidgets.CustomAlertDialog; |
||||
|
import com.remit.jmecustomer.features.mynotifications.model.MyNotificationDTO; |
||||
|
import com.remit.jmecustomer.features.mynotifications.model.MyNotificationDetailDTO; |
||||
|
import com.remit.jmecustomer.features.sendmoney.model.SendMoneyTransactionCompleteV2ResponseBody; |
||||
|
import com.remit.jmecustomer.utils.Constants; |
||||
|
import com.remit.jmecustomer.utils.https.GenericApiObserverResponseV2; |
||||
|
import com.remit.jmecustomer.utils.https.GenericResponseDataModel; |
||||
|
|
||||
|
import java.lang.reflect.Type; |
||||
|
import java.util.Collections; |
||||
|
import java.util.List; |
||||
|
|
||||
|
import io.reactivex.android.schedulers.AndroidSchedulers; |
||||
|
import io.reactivex.disposables.CompositeDisposable; |
||||
|
import io.reactivex.schedulers.Schedulers; |
||||
|
|
||||
|
public class MyNotificationViewModel extends BaseViewModel implements MyNotificationPresenterInterface { |
||||
|
|
||||
|
|
||||
|
private final NoticeViewContractInterface view; |
||||
|
private final MyNotificationGatewayInterface gateway; |
||||
|
private final CompositeDisposable compositeDisposable; |
||||
|
|
||||
|
MutableLiveData<List<MyNotificationDTO>> noticeListLiveData; |
||||
|
MutableLiveData<MyNotificationDetailDTO> noticeDetailLiveData; |
||||
|
private MyNotificationDTO selectedNotice; |
||||
|
|
||||
|
public MyNotificationViewModel(NoticeViewContractInterface view, MyNotificationGatewayInterface gatewayInterface) { |
||||
|
this.view = view; |
||||
|
this.gateway = gatewayInterface; |
||||
|
noticeListLiveData = new MutableLiveData<>(); |
||||
|
noticeDetailLiveData = new MutableLiveData<>(); |
||||
|
this.compositeDisposable = new CompositeDisposable(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onViewReady() { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onViewNotReady() { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void fetchNoticeListLiveData() { |
||||
|
this.compositeDisposable.add( |
||||
|
this.gateway.getNoticeList(gateway.getAuth(), gateway.getUserIDNumber()) |
||||
|
.doOnSubscribe(subs -> view.showProgressBar(true, "")) |
||||
|
.subscribeOn(Schedulers.io()) |
||||
|
.observeOn(AndroidSchedulers.mainThread()) |
||||
|
.doFinally(() -> view.showProgressBar(false, "")) |
||||
|
.subscribeWith(new NoticeListObserver()) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void fetchNoticeDetail(MyNotificationDTO selectedNotice) { |
||||
|
this.compositeDisposable.add( |
||||
|
this.gateway.getNoticeDetail(gateway.getAuth(), selectedNotice.getRowId()) |
||||
|
.doOnSubscribe(subs -> view.showProgressBar(true, "")) |
||||
|
.subscribeOn(Schedulers.io()) |
||||
|
.observeOn(AndroidSchedulers.mainThread()) |
||||
|
.doFinally(() -> view.showProgressBar(false, "")) |
||||
|
.subscribeWith(new NoticeDetailObserver()) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public LiveData<List<MyNotificationDTO>> getNoticeListLiveData() { |
||||
|
return noticeListLiveData; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public LiveData<MyNotificationDetailDTO> getNoticeDetailLiveData() { |
||||
|
return noticeDetailLiveData; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void changeNoticeStat() { |
||||
|
this.compositeDisposable.add( |
||||
|
this.gateway.setNoticeStatus(gateway.getAuth(), selectedNotice.getExtra(), "Y") |
||||
|
.doOnSubscribe(subs -> view.showProgressBar(true, "")) |
||||
|
.subscribeOn(Schedulers.io()) |
||||
|
.observeOn(AndroidSchedulers.mainThread()) |
||||
|
.doFinally(() -> view.showProgressBar(false, "")) |
||||
|
.subscribeWith(new NoticeStatUpdateObserver()) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public MyNotificationDTO getSelectedNotice() { |
||||
|
return selectedNotice; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void setSelectedNotice(MyNotificationDTO noticeState) { |
||||
|
this.selectedNotice = noticeState; |
||||
|
} |
||||
|
|
||||
|
private void sortNoticeList(List<MyNotificationDTO> data) { |
||||
|
// DateFormat df = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss a"); |
||||
|
// Collections.sort(data, (o1, o2) -> { |
||||
|
// try { |
||||
|
// return df.parse(o1.getCreateDate()).compareTo(df.parse(o2.getCreateDate())); |
||||
|
// } catch (Exception pe) { |
||||
|
// Collections.reverse(data); |
||||
|
// } |
||||
|
// return 0; |
||||
|
// }); |
||||
|
if (data != null) |
||||
|
Collections.reverse(data); |
||||
|
noticeListLiveData.setValue(data); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public class NoticeListObserver extends GenericApiObserverResponseV2<List<MyNotificationDTO>> { |
||||
|
|
||||
|
@Override |
||||
|
protected Type getDataType() { |
||||
|
return TypeToken.getParameterized(List.class, MyNotificationDTO.class).getType(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void onSuccess(GenericResponseDataModel<List<MyNotificationDTO>> t) { |
||||
|
if (t.getErrorCode().equalsIgnoreCase(Constants.SUCCESS_CODE_V2)) { |
||||
|
if (t.getData() != null && t.getData().size() > 0) { |
||||
|
view.lazyInitViews(); |
||||
|
sortNoticeList(t.getData()); |
||||
|
} else |
||||
|
view.showPopUpMessage(view.getContext().getResources().getString(R.string.donot_have_notification_text), CustomAlertDialog.AlertType.FAILED, alertType -> view.exitView()); |
||||
|
|
||||
|
} else { |
||||
|
view.showPopUpMessage(t.getMsg(), CustomAlertDialog.AlertType.FAILED, alertType -> view.exitView()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onFailed(String message) { |
||||
|
// view.lazyInitViews(); |
||||
|
// sortNoticeList(gateway.mockNoticeList()); |
||||
|
view.showPopUpMessage(message, CustomAlertDialog.AlertType.FAILED, alertType -> view.exitView()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void onConnectionNotEstablished(String message) { |
||||
|
view.showPopUpMessage(message, CustomAlertDialog.AlertType.FAILED, alertType -> view.exitView()); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void unauthorizedAccess(String message) { |
||||
|
view.showPopUpMessage(message, CustomAlertDialog.AlertType.FAILED, alertType -> view.logout()); |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class NoticeDetailObserver extends GenericApiObserverResponseV2<MyNotificationDetailDTO> { |
||||
|
@Override |
||||
|
protected Type getDataType() { |
||||
|
return TypeToken.getParameterized(MyNotificationDetailDTO.class).getType(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void onSuccess(GenericResponseDataModel<MyNotificationDetailDTO> t) { |
||||
|
if (t.getErrorCode().equalsIgnoreCase(Constants.SUCCESS_CODE_V2)) { |
||||
|
noticeDetailLiveData.setValue(t.getData()); |
||||
|
view.showDetailScreen(); |
||||
|
} else { |
||||
|
view.showPopUpMessage(t.getMsg(), CustomAlertDialog.AlertType.FAILED, null); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onFailed(String message) { |
||||
|
// noticeDetailLiveData.setValue(gateway.mockNoticeDetail()); |
||||
|
// view.showDetailScreen(); |
||||
|
view.showPopUpMessage(message, CustomAlertDialog.AlertType.FAILED, null); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void onConnectionNotEstablished(String message) { |
||||
|
view.showPopUpMessage(message, CustomAlertDialog.AlertType.FAILED, null); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void unauthorizedAccess(String message) { |
||||
|
gateway.clearAllUserData(); |
||||
|
view.showPopUpMessage(message, CustomAlertDialog.AlertType.FAILED, alertType -> view.logout()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class NoticeStatUpdateObserver extends GenericApiObserverResponseV2<SendMoneyTransactionCompleteV2ResponseBody> { |
||||
|
@Override |
||||
|
protected Type getDataType() { |
||||
|
return TypeToken.getParameterized(MyNotificationDetailDTO.class).getType(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void onSuccess(GenericResponseDataModel<SendMoneyTransactionCompleteV2ResponseBody> t) { |
||||
|
if (t.getErrorCode().equalsIgnoreCase(Constants.SUCCESS_CODE_V2)) { |
||||
|
view.getNoticeListContract().showTranSendComplete(); |
||||
|
} else { |
||||
|
view.showPopUpMessage(t.getMsg(), CustomAlertDialog.AlertType.FAILED, null); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onFailed(String message) { |
||||
|
view.showPopUpMessage(message, CustomAlertDialog.AlertType.FAILED, null); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void onConnectionNotEstablished(String message) { |
||||
|
view.showPopUpMessage(message, CustomAlertDialog.AlertType.FAILED, null); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void unauthorizedAccess(String message) { |
||||
|
gateway.clearAllUserData(); |
||||
|
view.showPopUpMessage(message, CustomAlertDialog.AlertType.FAILED, alertType -> view.logout()); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,127 @@ |
|||||
|
package com.remit.jmecustomer.features.mynotifications.view; |
||||
|
|
||||
|
import android.content.Intent; |
||||
|
import android.os.Bundle; |
||||
|
import android.widget.TextView; |
||||
|
|
||||
|
import androidx.fragment.app.Fragment; |
||||
|
import androidx.lifecycle.ViewModelProvider; |
||||
|
import androidx.viewpager.widget.ViewPager; |
||||
|
|
||||
|
import com.remit.jmecustomer.R; |
||||
|
import com.remit.jmecustomer.base.BaseActivity; |
||||
|
import com.remit.jmecustomer.common.customwidgets.GenericViewPagerAdapter; |
||||
|
import com.remit.jmecustomer.features.home.view.HomeActivityV2; |
||||
|
import com.remit.jmecustomer.features.mynotifications.MyNotificationViewModelFactory; |
||||
|
import com.remit.jmecustomer.features.mynotifications.presenter.MyNotificationPresenterInterface; |
||||
|
import com.remit.jmecustomer.features.mynotifications.presenter.MyNotificationViewModel; |
||||
|
|
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
import butterknife.BindView; |
||||
|
import butterknife.ButterKnife; |
||||
|
import butterknife.OnClick; |
||||
|
|
||||
|
public class MyNotificationActivity extends BaseActivity implements MyNotificationPresenterInterface.NoticeViewContractInterface, ViewPager.OnPageChangeListener { |
||||
|
|
||||
|
@BindView(R.id.noticeViewPager) |
||||
|
ViewPager noticeViewPager; |
||||
|
|
||||
|
|
||||
|
@BindView(R.id.toolbar_title) |
||||
|
TextView toolbar_title; |
||||
|
|
||||
|
private GenericViewPagerAdapter noticeViewPagerAdapter; |
||||
|
private MyNotificationListingFragment noticeListingFragment; |
||||
|
private MyNotificationFragment noticeDetailFragment; |
||||
|
|
||||
|
|
||||
|
@Override |
||||
|
protected void onCreate(Bundle savedInstanceState) { |
||||
|
super.onCreate(savedInstanceState); |
||||
|
setContentView(R.layout.activity_notice); |
||||
|
ButterKnife.bind(this); |
||||
|
initialize(); |
||||
|
} |
||||
|
|
||||
|
private void initialize() { |
||||
|
toolbar_title.setText(getString(R.string.my_notification_text)); |
||||
|
MyNotificationViewModelFactory noticeViewModelFactory = new MyNotificationViewModelFactory(this); |
||||
|
MyNotificationViewModel viewModel = new ViewModelProvider(this, noticeViewModelFactory).get(MyNotificationViewModel.class); |
||||
|
viewModel.fetchNoticeListLiveData(); |
||||
|
// setupViewPager(); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
private void setupViewPager() { |
||||
|
|
||||
|
List<Fragment> fragments = new ArrayList<>(); |
||||
|
|
||||
|
noticeListingFragment = new MyNotificationListingFragment(); |
||||
|
noticeDetailFragment = new MyNotificationFragment(); |
||||
|
|
||||
|
|
||||
|
fragments.add(noticeListingFragment); |
||||
|
fragments.add(noticeDetailFragment); |
||||
|
|
||||
|
noticeViewPagerAdapter = new GenericViewPagerAdapter(getSupportFragmentManager(),fragments); |
||||
|
|
||||
|
|
||||
|
noticeViewPager.setOffscreenPageLimit(2); |
||||
|
|
||||
|
noticeViewPager.addOnPageChangeListener(this); |
||||
|
|
||||
|
noticeViewPager.setAdapter(noticeViewPagerAdapter); |
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
@OnClick(R.id.iv_back) |
||||
|
public void backButtonPressed() { |
||||
|
this.onBackPressed(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void lazyInitViews() { |
||||
|
setupViewPager(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void showDetailScreen() { |
||||
|
noticeViewPager.setCurrentItem(1); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public NoticeListContractInterface getNoticeListContract() { |
||||
|
return noticeListingFragment; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onPageSelected(int position) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onPageScrollStateChanged(int state) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onBackPressed() { |
||||
|
if (noticeViewPager.getCurrentItem() == 0) { |
||||
|
Intent redirectIntent = new Intent(this, HomeActivityV2.class); |
||||
|
redirectIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); |
||||
|
redirectIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); |
||||
|
startActivity(redirectIntent); |
||||
|
finish(); |
||||
|
} else |
||||
|
noticeViewPager.setCurrentItem(noticeViewPager.getCurrentItem() - 1); |
||||
|
} |
||||
|
} |
@ -0,0 +1,107 @@ |
|||||
|
package com.remit.jmecustomer.features.mynotifications.view; |
||||
|
|
||||
|
import android.graphics.Bitmap; |
||||
|
import android.graphics.drawable.Drawable; |
||||
|
import android.os.Bundle; |
||||
|
import android.view.LayoutInflater; |
||||
|
import android.view.View; |
||||
|
import android.view.ViewGroup; |
||||
|
import android.widget.ImageView; |
||||
|
import android.widget.ProgressBar; |
||||
|
import android.widget.TextView; |
||||
|
|
||||
|
import androidx.annotation.NonNull; |
||||
|
import androidx.annotation.Nullable; |
||||
|
import androidx.lifecycle.ViewModelProvider; |
||||
|
|
||||
|
import com.bumptech.glide.Glide; |
||||
|
import com.bumptech.glide.request.target.CustomTarget; |
||||
|
import com.bumptech.glide.request.transition.Transition; |
||||
|
import com.remit.jmecustomer.R; |
||||
|
import com.remit.jmecustomer.base.BaseFragment; |
||||
|
import com.remit.jmecustomer.features.mynotifications.model.MyNotificationDetailDTO; |
||||
|
import com.remit.jmecustomer.features.mynotifications.presenter.MyNotificationViewModel; |
||||
|
|
||||
|
import butterknife.BindView; |
||||
|
import butterknife.ButterKnife; |
||||
|
|
||||
|
public class MyNotificationFragment extends BaseFragment { |
||||
|
|
||||
|
@BindView(R.id.tv_notification_date) |
||||
|
TextView noticeDate; |
||||
|
|
||||
|
@BindView(R.id.tv_notification_title) |
||||
|
TextView noticeTitle; |
||||
|
|
||||
|
@BindView(R.id.tv_notification_body) |
||||
|
TextView noticeBody; |
||||
|
|
||||
|
@BindView(R.id.notice_image) |
||||
|
ImageView noticeImage; |
||||
|
|
||||
|
@BindView(R.id.progressBar) |
||||
|
ProgressBar imageProgessBar; |
||||
|
|
||||
|
|
||||
|
|
||||
|
@Override |
||||
|
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { |
||||
|
return inflater.inflate(R.layout.fragment_notice_detail, container, false); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { |
||||
|
super.onViewCreated(view, savedInstanceState); |
||||
|
ButterKnife.bind(this, view); |
||||
|
init(); |
||||
|
performDefaultAction(savedInstanceState); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
private void init() { |
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
private void performDefaultAction(Bundle savedInstance) { |
||||
|
|
||||
|
MyNotificationViewModel myNotificationViewModel = new ViewModelProvider(getActivity()).get(MyNotificationViewModel.class); |
||||
|
|
||||
|
myNotificationViewModel.getNoticeDetailLiveData().observe(getViewLifecycleOwner(),this::updateNoticeDEtail); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
private void updateNoticeDEtail(MyNotificationDetailDTO noticeDetail) |
||||
|
{ |
||||
|
String date=getActivity().getResources().getString(R.string.date_text)+": "+noticeDetail.getCreateDate(); |
||||
|
noticeDate.setText(date); |
||||
|
noticeTitle.setText(noticeDetail.getTitle()); |
||||
|
noticeBody.setText(noticeDetail.getBody()); |
||||
|
if(noticeDetail.getImageURL()==null||noticeDetail.getImageURL().length()==0) |
||||
|
{ |
||||
|
imageProgessBar.setVisibility(View.GONE); |
||||
|
noticeImage.setVisibility(View.GONE); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
imageProgessBar.setVisibility(View.VISIBLE); |
||||
|
Glide.with(this) |
||||
|
.asBitmap() |
||||
|
.load(noticeDetail.getImageURL()) |
||||
|
.into(new CustomTarget<Bitmap>() { |
||||
|
@Override |
||||
|
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) { |
||||
|
// imageProgessBar.setVisibility(View.GONE); |
||||
|
// noticeImage.setImageBitmap(resource); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onLoadCleared(@Nullable Drawable placeholder) { |
||||
|
|
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,97 @@ |
|||||
|
package com.remit.jmecustomer.features.mynotifications.view; |
||||
|
|
||||
|
import android.content.Intent; |
||||
|
import android.os.Bundle; |
||||
|
import android.view.LayoutInflater; |
||||
|
import android.view.View; |
||||
|
import android.view.ViewGroup; |
||||
|
|
||||
|
import androidx.annotation.Nullable; |
||||
|
import androidx.lifecycle.ViewModelProvider; |
||||
|
import androidx.recyclerview.widget.RecyclerView; |
||||
|
|
||||
|
import com.remit.jmecustomer.R; |
||||
|
import com.remit.jmecustomer.base.BaseFragment; |
||||
|
import com.remit.jmecustomer.features.mynotifications.adapter.MyNotificationListingRVAdapter; |
||||
|
import com.remit.jmecustomer.features.mynotifications.model.MyNotificationDTO; |
||||
|
import com.remit.jmecustomer.features.mynotifications.presenter.MyNotificationPresenterInterface; |
||||
|
import com.remit.jmecustomer.features.mynotifications.presenter.MyNotificationViewModel; |
||||
|
import com.remit.jmecustomer.features.sendmoney.view.SendMoneyV2TransactionCompleteActivity; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
import butterknife.BindView; |
||||
|
import butterknife.ButterKnife; |
||||
|
|
||||
|
public class MyNotificationListingFragment extends BaseFragment implements MyNotificationListingRVAdapter.NoticeClickListener, MyNotificationPresenterInterface.NoticeViewContractInterface.NoticeListContractInterface { |
||||
|
|
||||
|
|
||||
|
@BindView(R.id.noticeRv) |
||||
|
RecyclerView noticeRv; |
||||
|
|
||||
|
MyNotificationListingRVAdapter myNotificationListingRVAdapter; |
||||
|
|
||||
|
|
||||
|
|
||||
|
@Override |
||||
|
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { |
||||
|
return inflater.inflate(R.layout.fragment_notice_listing, container, false); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { |
||||
|
super.onViewCreated(view, savedInstanceState); |
||||
|
ButterKnife.bind(this, view); |
||||
|
init(); |
||||
|
performDefaultAction(savedInstanceState); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
private void init() { |
||||
|
myNotificationListingRVAdapter = new MyNotificationListingRVAdapter(this); |
||||
|
noticeRv.setAdapter(myNotificationListingRVAdapter); |
||||
|
// noticeRv.addItemDecoration(new LineDividerItemDecoration(noticeRv.getContext(), LineDividerItemDecoration.VERTICAL_LIST)); |
||||
|
} |
||||
|
|
||||
|
private void performDefaultAction(Bundle savedInstance) { |
||||
|
|
||||
|
MyNotificationViewModel myNotificationViewModel = new ViewModelProvider(getActivity()).get(MyNotificationViewModel.class); |
||||
|
; |
||||
|
|
||||
|
myNotificationViewModel.getNoticeListLiveData().observe(getViewLifecycleOwner(), this::updateNoticeList); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
private void updateNoticeList(List<MyNotificationDTO> noticeList) { |
||||
|
myNotificationListingRVAdapter.setData(noticeList); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onNoticeClicked(MyNotificationDTO itemModel) { |
||||
|
new ViewModelProvider(getActivity()).get(MyNotificationViewModel.class).setSelectedNotice(itemModel); |
||||
|
handleNoticeClicked(itemModel); |
||||
|
} |
||||
|
|
||||
|
private void handleNoticeClicked(MyNotificationDTO itemModel) { |
||||
|
if (itemModel.getType().equals("0")) { |
||||
|
new ViewModelProvider(getActivity()).get(MyNotificationViewModel.class).fetchNoticeDetail(itemModel); |
||||
|
} else if (itemModel.getType().equals("1")) { |
||||
|
if(itemModel.getIsRead().equals("1")){ |
||||
|
showTranSendComplete(); |
||||
|
}else{ |
||||
|
new ViewModelProvider(getActivity()).get(MyNotificationViewModel.class).changeNoticeStat(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
@Override |
||||
|
public void showTranSendComplete() { |
||||
|
MyNotificationDTO selectedNotice=new ViewModelProvider(getActivity()).get(MyNotificationViewModel.class).getSelectedNotice(); |
||||
|
Intent startReceiptActivity = new Intent(getActivity(), SendMoneyV2TransactionCompleteActivity.class); |
||||
|
startReceiptActivity.putExtra(SendMoneyV2TransactionCompleteActivity.SEND_MONEY_TID_BUNDLE_KEY, selectedNotice.getExtra()); |
||||
|
startReceiptActivity.putExtra(SendMoneyV2TransactionCompleteActivity.DISPLAY_ACTIONS_BUNDLE_KEY, selectedNotice.getDisplayActions()); |
||||
|
startActivity(startReceiptActivity); |
||||
|
} |
||||
|
} |
@ -0,0 +1,13 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="match_parent" |
||||
|
android:orientation="vertical" |
||||
|
> |
||||
|
<include layout="@layout/layout_sendmoney_toolbar" /> |
||||
|
<com.remit.jmecustomer.common.customwidgets.SwipeDisabledViewPager |
||||
|
android:id="@+id/noticeViewPager" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="0dp" |
||||
|
android:layout_weight="1"/> |
||||
|
</androidx.appcompat.widget.LinearLayoutCompat> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue