diff --git a/app/src/main/java/com/eusecom/attendance/PostsFragment.java b/app/src/main/java/com/eusecom/attendance/PostsFragment.java index 4068501..1427769 100644 --- a/app/src/main/java/com/eusecom/attendance/PostsFragment.java +++ b/app/src/main/java/com/eusecom/attendance/PostsFragment.java @@ -196,7 +196,7 @@ private void loadPosts() { Query fbQuery = firebaseRef.child("fireblog"); showProgress(true); - RxFirebaseDatabase.getInstance().observeValueEvent(fbQuery).subscribe(getPostsSubscriber); + RxFirebaseDatabase.getInstance().observeValueEventDelayed(fbQuery).subscribe(getPostsSubscriber); } /** diff --git a/app/src/main/java/com/eusecom/attendance/fragment/ApproveListFragment.java b/app/src/main/java/com/eusecom/attendance/fragment/ApproveListFragment.java index e44f915..d2208b3 100644 --- a/app/src/main/java/com/eusecom/attendance/fragment/ApproveListFragment.java +++ b/app/src/main/java/com/eusecom/attendance/fragment/ApproveListFragment.java @@ -3,7 +3,6 @@ import android.app.Dialog; import android.app.ProgressDialog; import android.content.DialogInterface; -import android.content.Intent; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v7.app.AlertDialog; @@ -19,11 +18,16 @@ import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; - - import com.eusecom.attendance.Constants; import com.eusecom.attendance.FbmessClient; +import com.eusecom.attendance.PostsFragment; import com.eusecom.attendance.SettingsActivity; +import com.eusecom.attendance.animators.BaseItemAnimator; +import com.eusecom.attendance.animators.FadeInAnimator; +import com.eusecom.attendance.animators.FadeInDownAnimator; +import com.eusecom.attendance.animators.FadeInLeftAnimator; +import com.eusecom.attendance.animators.FadeInRightAnimator; +import com.eusecom.attendance.animators.FadeInUpAnimator; import com.eusecom.attendance.models.Attendance; import com.eusecom.attendance.models.MessData; import com.eusecom.attendance.models.Message; @@ -32,31 +36,36 @@ import com.eusecom.attendance.retrofit.RfEtestApi; import com.eusecom.attendance.retrofit.RfEtestService; import com.eusecom.attendance.retrofit.RfUser; -import com.eusecom.attendance.viewholder.ApproveViewHolder; -import com.firebase.ui.database.FirebaseRecyclerAdapter; +import com.eusecom.attendance.rxbus.RxBus; +import com.eusecom.attendance.rxfirebase2.database.RxFirebaseDatabase; +import com.eusecom.attendance.rxfirebase2models.BlogPostEntity; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; -import com.google.firebase.database.MutableData; import com.google.firebase.database.Query; import com.google.firebase.database.ServerValue; -import com.google.firebase.database.Transaction; import com.eusecom.attendance.R; -import com.eusecom.attendance.models.Post; import com.google.firebase.database.ValueEventListener; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; import java.util.Date; +import java.util.List; +import java.util.concurrent.TimeUnit; + import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.flowables.ConnectableFlowable; import io.reactivex.observers.DisposableObserver; import io.reactivex.schedulers.Schedulers; import rx.Observer; +import rx.Subscriber; import rx.Subscription; import static android.text.TextUtils.isEmpty; @@ -68,10 +77,6 @@ public abstract class ApproveListFragment extends Fragment { private DatabaseReference mDatabase; // [END define_database_reference] - private FirebaseRecyclerAdapter mAdapter; - private RecyclerView mRecycler; - private LinearLayoutManager mManager; - public ApproveListFragment() {} String absxy; String abskeydel=null; @@ -84,6 +89,31 @@ public ApproveListFragment() {} private Subscription subscription; + enum Type { + FadeIn(new FadeInAnimator()), + FadeInDown(new FadeInDownAnimator()), + FadeInUp(new FadeInUpAnimator()), + FadeInLeft(new FadeInLeftAnimator()), + FadeInRight(new FadeInRightAnimator()); + + private BaseItemAnimator mAnimator; + + Type(BaseItemAnimator animator) { + mAnimator = animator; + } + + public BaseItemAnimator getAnimator() { + return mAnimator; + } + } + + private ApproveRxAdapter mAdapter; + private RecyclerView mRecycler; + private LinearLayoutManager mManager; + public ApproveListFragment.GetApproveSubscriber getApproveSubscriber; + private final DatabaseReference firebaseRef = FirebaseDatabase.getInstance().getReference(); + private RxBus _rxBus; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -92,6 +122,44 @@ public void onCreate(Bundle savedInstanceState) { _githubService = RfEtestService.createGithubService(githubToken, urlx); _disposables = new CompositeDisposable(); + + _rxBus = getRxBusSingleton(); + + ConnectableFlowable tapEventEmitter = _rxBus.asFlowable().publish(); + + _disposables + .add(tapEventEmitter.subscribe(event -> { + if (event instanceof ApproveListFragment.TapEvent) { + ///_showTapText(); + } + if (event instanceof BlogPostEntity) { + //saveAbsServer(((Attendance) event).daod + " / " + ((Attendance) event).dado, ((Attendance) event)); + String keys = ((BlogPostEntity) event).getAuthor(); + + //showProgress(true); + Log.d("In FRGM shortClick", keys); + BlogPostEntity postx = new BlogPostEntity(null, null, null); + //delBlogPostRx(postx,1, keys); + + } + })); + + _disposables + .add(tapEventEmitter.publish(stream -> + stream.buffer(stream.debounce(1, TimeUnit.SECONDS))) + .observeOn(AndroidSchedulers.mainThread()).subscribe(taps -> { + ///_showTapCount(taps.size()); OK + })); + + _disposables.add(tapEventEmitter.connect()); + } + + public RxBus getRxBusSingleton() { + if (_rxBus == null) { + _rxBus = new RxBus(); + } + + return _rxBus; } @Override @@ -114,28 +182,8 @@ public View onCreateView (LayoutInflater inflater, ViewGroup container, public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - showfProgressDialog(); - - DatabaseReference connectedRef = FirebaseDatabase.getInstance().getReference(".info/connected"); - connectedRef.addValueEventListener(new ValueEventListener() { - @Override - public void onDataChange(DataSnapshot snapshot) { - boolean connected = snapshot.getValue(Boolean.class); - if (connected) { - System.out.println("connected"); - if(isrunning) { showfProgressDialog(); } - } else { - System.out.println("not connected"); - hidefProgressDialog(); - if(isrunning) { Toast.makeText(getActivity(), getResources().getString(R.string.notconnected), Toast.LENGTH_SHORT).show(); } - } - } - - @Override - public void onCancelled(DatabaseError error) { - System.err.println("Listener was cancelled"); - } - }); + mAdapter = new ApproveRxAdapter(Collections.emptyList(), _rxBus); + getApproveSubscriber = new ApproveListFragment.GetApproveSubscriber(); DatabaseReference gettimestramp = FirebaseDatabase.getInstance().getReference("gettimestamp"); gettimestramp.addValueEventListener(new ValueEventListener() { @@ -159,142 +207,39 @@ public void onCancelled(DatabaseError databaseError) { } // Set up FirebaseRecyclerAdapter with the Query Query absencesQuery = getQuery(mDatabase); - mDatabase.addListenerForSingleValueEvent(new ValueEventListener() { - @Override - public void onDataChange(DataSnapshot dataSnapshot) { - // the initial data has been loaded, hide the progress bar - hidefProgressDialog(); - } - - @Override - public void onCancelled(DatabaseError firebaseError) { - - hidefProgressDialog(); - } - }); - - - - mAdapter = new FirebaseRecyclerAdapter(Attendance.class, R.layout.item_approve, - ApproveViewHolder.class, absencesQuery) { - - @Override - protected void populateViewHolder(final ApproveViewHolder viewHolder, final Attendance model, final int position) { - - final DatabaseReference absRef = getRef(position); - - // Set click listener for the whole post view - final String absKey = absRef.getKey(); - absxy = absRef.getKey(); - - - viewHolder.itemView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - // Launch PostDetailActivity - Log.d(TAG, "onclick" + " listener"); - - //Intent intent = new Intent(getActivity(), PostDetailActivity.class); - //intent.putExtra(PostDetailActivity.EXTRA_POST_KEY, absKey); - Toast.makeText(getActivity(), "Onclick " + absKey, Toast.LENGTH_SHORT).show(); - - //startActivity(intent); - } - - - }); - - viewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - - final String datsx = model.getDatsString(); - //Log.d(TAG, "datsx " + datsx); - - gettimestramp.setValue(ServerValue.TIMESTAMP); - //Log.d(TAG, "ServerValue.TIMESTAMP " + timestampx); - - long timestampl = Long.parseLong(timestampx); - long datsl = Long.parseLong(datsx); - long rozdiel = timestampl - datsl; - //Log.d(TAG, "rozdiel " + rozdiel); - - Toast.makeText(getActivity(), "Longclick " + absKey,Toast.LENGTH_SHORT).show(); - - abskeydel = absKey; - - getDialog(abskeydel, model); - - - return true; - } + mRecycler.setAdapter(mAdapter); + mRecycler.setItemAnimator(new FadeInRightAnimator()); + mRecycler.getItemAnimator().setAddDuration(300); + mRecycler.getItemAnimator().setRemoveDuration(300); + loadAbsencesForApproving(); - }); - // Bind Abstype to ViewHolder - viewHolder.bindToApprove(model, new View.OnClickListener() { - @Override - public void onClick(View starView) { - // Need to write to both places the post is stored - DatabaseReference globalPostRef = mDatabase.child("posts").child(absRef.getKey()); - // Run two transactions - onStarClicked(globalPostRef); - - } - }); - } + }//end of onActivityCreated - }; - - mRecycler.setAdapter(mAdapter); + private void loadAbsencesForApproving() { + Query fbQuery = firebaseRef.child("fireblog"); + //showProgress(true); + RxFirebaseDatabase.getInstance().observeValueEvent(fbQuery).subscribe(getApproveSubscriber); } - // [START post_stars_transaction] - private void onStarClicked(DatabaseReference postRef) { - postRef.runTransaction(new Transaction.Handler() { - @Override - public Transaction.Result doTransaction(MutableData mutableData) { - Post p = mutableData.getValue(Post.class); - if (p == null) { - return Transaction.success(mutableData); - } + private void renderApproveList(List blogPostEntities) { + //showProgress(false); + mAdapter.setData(blogPostEntities); + //Log.d("blogPostEntities", blogPostEntities.get(0).getTitle()); + //Log.d("blogPostEntities", blogPostEntities.get(1).getTitle()); + } - if (p.stars.containsKey(getUid())) { - // Unstar the post and remove self from stars - p.starCount = p.starCount - 1; - p.stars.remove(getUid()); - } else { - // Star the post and add self to stars - p.starCount = p.starCount + 1; - p.stars.put(getUid(), true); - } - // Set value and report transaction success - mutableData.setValue(p); - return Transaction.success(mutableData); - } - - @Override - public void onComplete(DatabaseError databaseError, boolean b, - DataSnapshot dataSnapshot) { - // Transaction completed - Log.d(TAG, "postTransaction:onComplete:" + databaseError); - } - }); - } - // [END post_stars_transaction] @Override public void onDestroy() { super.onDestroy(); - if (mAdapter != null) { - mAdapter.cleanup(); - } + if (subscription != null && !subscription.isUnsubscribed()) { subscription.unsubscribe(); } @@ -309,7 +254,7 @@ public String getUid() { public abstract Query getQuery(DatabaseReference databaseReference); // [START deletefan_out] - private void approvePost(String postkey, int anodaj, Attendance model) { + private void approveAbsenceToServer(String postkey, int anodaj, Attendance model) { final String datsx = model.getDatsString(); Log.d(TAG, "datsx " + datsx); @@ -364,10 +309,10 @@ public void onNext(Pair pair) { if(contributor.saved == 1 ) { snext = getResources().getString(R.string.abs_saved) + snextx; - approveFBPost(abskeydel, contributor.anodaj, model); + approveAbsenceToFB(abskeydel, contributor.anodaj, model); }else{ snext = getResources().getString(R.string.abs_savednot); - approveFBPost(abskeydel, contributor.anodaj, model); + approveAbsenceToFB(abskeydel, contributor.anodaj, model); } @@ -403,9 +348,9 @@ private void getDialog(String postkey, Attendance model) { public void onClick(View v) { dialog.dismiss(); if(savetofiri>0){ - approvePost(abskeydel, 1, model); + approveAbsenceToServer(abskeydel, 1, model); }else{ - approveFBPost(abskeydel, 1, model); + approveAbsenceToFB(abskeydel, 1, model); } } }); @@ -416,9 +361,9 @@ public void onClick(View v) { public void onClick(View v) { dialog.dismiss(); if(savetofiri>0){ - approvePost(abskeydel, 0, model); + approveAbsenceToServer(abskeydel, 0, model); }else{ - approveFBPost(abskeydel, 0, model); + approveAbsenceToFB(abskeydel, 0, model); } @@ -428,7 +373,7 @@ public void onClick(View v) { }//end getdialog - private void approveFBPost(String postkey, int anodaj, Attendance model) { + private void approveAbsenceToFB(String postkey, int anodaj, Attendance model) { //set appr at firebase child String apprx="1"; @@ -499,19 +444,6 @@ public void hidefProgressDialog() { } - - @Override - public void onResume() { - super.onResume(); - isrunning=true; - } - - @Override - public void onPause() { - super.onPause(); - isrunning=false; - } - public class FirebaseRxApproveMessaging { String to, title, body; @@ -595,4 +527,38 @@ public void onNext(Message message) { }//end of FirebaseRxApproveMessaging + + /** + * Subscriber for {@link //RxFirebaseDatabase} query + */ + private final class GetApproveSubscriber extends Subscriber { + @Override public void onCompleted() { + //showProgress(false); + //getPostsSubscriber.unsubscribe(); + } + + @Override public void onError(Throwable e) { + //showProgress(false); + //showError(e.getMessage()); + //getPostsSubscriber.unsubscribe(); + } + + @SuppressWarnings("unchecked") @Override public void onNext(DataSnapshot dataSnapshot) { + List blogPostEntities = new ArrayList<>(); + for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) { + String keys = childDataSnapshot.getKey(); + Log.d("keys ", keys); + BlogPostEntity resultx = childDataSnapshot.getValue(BlogPostEntity.class); + resultx.setAuthor(keys); + blogPostEntities.add(resultx); + } + renderApproveList(blogPostEntities); + + } + }//end of GetPostsSubscriber + + public static class TapEvent {} + + + } diff --git a/app/src/main/java/com/eusecom/attendance/fragment/ApproveRxAdapter.java b/app/src/main/java/com/eusecom/attendance/fragment/ApproveRxAdapter.java new file mode 100644 index 0000000..5dd1682 --- /dev/null +++ b/app/src/main/java/com/eusecom/attendance/fragment/ApproveRxAdapter.java @@ -0,0 +1,105 @@ +package com.eusecom.attendance.fragment; + +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.eusecom.attendance.BlogPostViewHolder; +import com.eusecom.attendance.R; +import com.eusecom.attendance.rxbus.RxBus; +import com.eusecom.attendance.rxfirebase2models.BlogPostEntity; +import com.eusecom.attendance.fragment.ApproveRxViewHolder; + +import java.util.List; + +/** + * The {@link RecyclerView.Adapter} with a {@link List} of {@link BlogPostEntity} + */ +class ApproveRxAdapter extends RecyclerView.Adapter { + + private List mBlogPostEntities; + private RxBus _rxBus; + + public ApproveRxAdapter(List blogPostEntities, RxBus bus) { + mBlogPostEntities = blogPostEntities; + _rxBus = bus; + } + + @Override public ApproveRxViewHolder onCreateViewHolder(ViewGroup viewGroup, int position) { + //View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_rxfirebase_post, viewGroup, false); + View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_approve, viewGroup, false); + return new ApproveRxViewHolder(view); + } + + @Override public void onBindViewHolder(ApproveRxViewHolder holder, int position) { + BlogPostEntity blogPostEntity = mBlogPostEntities.get(position); + holder.bindModel(blogPostEntity); + + holder.setClickListener(new ApproveRxViewHolder.ClickListener() { + public void onClick(View v, int pos, boolean isLongClick) { + + String keys = blogPostEntity.getAuthor(); + if (isLongClick) { + + Log.d("longClick", pos + " " + keys); + + + } else { + + Log.d("shortClick", pos + " " + keys); + remove(position); + if (_rxBus.hasObservers()) { + _rxBus.send(blogPostEntity); + _rxBus.send(new ApproveListFragment.TapEvent()); + } + + } + } + }); + + } + + @Override public int getItemCount() { + Log.d("getItemCount", mBlogPostEntities.size() + ""); + return mBlogPostEntities.size(); + } + + + public void remove(int position) { + mBlogPostEntities.remove(position); + notifyItemRemoved(position); + } + + + + public void add(BlogPostEntity addmodel, int position) { + mBlogPostEntities.add(position, addmodel); + notifyItemInserted(position); + } + + /** + * Sets the data for adapter + * + * @param blogPost a {@link List} of {@link BlogPostEntity} + */ + public void setData(List blogPost) { + this.validateData(blogPost); + mBlogPostEntities = blogPost; + //Log.d("AdapterSetData", mBlogPostEntities.get(0).getTitle()); + //Log.d("AdapterSetData", mBlogPostEntities.get(1).getTitle()); + this.notifyDataSetChanged(); + } + + /** + * Validates the data + * + * @param blogPostEntities a {@link List} of {@link BlogPostEntity} + */ + public void validateData(List blogPostEntities) { + if (blogPostEntities == null) { + throw new IllegalArgumentException("The list cannot be null"); + } + } +} diff --git a/app/src/main/java/com/eusecom/attendance/fragment/ApproveRxViewHolder.java b/app/src/main/java/com/eusecom/attendance/fragment/ApproveRxViewHolder.java new file mode 100644 index 0000000..ce5d2f2 --- /dev/null +++ b/app/src/main/java/com/eusecom/attendance/fragment/ApproveRxViewHolder.java @@ -0,0 +1,75 @@ +package com.eusecom.attendance.fragment; + +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.TextView; + +import com.eusecom.attendance.R; +import com.eusecom.attendance.rxfirebase2models.BlogPostEntity; + +/** + * The view holder for an item + */ +public class ApproveRxViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { + + public TextView postsTitle; + public TextView postsAuthor; + private ClickListener clickListener; + + + public ApproveRxViewHolder(View itemView) { + super(itemView); + //postsTitle = (TextView) itemView.findViewById(R.id.postsTitle); + //postsAuthor = (TextView) itemView.findViewById(R.id.postsAuthor); + postsTitle = (TextView) itemView.findViewById(R.id.absence_name); + postsAuthor = (TextView) itemView.findViewById(R.id.datefrom); + + itemView.setOnClickListener(this); + itemView.setOnLongClickListener(this); + } + + public void bindModel(BlogPostEntity entity) { + if (entity == null) { + throw new IllegalArgumentException("Entity cannot be null"); + } + postsTitle.setText(entity.getTitle()); + postsAuthor.setText(entity.getAuthor()); + } + + /* Interface for handling clicks - both normal and long ones. */ + public interface ClickListener { + + /** + * Called when the view is clicked. + * + * @param v view that is clicked + * @param position of the clicked item + * @param isLongClick true if long click, false otherwise + */ + public void onClick(View v, int position, boolean isLongClick); + + } + + /* Setter for listener. */ + public void setClickListener(ClickListener clickListener) { + this.clickListener = clickListener; + } + + @Override + public void onClick(View v) { + + // If not long clicked, pass last variable as false. + clickListener.onClick(v, getPosition(), false); + } + + @Override + public boolean onLongClick(View v) { + + // If long clicked, passed last variable as true. + clickListener.onClick(v, getPosition(), true); + return true; + } + + + +} diff --git a/app/src/main/java/com/eusecom/attendance/fragment/MyApproveFragment.java b/app/src/main/java/com/eusecom/attendance/fragment/MyApproveFragment.java index 04eedd5..4599976 100644 --- a/app/src/main/java/com/eusecom/attendance/fragment/MyApproveFragment.java +++ b/app/src/main/java/com/eusecom/attendance/fragment/MyApproveFragment.java @@ -7,8 +7,6 @@ public class MyApproveFragment extends ApproveListFragment { - private DatabaseReference mDatabase; - public MyApproveFragment() {} @Override diff --git a/app/src/main/java/com/eusecom/attendance/rxfirebase2/database/RxFirebaseDatabase.java b/app/src/main/java/com/eusecom/attendance/rxfirebase2/database/RxFirebaseDatabase.java index febaed7..8ef4d38 100644 --- a/app/src/main/java/com/eusecom/attendance/rxfirebase2/database/RxFirebaseDatabase.java +++ b/app/src/main/java/com/eusecom/attendance/rxfirebase2/database/RxFirebaseDatabase.java @@ -170,13 +170,42 @@ public Observable observeValueEvent(final Query firebaseRef) { } })); } - }).delay(500, TimeUnit.MILLISECONDS).observeOn(AndroidSchedulers.mainThread()).compose(this.applyScheduler()); + }).compose(this.applyScheduler()); } - //}).delay(300, TimeUnit.MILLISECONDS).observeOn(Schedulers.newThread()).compose(this.applyScheduler()); - //do not work }).delay(300, TimeUnit.MILLISECONDS).compose(this.applyScheduler()); - //work subscription is delayed, onNext is not delayed }).delaySubscription(10, TimeUnit.SECONDS).compose(this.applyScheduler()); + /** + * This methods observes a firebase query and returns back delayed + * Observable of the {@link DataSnapshot} + * when the firebase client uses a {@link ValueEventListener} + * + * @param firebaseRef {@link Query} this is reference of a Firebase Query + * @return an {@link rx.Observable} of datasnapshot to use + */ + public Observable observeValueEventDelayed(final Query firebaseRef) { + return Observable.create(new Observable.OnSubscribe() { + @Override public void call(final Subscriber subscriber) { + final ValueEventListener listener = + firebaseRef.addValueEventListener(new ValueEventListener() { + @Override public void onDataChange(DataSnapshot dataSnapshot) { + subscriber.onNext(dataSnapshot); + } + + @Override public void onCancelled(DatabaseError error) { + FirebaseDatabaseErrorFactory.buildError(subscriber, error); + } + }); + + // When the subscription is cancelled, remove the listener + subscriber.add(Subscriptions.create(new Action0() { + @Override public void call() { + firebaseRef.removeEventListener(listener); + } + })); + } + }).delay(500, TimeUnit.MILLISECONDS).observeOn(AndroidSchedulers.mainThread()).compose(this.applyScheduler()); + } + //work subscription is delayed, onNext is not delayed }).delaySubscription(10, TimeUnit.SECONDS).compose(this.applyScheduler()); /** * This methods observes a firebase query and returns back ONCE