MyScheduleFragment.java 7.16 KB
package com.styleteq.app.fragments;

import android.app.Activity;
import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.CompoundButton;
import android.widget.RelativeLayout;
import android.widget.Switch;
import android.widget.Toast;

import com.styleteq.app.R;
import com.styleteq.app.adapters.SchedulesAdapter;
import com.styleteq.app.api.STCallback;
import com.styleteq.app.api.STRequest;
import com.styleteq.app.api.ServiceGenerator;
import com.styleteq.app.errors.ErrorBag;
import com.styleteq.app.errors.ErrorsSerializer;
import com.styleteq.app.models.InfiniteScrollable;
import com.styleteq.app.models.PaginatedResult;
import com.styleteq.app.models.Schedule;
import com.styleteq.app.services.ScheduleService;
import com.styleteq.app.ui.DividerItemDecorator;
import com.styleteq.app.ui.InfiniteScrollView;
import com.styleteq.app.ui.LoadingScreen;
import com.styleteq.app.ui.NoEntityPlaceholder;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

import butterknife.ButterKnife;
import retrofit2.Call;
import retrofit2.Response;

/**
 * A simple {@link Fragment} subclass.
 * create an instance of this fragment.
 */
public abstract class MyScheduleFragment extends Fragment implements InfiniteScrollable {

    ScheduleService scheduleService;
    boolean qWithPast;

    protected ViewGroup container;
    protected Runnable runnable;
    protected PaginatedResult currentResult;

    private RelativeLayout fragmentWrapper;
    private NoEntityPlaceholder placeholder;
    private LoadingScreen loadingScreen;
    private boolean loading;
    private boolean resetList;

    public MyScheduleFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        this.container = container;
        return inflater.inflate(R.layout.fragment_my_schedule_list, container, false);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        ButterKnife.bind(Objects.requireNonNull(getFragmentActivity()));
        preInit();
        init();
        scheduleService = ServiceGenerator.createService(ScheduleService.class);
        addListeners();
        qWithPast = defaultSwitchState();
    }

    @Override
    public void onResume() {
        super.onResume();
        this.loadingScreen = new LoadingScreen(container);
        placeholder.setTarget(fragmentWrapper);
        load(0);
    }

    @Override
    public void onStop() {
        super.onStop();
        getSchedulesAdapter().clearAll();
    }

    @Override
    public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
        super.onViewStateRestored(savedInstanceState);
        resetList = true;
    }

    private void init() {
        View v = getMainView();
        RecyclerView recyclerView = v.findViewById(R.id.schedule_list_recycler);
        InfiniteScrollView scrollView = v.findViewById(R.id.inf_scroll_view);
        fragmentWrapper = v.findViewById(R.id.schedule_list);
        placeholder = v.findViewById(R.id.placeholder);

        scrollView.setScrollable(this);

        placeholder.set(Objects.requireNonNull(getActivity()), R.string.schedule_no_title, R.string.schedule_no_sub);

        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        recyclerView.setAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_in));
        recyclerView.setAdapter(getSchedulesAdapter());
        recyclerView.setNestedScrollingEnabled(false);
        recyclerView.addItemDecoration(new DividerItemDecorator(Objects.requireNonNull(getActivity()), DividerItemDecorator.VERTICAL_LIST));
    }

    protected void addListeners() {
        if (null != getSwitch()) {
            getSwitch().setChecked(defaultSwitchState());
            getSwitch().setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    qWithPast = isChecked;
                    resetList = true;
                    load(0);
                }
            });
        }
    }

    protected void load(int page) {
        this.loadingScreen.show(true);
        this.loading = true;
        new STRequest<>(getQuery(page), new STCallback<PaginatedResult>() {
            @Override
            public void onCustomResponse(Call<PaginatedResult> call, Response<PaginatedResult> response) {
                if (response.isSuccessful()) {
                    currentResult = response.body();
                    if (null != currentResult && !currentResult.schedules.isEmpty()) {
                        getResults(currentResult.schedules);
                    } else {
                        getResults(Collections.emptyList());
                    }
                } else {
                    ErrorBag b = ErrorsSerializer.parseResourceErrors(response);
                    if (b != null)
                        Toast.makeText(getActivity(), b.concatenateErrors(), Toast.LENGTH_SHORT).show();
                }
                checkList();
                endLoading();
            }

            @Override
            public void onFailure(Call<PaginatedResult> call, Throwable t) {
                endLoading();
                placeholder.showError(t.getMessage());
            }
        }).execute();
    }

    private void checkList() {
        if (getSchedulesAdapter().getItemCount() > 0) {
            placeholder.show(false);
        } else {
            getSchedulesAdapter().notifyDataSetChanged();
            placeholder.show(true);
        }
    }

    private void getResults(List<Schedule> schedules) {
        if (resetList) {
            getSchedulesAdapter().clearAll();
            resetList = false;
        }
        getSchedulesAdapter().addAll(schedules);
    }

    private void endLoading() {
        this.loading = false;
        this.loadingScreen.show(false);
    }

    @Override
    public boolean canLoad() {
        return !this.loading && (null != currentResult && currentResult.hasNext());
    }

    @Override
    public Runnable loadMoreResults() {
        if (runnable == null)
            runnable = new Runnable() {
                @Override
                public void run() {
                    load(currentResult.nextPage());
                }
            };
        return runnable;
    }

    protected boolean defaultSwitchState() {
        return false;
    }

    protected Switch getSwitch() {
        return null;
    }

    protected abstract void preInit();

    protected abstract Call<PaginatedResult> getQuery(int page);

    protected abstract SchedulesAdapter getSchedulesAdapter();

    protected abstract View getMainView();

    protected abstract Activity getFragmentActivity();

    protected abstract String getSource();
}