com.cryart.sabbathschool.viewmodel.SSReadingViewModel.java Source code

Java tutorial

Introduction

Here is the source code for com.cryart.sabbathschool.viewmodel.SSReadingViewModel.java

Source

/*
 * Copyright (c) 2016 Adventech <info@adventech.io>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.cryart.sabbathschool.viewmodel;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.databinding.ObservableInt;
import android.os.Build;
import android.preference.PreferenceManager;
import android.text.InputType;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.widget.Toast;

import com.afollestad.materialdialogs.MaterialDialog;
import com.cryart.sabbathschool.R;
import com.cryart.sabbathschool.databinding.SsReadingActivityBinding;
import com.cryart.sabbathschool.misc.SSConstants;
import com.cryart.sabbathschool.misc.SSHelper;
import com.cryart.sabbathschool.model.SSComment;
import com.cryart.sabbathschool.model.SSContextMenu;
import com.cryart.sabbathschool.model.SSDay;
import com.cryart.sabbathschool.model.SSLessonInfo;
import com.cryart.sabbathschool.model.SSRead;
import com.cryart.sabbathschool.model.SSReadComments;
import com.cryart.sabbathschool.model.SSReadHighlights;
import com.cryart.sabbathschool.model.SSReadingDisplayOptions;
import com.cryart.sabbathschool.model.SSSuggestion;
import com.cryart.sabbathschool.view.SSBibleVersesActivity;
import com.cryart.sabbathschool.view.SSReadingActivity;
import com.cryart.sabbathschool.view.SSReadingDisplayOptionsView;
import com.cryart.sabbathschool.view.SSReadingView;
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.ValueEventListener;

import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;

import java.util.ArrayList;

import static com.facebook.FacebookSdk.getApplicationContext;

public class SSReadingViewModel
        implements SSViewModel, SSReadingView.ContextMenuCallback, SSReadingView.HighlightsCommentsCallback {
    private static final String TAG = SSReadingViewModel.class.getSimpleName();

    private Context context;
    private String ssLessonIndex;
    private DataListener dataListener;
    private FirebaseAuth ssFirebaseAuth;
    private DatabaseReference mDatabase;
    private ValueEventListener ssReadRef;
    private ValueEventListener ssHighlightsRef;
    private ValueEventListener ssCommentsRef;

    public SsReadingActivityBinding ssReadingActivityBinding;
    public SSReadingDisplayOptions ssReadingDisplayOptions;
    public SSLessonInfo ssLessonInfo;
    public ObservableInt ssReadPosition;
    public SSRead ssRead;

    public ObservableInt ssLessonLoadingVisibility;
    public ObservableInt ssLessonEmptyStateVisibility;
    public ObservableInt ssLessonErrorStateVisibility;
    public ObservableInt ssLessonCoordinatorVisibility;

    public SSReadingViewModel(Context context, DataListener dataListener, String ssLessonIndex,
            SsReadingActivityBinding ssReadingActivityBinding) {
        this.context = context;
        this.dataListener = dataListener;
        this.ssLessonIndex = ssLessonIndex;
        this.ssReadingActivityBinding = ssReadingActivityBinding;
        this.ssFirebaseAuth = FirebaseAuth.getInstance();

        mDatabase = FirebaseDatabase.getInstance().getReference();
        mDatabase.keepSynced(true);

        ssReadPosition = new ObservableInt(0);

        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
        ssReadingDisplayOptions = new SSReadingDisplayOptions(
                prefs.getString(SSConstants.SS_SETTINGS_THEME_KEY, SSReadingDisplayOptions.SS_THEME_LIGHT),
                prefs.getString(SSConstants.SS_SETTINGS_SIZE_KEY, SSReadingDisplayOptions.SS_SIZE_MEDIUM),
                prefs.getString(SSConstants.SS_SETTINGS_FONT_KEY, SSReadingDisplayOptions.SS_FONT_ANDADA));

        ssReadingActivityBinding.ssReadingView.setReadingDisplayOptions(ssReadingDisplayOptions);

        ssLessonLoadingVisibility = new ObservableInt(View.INVISIBLE);
        ssLessonEmptyStateVisibility = new ObservableInt(View.INVISIBLE);
        ssLessonErrorStateVisibility = new ObservableInt(View.INVISIBLE);
        ssLessonCoordinatorVisibility = new ObservableInt(View.INVISIBLE);

        loadLessonInfo();
    }

    private void loadLessonInfo() {
        ssLessonLoadingVisibility.set(View.VISIBLE);
        ssLessonEmptyStateVisibility.set(View.INVISIBLE);
        ssLessonErrorStateVisibility.set(View.INVISIBLE);
        ssLessonCoordinatorVisibility.set(View.INVISIBLE);

        mDatabase.child(SSConstants.SS_FIREBASE_LESSON_INFO_DATABASE).child(ssLessonIndex)
                .addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        if (dataSnapshot != null) {
                            ssLessonInfo = dataSnapshot.getValue(SSLessonInfo.class);
                            dataListener.onLessonInfoChanged(ssLessonInfo);

                            if (ssLessonInfo != null && ssLessonInfo.days.size() > 0) {
                                DateTime today = DateTime.now().withTimeAtStartOfDay();
                                int idx = 0;

                                for (SSDay ssDay : ssLessonInfo.days) {
                                    DateTime startDate = DateTimeFormat.forPattern(SSConstants.SS_DATE_FORMAT)
                                            .parseDateTime(ssDay.date).withTimeAtStartOfDay();

                                    if (startDate.isEqual(today)) {
                                        ssReadPosition.set(idx);
                                        break;
                                    }
                                    idx++;
                                }
                            }

                            ssLessonCoordinatorVisibility.set(View.VISIBLE);
                            ssLessonLoadingVisibility.set(View.INVISIBLE);
                            ssLessonEmptyStateVisibility.set(View.INVISIBLE);
                            ssLessonErrorStateVisibility.set(View.INVISIBLE);

                            loadRead();
                        } else {
                            ssLessonEmptyStateVisibility.set(View.VISIBLE);
                            ssLessonErrorStateVisibility.set(View.INVISIBLE);
                            ssLessonLoadingVisibility.set(View.INVISIBLE);
                            ssLessonCoordinatorVisibility.set(View.INVISIBLE);
                        }
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {
                        ssLessonErrorStateVisibility.set(View.VISIBLE);
                        ssLessonLoadingVisibility.set(View.INVISIBLE);
                        ssLessonEmptyStateVisibility.set(View.INVISIBLE);
                        ssLessonCoordinatorVisibility.set(View.INVISIBLE);
                    }
                });
    }

    public void promptForEditSuggestion() {
        if (ssRead != null) {
            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
            final String name = prefs.getString(SSConstants.SS_USER_NAME_INDEX,
                    context.getString(R.string.ss_menu_anonymous_name));
            final String email = prefs.getString(SSConstants.SS_USER_EMAIL_INDEX,
                    context.getString(R.string.ss_menu_anonymous_email));

            new MaterialDialog.Builder(context).title(context.getString(R.string.ss_reading_suggest_edit))
                    .inputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES)
                    .input(context.getString(R.string.ss_reading_suggest_edit_hint), "",
                            new MaterialDialog.InputCallback() {
                                @Override
                                public void onInput(@NotNull MaterialDialog dialog, CharSequence input) {

                                    mDatabase.child(SSConstants.SS_FIREBASE_SUGGESTIONS_DATABASE)
                                            .child(ssFirebaseAuth.getCurrentUser().getUid()).child(ssRead.index)
                                            .setValue(new SSSuggestion(name, email, input.toString()));

                                    Toast.makeText(getApplicationContext(),
                                            context.getString(R.string.ss_reading_suggest_edit_done),
                                            Toast.LENGTH_LONG).show();
                                }
                            })
                    .show();
        }
    }

    private void loadRead() {
        String dayIndex = ssLessonInfo.days.get(ssReadPosition.get()).index;
        loadRead(dayIndex);
    }

    public void loadRead(final String dayIndex) {
        if (ssReadRef != null) {
            mDatabase.removeEventListener(ssReadRef);
        }

        if (ssHighlightsRef != null) {
            mDatabase.removeEventListener(ssHighlightsRef);
        }

        if (ssCommentsRef != null) {
            mDatabase.removeEventListener(ssCommentsRef);
        }

        ssHighlightsRef = mDatabase.child(SSConstants.SS_FIREBASE_HIGHLIGHTS_DATABASE)
                .child(ssFirebaseAuth.getCurrentUser().getUid()).child(dayIndex)
                .addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        SSReadHighlights ssReadHighlights = new SSReadHighlights(dayIndex, "");
                        if (dataSnapshot != null) {
                            if (dataSnapshot.getValue(SSReadHighlights.class) != null) {
                                ssReadHighlights = dataSnapshot.getValue(SSReadHighlights.class);
                            }
                        }
                        ssReadingActivityBinding.ssReadingView.setReadHighlights(ssReadHighlights);
                        ssReadingActivityBinding.ssReadingView.updateHighlights();
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {
                        SSReadHighlights ssReadHighlights = new SSReadHighlights(dayIndex, "");
                        ssReadingActivityBinding.ssReadingView.setReadHighlights(ssReadHighlights);
                    }
                });

        ssCommentsRef = mDatabase.child(SSConstants.SS_FIREBASE_COMMENTS_DATABASE)
                .child(ssFirebaseAuth.getCurrentUser().getUid()).child(dayIndex)
                .addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        SSReadComments ssReadComments = new SSReadComments(dayIndex, new ArrayList<SSComment>());
                        if (dataSnapshot != null) {
                            if (dataSnapshot.getValue(SSReadComments.class) != null) {
                                ssReadComments = dataSnapshot.getValue(SSReadComments.class);
                            }
                        }
                        ssReadingActivityBinding.ssReadingView.setReadComments(ssReadComments);
                        ssReadingActivityBinding.ssReadingView.updateComments();
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {
                        SSReadComments ssReadComments = new SSReadComments(dayIndex, new ArrayList<SSComment>());
                        ssReadingActivityBinding.ssReadingView.setReadComments(ssReadComments);
                    }
                });

        ssReadRef = mDatabase.child(SSConstants.SS_FIREBASE_READS_DATABASE).child(dayIndex)
                .addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        if (dataSnapshot != null) {
                            ssRead = dataSnapshot.getValue(SSRead.class);
                            dataListener.onReadChanged(ssRead);
                        }
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {

                    }
                });
    }

    public void destroy() {
        context = null;
        dataListener = null;
        ssLessonInfo = null;
        ssLessonIndex = null;
        ssFirebaseAuth = null;

        if (ssReadRef != null) {
            mDatabase.removeEventListener(ssReadRef);
        }

        if (ssHighlightsRef != null) {
            mDatabase.removeEventListener(ssHighlightsRef);
        }

        if (ssCommentsRef != null) {
            mDatabase.removeEventListener(ssCommentsRef);
        }

        mDatabase = null;
        ssReadRef = null;
        ssHighlightsRef = null;
        ssCommentsRef = null;
        ssReadingActivityBinding = null;
        ssReadingDisplayOptions = null;
        ssReadPosition = null;
        ssRead = null;
    }

    public void onMenuClick() {
        final View view = ssReadingActivityBinding.ssReadingSheet;
        final int state = view.getVisibility() == View.VISIBLE ? View.INVISIBLE : View.VISIBLE;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            int centerX = view.getRight() / 2;
            int centerY = view.getHeight() - 20;
            int startRadius = (state == View.VISIBLE) ? 0 : view.getHeight();
            int endRadius = (state == View.VISIBLE) ? view.getHeight() : 0;

            Animator anim = ViewAnimationUtils.createCircularReveal(view, centerX, centerY, startRadius, endRadius);

            if (state == View.VISIBLE) {
                view.setVisibility(state);
                ssReadingActivityBinding.ssReadingSheetOverlay.setVisibility(state);

            } else {
                anim.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        view.setVisibility(state);
                        ssReadingActivityBinding.ssReadingSheetOverlay.setVisibility(state);
                    }
                });
            }
            anim.start();
        } else {
            view.setVisibility(state);
            ssReadingActivityBinding.ssReadingSheetOverlay.setVisibility(state);
        }
    }

    public void onNextClick() {
        ssReadPosition.set((ssReadPosition.get() < ssLessonInfo.days.size() - 1) ? ssReadPosition.get() + 1
                : ssReadPosition.get());
        loadRead();
    }

    public void onPrevClick() {
        ssReadPosition.set((ssReadPosition.get() > 0) ? ssReadPosition.get() - 1 : ssReadPosition.get());
        loadRead();
    }

    public String getCover() {
        if (ssLessonInfo != null) {
            return ssLessonInfo.lesson.cover;
        }
        return "";
    }

    public String getLessonInterval() {
        if (ssLessonInfo != null) {
            String startDateOut = DateTimeFormat.forPattern(SSConstants.SS_DATE_FORMAT_OUTPUT).print(DateTimeFormat
                    .forPattern(SSConstants.SS_DATE_FORMAT).parseDateTime(ssLessonInfo.lesson.start_date));

            String endDateOut = DateTimeFormat.forPattern(SSConstants.SS_DATE_FORMAT_OUTPUT).print(DateTimeFormat
                    .forPattern(SSConstants.SS_DATE_FORMAT).parseDateTime(ssLessonInfo.lesson.end_date));

            return StringUtils.capitalize(startDateOut) + " - " + StringUtils.capitalize(endDateOut);
        }
        return "";
    }

    public String formatDate(String date, String DateFormatOutput) {
        return StringUtils.capitalize(DateTimeFormat.forPattern(DateFormatOutput)
                .print(DateTimeFormat.forPattern(SSConstants.SS_DATE_FORMAT).parseDateTime(date)));
    }

    public String formatDate(String date) {
        return formatDate(date, SSConstants.SS_DATE_FORMAT_OUTPUT);
    }

    public String getDayDate(int ssDayIdx) {
        if (ssLessonInfo != null && ssLessonInfo.days.size() > ssDayIdx) {
            return formatDate(ssLessonInfo.days.get(ssDayIdx).date);
        }
        return "";
    }

    @Override
    public void onSelectionStarted(float x, float y) {
        y = y - ssReadingActivityBinding.ssReadingViewScroll.getScrollY();

        DisplayMetrics metrics = new DisplayMetrics();
        ((SSReadingActivity) context).getWindowManager().getDefaultDisplay().getMetrics(metrics);
        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) ssReadingActivityBinding.ssContextMenu.ssReadingContextMenu
                .getLayoutParams();

        int contextMenuWidth = ssReadingActivityBinding.ssContextMenu.ssReadingContextMenu.getWidth();
        int contextMenuHeight = ssReadingActivityBinding.ssContextMenu.ssReadingContextMenu.getHeight();

        int screenWidth = metrics.widthPixels;
        int screenHeight = metrics.heightPixels;

        int margin = SSHelper.convertDpToPixels(context, 20);
        int jumpMargin = SSHelper.convertDpToPixels(context, 60);

        int contextMenuX = (int) x - (contextMenuWidth / 2);
        int contextMenuY = ssReadingActivityBinding.ssReadingViewScroll.getTop() + (int) y - contextMenuHeight
                - margin;

        if (contextMenuX - margin < 0) {
            contextMenuX = margin;
        }

        if (contextMenuX + contextMenuWidth + margin > screenWidth) {
            contextMenuX = screenWidth - margin - contextMenuWidth;
        }

        if (contextMenuY - margin < 0) {
            contextMenuY = contextMenuY + contextMenuHeight + jumpMargin;
        }

        params.setMargins(contextMenuX, contextMenuY, 0, 0);
        ssReadingActivityBinding.ssContextMenu.ssReadingContextMenu.setLayoutParams(params);
        ssReadingActivityBinding.ssContextMenu.ssReadingContextMenu.setVisibility(View.VISIBLE);
    }

    @Override
    public void onSelectionFinished() {
        ssReadingActivityBinding.ssContextMenu.ssReadingContextMenu.setVisibility(View.INVISIBLE);
    }

    @Override
    public void onHighlightsReceived(SSReadHighlights ssReadHighlights) {
        mDatabase.child(SSConstants.SS_FIREBASE_HIGHLIGHTS_DATABASE).child(ssFirebaseAuth.getCurrentUser().getUid())
                .child(ssReadHighlights.readIndex).setValue(ssReadHighlights);
    }

    @Override
    public void onCommentsReceived(SSReadComments ssReadComments) {
        mDatabase.child(SSConstants.SS_FIREBASE_COMMENTS_DATABASE).child(ssFirebaseAuth.getCurrentUser().getUid())
                .child(ssReadComments.readIndex).setValue(ssReadComments);
    }

    @Override
    public void onVerseClicked(String verse) {
        Intent _SSBibleActivityIntent = new Intent(context.getApplicationContext(), SSBibleVersesActivity.class);
        _SSBibleActivityIntent.putExtra(SSConstants.SS_READ_INDEX_EXTRA, ssRead.index);
        _SSBibleActivityIntent.putExtra(SSConstants.SS_READ_VERSE_EXTRA, verse);
        context.startActivity(_SSBibleActivityIntent);
    }

    public interface DataListener {
        void onLessonInfoChanged(SSLessonInfo ssLessonInfo);

        void onReadChanged(SSRead ssRead);
    }

    public void onDisplayOptionsClick() {
        SSReadingDisplayOptionsView ssReadingDisplayOptionsView = new SSReadingDisplayOptionsView();
        ssReadingDisplayOptionsView.setSSReadingViewModel(context, this, ssReadingDisplayOptions);
        ssReadingDisplayOptionsView.show(((SSReadingActivity) context).getSupportFragmentManager(),
                ssReadingDisplayOptionsView.getTag());
    }

    public void highlightYellow() {
        highlightSelection(SSContextMenu.HIGHLIGHT_YELLOW);
    }

    public void highlightOrange() {
        highlightSelection(SSContextMenu.HIGHLIGHT_ORANGE);
    }

    public void highlightGreen() {
        highlightSelection(SSContextMenu.HIGHLIGHT_GREEN);
    }

    public void highlightBlue() {
        highlightSelection(SSContextMenu.HIGHLIGHT_BLUE);
    }

    public void unHighlightSelection() {
        ssReadingActivityBinding.ssReadingView.ssReadViewBridge.unHighlightSelection();
        ssReadingActivityBinding.ssReadingView.selectionFinished();
    }

    private void highlightSelection(String color) {
        ssReadingActivityBinding.ssReadingView.ssReadViewBridge.highlightSelection(color);
        ssReadingActivityBinding.ssReadingView.selectionFinished();
    }

    public void copy() {
        ssReadingActivityBinding.ssReadingView.ssReadViewBridge.copy();
        ssReadingActivityBinding.ssReadingView.selectionFinished();
    }

    public void share() {
        ssReadingActivityBinding.ssReadingView.ssReadViewBridge.share();
        ssReadingActivityBinding.ssReadingView.selectionFinished();
    }

    public void search() {
        ssReadingActivityBinding.ssReadingView.ssReadViewBridge.search();
        ssReadingActivityBinding.ssReadingView.selectionFinished();
    }

    public void onSSReadingDisplayOptions(SSReadingDisplayOptions ssReadingDisplayOptions) {
        this.ssReadingDisplayOptions = ssReadingDisplayOptions;

        SharedPreferences shared = PreferenceManager.getDefaultSharedPreferences(context);
        SharedPreferences.Editor editor = shared.edit();
        editor.putString(SSConstants.SS_SETTINGS_THEME_KEY, ssReadingDisplayOptions.theme);
        editor.putString(SSConstants.SS_SETTINGS_FONT_KEY, ssReadingDisplayOptions.font);
        editor.putString(SSConstants.SS_SETTINGS_SIZE_KEY, ssReadingDisplayOptions.size);
        editor.apply();

        ssReadingActivityBinding.ssReadingView.setReadingDisplayOptions(ssReadingDisplayOptions);
        ssReadingActivityBinding.ssReadingView.updateReadingDisplayOptions();
    }
}