Commit 2c3e0998 authored by Nihal Singh's avatar Nihal Singh Committed by Varun Patil

Adds 'Add to Calendar' integration (#286)

* Calender provider implementation

* Undo Calendar provider. Intent approach with dialog

* Lambdas, undo manifest change

* Settings ListPreference added. Fixes minor bug from #284

* Improving EventFragment diff, cleanup

* Preserve going status of event on going back to fragment
parent 99e7df5a
...@@ -6,6 +6,10 @@ public class Constants { ...@@ -6,6 +6,10 @@ public class Constants {
public static final int RESULT_LOAD_IMAGE = 11; public static final int RESULT_LOAD_IMAGE = 11;
public static final int REQUEST_CAMERA_INT_ID = 101; public static final int REQUEST_CAMERA_INT_ID = 101;
public static final String DARK_THEME = "dark_theme"; public static final String DARK_THEME = "dark_theme";
public static final String CALENDAR_DIALOG = "calendar_dialog";
public static final String CALENDAR_DIALOG_YES = "Yes";
public static final String CALENDAR_DIALOG_NO = "No";
public static final String CALENDAR_DIALOG_ALWAYS_ASK = "Always ask";
public static final String NOTIFICATIONS_RESPONSE_JSON = "notifications_json"; public static final String NOTIFICATIONS_RESPONSE_JSON = "notifications_json";
public static final String EVENT_ID = "event_id"; public static final String EVENT_ID = "event_id";
public static final String EVENT_LATITUDE = "event_latitude"; public static final String EVENT_LATITUDE = "event_latitude";
......
...@@ -274,14 +274,20 @@ public class Event implements CardInterface { ...@@ -274,14 +274,20 @@ public class Event implements CardInterface {
subtitle += simpleDateFormatDate.format(Date) + " | " + simpleDateFormatTime.format(Date); subtitle += simpleDateFormatDate.format(Date) + " | " + simpleDateFormatTime.format(Date);
} }
String eventVenueName = getEventVenueString();
if (!eventVenueName.equals(""))
subtitle += " | " + eventVenueName;
return subtitle;
}
public String getEventVenueString() {
StringBuilder eventVenueName = new StringBuilder(); StringBuilder eventVenueName = new StringBuilder();
for (Venue venue : getEventVenues()) { for (Venue venue : getEventVenues()) {
eventVenueName.append(", ").append(venue.getVenueShortName()); eventVenueName.append(", ").append(venue.getVenueShortName());
} }
if (!eventVenueName.toString().equals("")) return eventVenueName.toString().equals("") ? "" : eventVenueName.toString().substring(2);
subtitle += " | " + eventVenueName.toString().substring(2);
return subtitle;
} }
public String getAvatarUrl() { public String getAvatarUrl() {
......
...@@ -5,12 +5,16 @@ import android.animation.Animator; ...@@ -5,12 +5,16 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet; import android.animation.AnimatorSet;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.provider.CalendarContract;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.Spanned; import android.text.Spanned;
...@@ -24,6 +28,7 @@ import android.view.View; ...@@ -24,6 +28,7 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator; import android.view.animation.DecelerateInterpolator;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
...@@ -168,12 +173,7 @@ public class EventFragment extends BackHandledFragment implements TransitionTarg ...@@ -168,12 +173,7 @@ public class EventFragment extends BackHandledFragment implements TransitionTarg
((CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams()).setBehavior(new AppBarLayout.Behavior()); ((CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams()).setBehavior(new AppBarLayout.Behavior());
// Set offset on init // Set offset on init
mAppBarLayout.post(new Runnable() { mAppBarLayout.post(() -> setAppBarOffset(appBarOffset));
@Override
public void run() {
setAppBarOffset(appBarOffset);
}
});
// Store offset for next init // Store offset for next init
mAppBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { mAppBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
...@@ -279,15 +279,12 @@ public class EventFragment extends BackHandledFragment implements TransitionTarg ...@@ -279,15 +279,12 @@ public class EventFragment extends BackHandledFragment implements TransitionTarg
if (event.getEventVenues().get(0).getVenueLatitude() == 0) { if (event.getEventVenues().get(0).getVenueLatitude() == 0) {
navigateButton.setVisibility(View.GONE); navigateButton.setVisibility(View.GONE);
} else { } else {
navigateButton.setOnClickListener(new View.OnClickListener() { navigateButton.setOnClickListener(v -> {
@Override Venue primaryVenue = event.getEventVenues().get(0);
public void onClick(View v) { Uri gmmIntentUri = Uri.parse("google.navigation:q=" + primaryVenue.getVenueLatitude() + "," + primaryVenue.getVenueLongitude() + "(" + primaryVenue.getVenueName() + ")");
Venue primaryVenue = event.getEventVenues().get(0); Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
Uri gmmIntentUri = Uri.parse("google.navigation:q=" + primaryVenue.getVenueLatitude() + "," + primaryVenue.getVenueLongitude() + "(" + primaryVenue.getVenueName() + ")"); mapIntent.setPackage("com.google.android.apps.maps");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri); startActivity(mapIntent);
mapIntent.setPackage("com.google.android.apps.maps");
startActivity(mapIntent);
}
}); });
} }
} else { } else {
...@@ -318,37 +315,26 @@ public class EventFragment extends BackHandledFragment implements TransitionTarg ...@@ -318,37 +315,26 @@ public class EventFragment extends BackHandledFragment implements TransitionTarg
}); });
} }
eventPicture.setOnClickListener(new View.OnClickListener() { eventPicture.setOnClickListener(v -> zoomImageFromThumb(eventPicture));
@Override
public void onClick(View v) {
zoomImageFromThumb(eventPicture);
}
});
mShortAnimationDuration = getResources().getInteger(android.R.integer.config_shortAnimTime); mShortAnimationDuration = getResources().getInteger(android.R.integer.config_shortAnimTime);
final FloatingActionButton fab = (FloatingActionButton) getView().findViewById(R.id.edit_fab); final FloatingActionButton fab = getView().findViewById(R.id.edit_fab);
if (((MainActivity) getActivity()).editEventAccess(event)) { if (((MainActivity) getActivity()).editEventAccess(event)) {
fab.show(); fab.show();
NestedScrollView nsv = (NestedScrollView) getView().findViewById(R.id.event_scrollview); NestedScrollView nsv = getView().findViewById(R.id.event_scrollview);
nsv.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() { nsv.setOnScrollChangeListener((NestedScrollView.OnScrollChangeListener) (v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
@Override if (scrollY > oldScrollY) fab.hide();
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { else fab.show();
if (scrollY > oldScrollY) fab.hide();
else fab.show();
}
}); });
} }
fab.setOnClickListener(new View.OnClickListener() { fab.setOnClickListener(v -> {
@Override AddEventFragment addEventFragment = new AddEventFragment();
public void onClick(View v) { Bundle bundle = new Bundle();
AddEventFragment addEventFragment = new AddEventFragment(); bundle.putString("id", event.getEventID());
Bundle bundle = new Bundle(); addEventFragment.setArguments(bundle);
bundle.putString("id", event.getEventID()); ((MainActivity) getActivity()).updateFragment(addEventFragment);
addEventFragment.setArguments(bundle);
((MainActivity) getActivity()).updateFragment(addEventFragment);
}
}); });
} }
...@@ -368,221 +354,290 @@ public class EventFragment extends BackHandledFragment implements TransitionTarg ...@@ -368,221 +354,290 @@ public class EventFragment extends BackHandledFragment implements TransitionTarg
} }
private View.OnClickListener getGoingButtonOnClickListener() { private View.OnClickListener getGoingButtonOnClickListener() {
return new View.OnClickListener() { return v -> {
@Override int currentStatus = event.getEventUserUes();
public void onClick(View v) { final int finalStatus;
int currentStatus = event.getEventUserUes();
final int finalStatus; if (currentStatus == Constants.STATUS_GOING) {
event.setEventGoingCount(event.getEventGoingCount() - 1);
if (currentStatus == Constants.STATUS_GOING) { finalStatus = Constants.STATUS_NOT_GOING;
event.setEventGoingCount(event.getEventGoingCount() - 1); } else if (currentStatus == Constants.STATUS_INTERESTED) {
finalStatus = Constants.STATUS_NOT_GOING; event.setEventInterestedCount(event.getEventInterestedCount() - 1);
} else if (currentStatus == Constants.STATUS_INTERESTED) { event.setEventGoingCount(event.getEventGoingCount() + 1);
event.setEventInterestedCount(event.getEventInterestedCount() - 1); finalStatus = Constants.STATUS_GOING;
event.setEventGoingCount(event.getEventGoingCount() + 1); } else {
finalStatus = Constants.STATUS_GOING; event.setEventGoingCount(event.getEventGoingCount() + 1);
} else { finalStatus = Constants.STATUS_GOING;
event.setEventGoingCount(event.getEventGoingCount() + 1); }
finalStatus = Constants.STATUS_GOING;
}
RetrofitInterface retrofitInterface = Utils.getRetrofitInterface(); RetrofitInterface retrofitInterface = Utils.getRetrofitInterface();
retrofitInterface.updateUserEventStatus(Utils.getSessionIDHeader(), event.getEventID(), finalStatus).enqueue(new Callback<Void>() { retrofitInterface.updateUserEventStatus(Utils.getSessionIDHeader(), event.getEventID(), finalStatus).enqueue(new Callback<Void>() {
@Override @Override
public void onResponse(Call<Void> call, Response<Void> response) { public void onResponse(Call<Void> call, Response<Void> response) {
event.setEventUserUes(finalStatus); event.setEventUserUes(finalStatus);
updateGoingInterestedButtonsAppearance(finalStatus); updateGoingInterestedButtonsAppearance(finalStatus);
// Update global memory cache // Preserve status on going back
Utils.eventCache.updateCache(event); if (getArguments() != null) {
getArguments().putString(Constants.EVENT_JSON, Utils.gson.toJson(event));
} }
@Override // Update global memory cache
public void onFailure(Call<Void> call, Throwable t) { Utils.eventCache.updateCache(event);
Toast.makeText(getContext(), "Network Error", Toast.LENGTH_LONG).show();
if (finalStatus == Constants.STATUS_GOING) {
addEventToCalender();
} }
}
}); @Override
} public void onFailure(Call<Void> call, Throwable t) {
Toast.makeText(getContext(), "Network Error", Toast.LENGTH_LONG).show();
}
});
}; };
} }
private View.OnClickListener getInterestedButtonOnClickListener () { private View.OnClickListener getInterestedButtonOnClickListener() {
return new View.OnClickListener() { return v -> {
@Override int currentStatus = event.getEventUserUes();
public void onClick(View v) { final int finalStatus;
int currentStatus = event.getEventUserUes();
final int finalStatus; if (currentStatus == Constants.STATUS_INTERESTED) {
event.setEventInterestedCount(event.getEventInterestedCount() - 1);
if (currentStatus == Constants.STATUS_INTERESTED) { finalStatus = Constants.STATUS_NOT_GOING;
event.setEventInterestedCount(event.getEventInterestedCount() - 1); } else if (currentStatus == Constants.STATUS_GOING) {
finalStatus = Constants.STATUS_NOT_GOING; event.setEventInterestedCount(event.getEventInterestedCount() + 1);
} else if (currentStatus == Constants.STATUS_GOING) { event.setEventGoingCount(event.getEventGoingCount() - 1);
event.setEventInterestedCount(event.getEventInterestedCount() + 1); finalStatus = Constants.STATUS_INTERESTED;
event.setEventGoingCount(event.getEventGoingCount() - 1); } else {
finalStatus = Constants.STATUS_INTERESTED; event.setEventInterestedCount(event.getEventInterestedCount() + 1);
} else { finalStatus = Constants.STATUS_INTERESTED;
event.setEventGoingCount(event.getEventInterestedCount() + 1); }
finalStatus = Constants.STATUS_INTERESTED;
}
RetrofitInterface retrofitInterface = Utils.getRetrofitInterface();
retrofitInterface.updateUserEventStatus(Utils.getSessionIDHeader(), event.getEventID(), finalStatus).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
event.setEventUserUes(finalStatus);
updateGoingInterestedButtonsAppearance(finalStatus);
// Update global memory cache RetrofitInterface retrofitInterface = Utils.getRetrofitInterface();
Utils.eventCache.updateCache(event); retrofitInterface.updateUserEventStatus(Utils.getSessionIDHeader(), event.getEventID(), finalStatus).enqueue(new Callback<Void>() {
} @Override
public void onResponse(Call<Void> call, Response<Void> response) {
event.setEventUserUes(finalStatus);
updateGoingInterestedButtonsAppearance(finalStatus);
@Override // Update global memory cache
public void onFailure(Call<Void> call, Throwable t) { Utils.eventCache.updateCache(event);
Toast.makeText(getContext(), "Network Error", Toast.LENGTH_LONG).show();
}
}); if (finalStatus == Constants.STATUS_INTERESTED) {
addEventToCalender();
}
} }
};
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
Toast.makeText(getContext(), "Network Error", Toast.LENGTH_LONG).show();
}
private void zoomImageFromThumb ( final ImageView thumbView){ });
// If there's an animation in progress, cancel it };
// immediately and proceed with this one. }
if (mCurrentAnimator != null) {
mCurrentAnimator.cancel(); private void addEventToCalender() {
} SharedPreferences sharedPref = getContext().getSharedPreferences(Constants.PREF_NAME, Context.MODE_PRIVATE);
String savedOption = sharedPref.getString(Constants.CALENDAR_DIALOG, Constants.CALENDAR_DIALOG_ALWAYS_ASK);
if (savedOption.equals(Constants.CALENDAR_DIALOG_YES)) {
createAddToCalendarIntent();
} else if (savedOption.equals(Constants.CALENDAR_DIALOG_ALWAYS_ASK)) {
showAddEventToCalendarDialog();
}
}
// Load the high-resolution "zoomed-in" image. private void saveCalendarDialogPreference(boolean dontAskAgain, boolean yes) {
expandedImageView = (ImageView) getActivity().findViewById( SharedPreferences sharedPref = getActivity().getSharedPreferences(Constants.PREF_NAME, Context.MODE_PRIVATE);
R.id.expanded_image_event); SharedPreferences.Editor editor = sharedPref.edit();
expandedImageView.setImageDrawable(thumbView.getDrawable()); if (!dontAskAgain) {
editor.putString(Constants.CALENDAR_DIALOG, Constants.CALENDAR_DIALOG_ALWAYS_ASK);
// Calculate the starting and ending bounds for the zoomed-in image. editor.commit();
// This step involves lots of math. Yay, math. } else {
startBounds = new Rect(); if (yes) {
final Rect finalBounds = new Rect(); editor.putString(Constants.CALENDAR_DIALOG, Constants.CALENDAR_DIALOG_YES);
final Point globalOffset = new Point(); editor.commit();
// The start bounds are the global visible rectangle of the thumbnail,
// and the final bounds are the global visible rectangle of the container
// view. Also set the container view's offset as the origin for the
// bounds, since that's the origin for the positioning animation
// properties (X, Y).
thumbView.getGlobalVisibleRect(startBounds);
getActivity().findViewById(R.id.container_event)
.getGlobalVisibleRect(finalBounds, globalOffset);
startBounds.offset(-globalOffset.x, -globalOffset.y);
finalBounds.offset(-globalOffset.x, -globalOffset.y);
// Adjust the start bounds to be the same aspect ratio as the final
// bounds using the "center crop" technique. This prevents undesirable
// stretching during the animation. Also calculate the start scaling
// factor (the end scaling factor is always 1.0).
float startScale;
if ((float) finalBounds.width() / finalBounds.height()
> (float) startBounds.width() / startBounds.height()) {
// Extend start bounds horizontally
startScale = (float) startBounds.height() / finalBounds.height();
float startWidth = startScale * finalBounds.width();
float deltaWidth = (startWidth - startBounds.width()) / 2;
startBounds.left -= deltaWidth;
startBounds.right += deltaWidth;
} else { } else {
// Extend start bounds vertically editor.putString(Constants.CALENDAR_DIALOG, Constants.CALENDAR_DIALOG_NO);
startScale = (float) startBounds.width() / finalBounds.width(); editor.commit();
float startHeight = startScale * finalBounds.height();
float deltaHeight = (startHeight - startBounds.height()) / 2;
startBounds.top -= deltaHeight;
startBounds.bottom += deltaHeight;
} }
}
}
// Hide the thumbnail and show the zoomed-in view. When the animation private void showAddEventToCalendarDialog() {
// begins, it will position the zoomed-in view in the place of the AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getContext());
// thumbnail. LayoutInflater layoutInflater = LayoutInflater.from(getContext());
thumbView.setAlpha(0f); View layout = layoutInflater.inflate(R.layout.calendar_dialog_checkbox, null);
expandedImageView.setVisibility(View.VISIBLE); dialogBuilder.setView(layout);
CheckBox dontShowAgain = layout.findViewById(R.id.skip);
// Set the pivot point for SCALE_X and SCALE_Y transformations
// to the top-left corner of the zoomed-in view (the default dialogBuilder.setTitle("Add to Calendar")
// is the center of the view). .setMessage("You will be notified about this event by InstiApp. Do you also want to add this event to your calendar?")
expandedImageView.setPivotX(0f); .setPositiveButton("Yes", (dialog, which) -> {
expandedImageView.setPivotY(0f); createAddToCalendarIntent();
saveCalendarDialogPreference(dontShowAgain.isChecked(), true);
// Construct and run the parallel animation of the four translation and })
// scale properties (X, Y, SCALE_X, and SCALE_Y). .setNegativeButton("No", (dialog, which) -> {
AnimatorSet set = new AnimatorSet(); dialog.cancel();
set saveCalendarDialogPreference(dontShowAgain.isChecked(), false);
.play(ObjectAnimator.ofFloat(expandedImageView, View.X, })
startBounds.left, finalBounds.left)) .create()
.with(ObjectAnimator.ofFloat(expandedImageView, View.Y, .show();
startBounds.top, finalBounds.top)) }
.with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X,
startScale, 1f))
.with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_Y,
startScale, 1f));
set.setDuration(mShortAnimationDuration);
set.setInterpolator(new DecelerateInterpolator());
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mCurrentAnimator = null;
expandedImageView.setBackgroundColor(Color.parseColor("#9E9E9E"));
}
@Override private void createAddToCalendarIntent() {
public void onAnimationCancel(Animator animation) { Intent intent = new Intent(Intent.ACTION_INSERT);
mCurrentAnimator = null; intent.setType("vnd.android.cursor.item/event");
}
}); intent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, event.getEventStartTime().getTime());
set.start(); intent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, event.getEventEndTime().getTime());
mCurrentAnimator = set; intent.putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, event.isAllDayEvent());
intent.putExtra(CalendarContract.Events.TITLE, event.getTitle());
intent.putExtra(CalendarContract.Events.DESCRIPTION, event.getEventDescription());
intent.putExtra(CalendarContract.Events.EVENT_LOCATION, event.getEventVenueString());
startActivity(intent);
}
private void zoomImageFromThumb(final ImageView thumbView) {
// If there's an animation in progress, cancel it
// immediately and proceed with this one.
if (mCurrentAnimator != null) {
mCurrentAnimator.cancel();
}
startScaleFinal = startScale; // Load the high-resolution "zoomed-in" image.
zoomMode = true; expandedImageView = getActivity().findViewById(
R.id.expanded_image_event);
expandedImageView.setImageDrawable(thumbView.getDrawable());
// Calculate the starting and ending bounds for the zoomed-in image.
// This step involves lots of math. Yay, math.
startBounds = new Rect();
final Rect finalBounds = new Rect();
final Point globalOffset = new Point();
// The start bounds are the global visible rectangle of the thumbnail,
// and the final bounds are the global visible rectangle of the container
// view. Also set the container view's offset as the origin for the
// bounds, since that's the origin for the positioning animation
// properties (X, Y).
thumbView.getGlobalVisibleRect(startBounds);
getActivity().findViewById(R.id.container_event)
.getGlobalVisibleRect(finalBounds, globalOffset);
startBounds.offset(-globalOffset.x, -globalOffset.y);
finalBounds.offset(-globalOffset.x, -globalOffset.y);
// Adjust the start bounds to be the same aspect ratio as the final
// bounds using the "center crop" technique. This prevents undesirable
// stretching during the animation. Also calculate the start scaling
// factor (the end scaling factor is always 1.0).
float startScale;
if ((float) finalBounds.width() / finalBounds.height()
> (float) startBounds.width() / startBounds.height()) {
// Extend start bounds horizontally
startScale = (float) startBounds.height() / finalBounds.height();
float startWidth = startScale * finalBounds.width();
float deltaWidth = (startWidth - startBounds.width()) / 2;
startBounds.left -= deltaWidth;
startBounds.right += deltaWidth;
} else {
// Extend start bounds vertically
startScale = (float) startBounds.width() / finalBounds.width();
float startHeight = startScale * finalBounds.height();
float deltaHeight = (startHeight - startBounds.height()) / 2;
startBounds.top -= deltaHeight;
startBounds.bottom += deltaHeight;
} }
private void zoomOut ( final ImageView expandedImageView, Rect startBounds, // Hide the thumbnail and show the zoomed-in view. When the animation
float startScaleFinal, final View thumbView){ // begins, it will position the zoomed-in view in the place of the
expandedImageView.setBackgroundColor(0x00000000); // thumbnail.
if (mCurrentAnimator != null) { thumbView.setAlpha(0f);
mCurrentAnimator.cancel(); expandedImageView.setVisibility(View.VISIBLE);
// Set the pivot point for SCALE_X and SCALE_Y transformations
// to the top-left corner of the zoomed-in view (the default
// is the center of the view).
expandedImageView.setPivotX(0f);
expandedImageView.setPivotY(0f);
// Construct and run the parallel animation of the four translation and
// scale properties (X, Y, SCALE_X, and SCALE_Y).
AnimatorSet set = new AnimatorSet();
set
.play(ObjectAnimator.ofFloat(expandedImageView, View.X,
startBounds.left, finalBounds.left))
.with(ObjectAnimator.ofFloat(expandedImageView, View.Y,
startBounds.top, finalBounds.top))
.with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X,
startScale, 1f))
.with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_Y,
startScale, 1f));
set.setDuration(mShortAnimationDuration);
set.setInterpolator(new DecelerateInterpolator());
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mCurrentAnimator = null;
expandedImageView.setBackgroundColor(Color.parseColor("#9E9E9E"));
} }
// Animate the four positioning/sizing properties in parallel, @Override
// back to their original values. public void onAnimationCancel(Animator animation) {
AnimatorSet set = new AnimatorSet(); mCurrentAnimator = null;
set.play(ObjectAnimator }
.ofFloat(expandedImageView, View.X, startBounds.left)) });
.with(ObjectAnimator set.start();
.ofFloat(expandedImageView, mCurrentAnimator = set;
View.Y, startBounds.top))
.with(ObjectAnimator
.ofFloat(expandedImageView,
View.SCALE_X, startScaleFinal))
.with(ObjectAnimator
.ofFloat(expandedImageView,
View.SCALE_Y, startScaleFinal));
set.setDuration(mShortAnimationDuration);
set.setInterpolator(new DecelerateInterpolator());
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
thumbView.setAlpha(1f);
expandedImageView.setVisibility(View.GONE);
mCurrentAnimator = null;
}
@Override startScaleFinal = startScale;
public void onAnimationCancel(Animator animation) { zoomMode = true;
thumbView.setAlpha(1f); }
expandedImageView.setVisibility(View.GONE);
mCurrentAnimator = null; private void zoomOut(final ImageView expandedImageView, Rect startBounds,
} float startScaleFinal, final View thumbView) {
}); expandedImageView.setBackgroundColor(0x00000000);
set.start(); if (mCurrentAnimator != null) {
mCurrentAnimator = set; mCurrentAnimator.cancel();
} }
// Animate the four positioning/sizing properties in parallel,
// back to their original values.
AnimatorSet set = new AnimatorSet();
set.play(ObjectAnimator
.ofFloat(expandedImageView, View.X, startBounds.left))
.with(ObjectAnimator
.ofFloat(expandedImageView,
View.Y, startBounds.top))
.with(ObjectAnimator
.ofFloat(expandedImageView,
View.SCALE_X, startScaleFinal))
.with(ObjectAnimator
.ofFloat(expandedImageView,
View.SCALE_Y, startScaleFinal));
set.setDuration(mShortAnimationDuration);
set.setInterpolator(new DecelerateInterpolator());
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
thumbView.setAlpha(1f);
expandedImageView.setVisibility(View.GONE);
mCurrentAnimator = null;
}
@Override
public void onAnimationCancel(Animator animation) {
thumbView.setAlpha(1f);
expandedImageView.setVisibility(View.GONE);
mCurrentAnimator = null;
}
});
set.start();
mCurrentAnimator = set;
} }
}
...@@ -5,6 +5,8 @@ import android.content.Intent; ...@@ -5,6 +5,8 @@ import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import androidx.preference.ListPreference;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.SwitchPreferenceCompat; import androidx.preference.SwitchPreferenceCompat;
...@@ -37,64 +39,54 @@ public class SettingsFragment extends PreferenceFragmentCompat { ...@@ -37,64 +39,54 @@ public class SettingsFragment extends PreferenceFragmentCompat {
// Show contact number // Show contact number
showContactPref = (SwitchPreferenceCompat) findPreference("show_contact"); showContactPref = (SwitchPreferenceCompat) findPreference("show_contact");
showContactPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { showContactPref.setOnPreferenceChangeListener((preference, option) -> {
@Override toggleShowContact((SwitchPreferenceCompat) preference, option);
public boolean onPreferenceChange(Preference preference, Object o) { return false;
toggleShowContact((SwitchPreferenceCompat) preference, o);
return false;
}
}); });
showContactPref.setEnabled(false); showContactPref.setEnabled(false);
// Dark Theme // Dark Theme
SwitchPreferenceCompat darkThemePref = (SwitchPreferenceCompat) findPreference("dark_theme"); SwitchPreferenceCompat darkThemePref = (SwitchPreferenceCompat) findPreference("dark_theme");
darkThemePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { darkThemePref.setOnPreferenceChangeListener((preference, option) -> {
@Override toggleDarkTheme((boolean) option);
public boolean onPreferenceChange(Preference preference, Object o) { return true;
toggleDarkTheme((SwitchPreferenceCompat) preference, o);
return true;
}
}); });
darkThemePref.setChecked(sharedPref.getBoolean(Constants.DARK_THEME, false)); darkThemePref.setChecked(sharedPref.getBoolean(Constants.DARK_THEME, false));
// Add to Calendar
ListPreference calendarPref = (ListPreference) findPreference("add_to_calendar");
calendarPref.setOnPreferenceChangeListener((preference, option) -> {
toggleCalendarDialog((String) option);
return true;
});
calendarPref.setValue(sharedPref.getString(Constants.CALENDAR_DIALOG, Constants.CALENDAR_DIALOG_ALWAYS_ASK));
// Update Profile // Update Profile
Preference profilePref = findPreference("profile"); Preference profilePref = findPreference("profile");
profilePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { profilePref.setOnPreferenceClickListener(preference -> {
@Override openWebURL("https://gymkhana.iitb.ac.in/sso/user");
public boolean onPreferenceClick(Preference preference) { return false;
openWebURL("https://gymkhana.iitb.ac.in/sso/user");
return false;
}
}); });
// Feedback // Feedback
Preference feedbackPref = findPreference("feedback"); Preference feedbackPref = findPreference("feedback");
feedbackPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { feedbackPref.setOnPreferenceClickListener(preference -> {
@Override openWebURL("https://insti.app/feedback");
public boolean onPreferenceClick(Preference preference) { return false;
openWebURL("https://insti.app/feedback");
return false;
}
}); });
// About // About
Preference aboutPref = findPreference("about"); Preference aboutPref = findPreference("about");
aboutPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { aboutPref.setOnPreferenceClickListener(preference -> {
@Override openAbout();
public boolean onPreferenceClick(Preference preference) { return false;
openAbout();
return false;
}
}); });
// Logout // Logout
Preference logoutPref = findPreference("logout"); Preference logoutPref = findPreference("logout");
logoutPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { logoutPref.setOnPreferenceClickListener(preference -> {
@Override logout();
public boolean onPreferenceClick(Preference preference) { return false;
logout();
return false;
}
}); });
// Disable buttons if not logged in // Disable buttons if not logged in
...@@ -139,8 +131,8 @@ public class SettingsFragment extends PreferenceFragmentCompat { ...@@ -139,8 +131,8 @@ public class SettingsFragment extends PreferenceFragmentCompat {
} }
} }
public void toggleShowContact(final SwitchPreferenceCompat showContactPref, Object o) { private void toggleShowContact(final SwitchPreferenceCompat showContactPref, Object option) {
final boolean isChecked = (boolean) o; final boolean isChecked = (boolean) option;
showContactPref.setEnabled(false); showContactPref.setEnabled(false);
RetrofitInterface retrofitInterface = Utils.getRetrofitInterface(); RetrofitInterface retrofitInterface = Utils.getRetrofitInterface();
retrofitInterface.patchUserMe(Utils.getSessionIDHeader(), new UserShowContactPatchRequest(isChecked)).enqueue(new Callback<User>() { retrofitInterface.patchUserMe(Utils.getSessionIDHeader(), new UserShowContactPatchRequest(isChecked)).enqueue(new Callback<User>() {
...@@ -166,17 +158,29 @@ public class SettingsFragment extends PreferenceFragmentCompat { ...@@ -166,17 +158,29 @@ public class SettingsFragment extends PreferenceFragmentCompat {
}); });
} }
public void toggleDarkTheme(final SwitchPreferenceCompat showContactPref, Object o) { private void toggleDarkTheme(boolean option) {
editor.putBoolean(Constants.DARK_THEME, (boolean) o); editor.putBoolean(Constants.DARK_THEME, option);
editor.commit();
Utils.changeTheme(this, option);
}
private void toggleCalendarDialog(String option) {
// Using strings.xml values for populating ListPreference. `option` comes from strings.xml
// Using Constants for updating SharedPrefs. `choice` comes from Constants.
String choice = Constants.CALENDAR_DIALOG_ALWAYS_ASK;
if (option.equals(getString(R.string.calendar_yes))) choice = Constants.CALENDAR_DIALOG_YES;
else if (option.equals(getString(R.string.calendar_no))) choice = Constants.CALENDAR_DIALOG_NO;
editor.putString(Constants.CALENDAR_DIALOG, choice);
editor.commit(); editor.commit();
Utils.changeTheme(this, (boolean) o);
} }
public void openAbout() { private void openAbout() {
Utils.updateFragment(new AboutFragment(), getActivity()); Utils.updateFragment(new AboutFragment(), getActivity());
} }
public void logout() { private void logout() {
final SessionManager sessionManager = new SessionManager(getContext()); final SessionManager sessionManager = new SessionManager(getContext());
RetrofitInterface retrofitInterface = Utils.getRetrofitInterface(); RetrofitInterface retrofitInterface = Utils.getRetrofitInterface();
retrofitInterface.logout(Utils.getSessionIDHeader()).enqueue(new EmptyCallback<Void>() { retrofitInterface.logout(Utils.getSessionIDHeader()).enqueue(new EmptyCallback<Void>() {
......
<vector android:height="36dp" android:tint="#767676"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="36dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M17,12h-5v5h5v-5zM16,1v2L8,3L8,1L6,1v2L5,3c-1.11,0 -1.99,0.9 -1.99,2L3,19c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2h-1L18,1h-2zM19,19L5,19L5,8h14v11z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_root"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:padding="20dp" >
<CheckBox
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/skip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Remember my choice and don't ask me again" >
</CheckBox>
</LinearLayout>
\ No newline at end of file
...@@ -27,6 +27,17 @@ ...@@ -27,6 +27,17 @@
<item>QIP</item> <item>QIP</item>
</string-array> </string-array>
<string-array name="add_to_calendar_options">
<item>@string/calendar_yes</item>
<item>@string/calendar_no</item>
<item>@string/calendar_always_ask</item>
</string-array>
<!-- Add to Calendar Preference options -->
<string name="calendar_yes">Yes</string>
<string name="calendar_no">No</string>
<string name="calendar_always_ask">Always ask</string>
<string name="default_notification_channel_id">INSTIAPP_NOTIFS</string> <string name="default_notification_channel_id">INSTIAPP_NOTIFS</string>
<!--NSS side--> <!--NSS side-->
......
...@@ -15,6 +15,14 @@ ...@@ -15,6 +15,14 @@
app:summary="Note: this feature is in beta" app:summary="Note: this feature is in beta"
android:icon="@drawable/ic_color_lens_gray_36dp"/> android:icon="@drawable/ic_color_lens_gray_36dp"/>
<ListPreference
app:key="add_to_calendar"
app:title="Add to Calendar"
app:summary="Add to calendar on Going/Interested press"
app:entries="@array/add_to_calendar_options"
app:entryValues="@array/add_to_calendar_options"
android:icon="@drawable/ic_event_gray_36dp"/>
<Preference <Preference
app:key="profile" app:key="profile"
app:title="Update Profile" app:title="Update Profile"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment