otbeta/com.iamthefij.otbeta/src/main/java/com/iamthefij/otbeta/WorkoutListActivity.java

263 lines
9.7 KiB
Java

package com.iamthefij.otbeta;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.net.http.HttpResponseCache;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.goebl.david.Response;
import com.goebl.david.WebbException;
import com.iamthefij.otbeta.api.Client;
import com.iamthefij.otbeta.api.Exerciser;
import com.iamthefij.otbeta.api.Interval;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
/**
* An activity representing a list of Workouts. This activity
* has different presentations for handset and tablet-size devices. On
* handsets, the activity presents a list of items, which when touched,
* lead to a {@link WorkoutDetailActivity} representing
* item details. On tablets, the activity presents the list of items and
* item details side-by-side using two vertical panes.
*/
public class WorkoutListActivity extends AppCompatActivity {
private static final String TAG = "WorkoutListActivity";
/**
* Whether or not the activity is in two-pane mode, i.e. running on a tablet
* device.
*/
private boolean mTwoPane;
private Client mClient;
private Exerciser mExerciser;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_workout_list);
// Install cache to prevent HTTP requests every time a view is revisited
installHttpCache();
// Initialize client
mClient = new Client(this);
// Get Exerciser from store
ExerciserStore exerciserStore = new ExerciserStore(this);
mExerciser = exerciserStore.getExerciser();
// Get
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.workout_list);
new WorkoutListGetter(recyclerView).execute();
// Set up the toolbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setTitle(getTitle());
// Determine if dual pane
if (findViewById(R.id.workout_detail_container) != null) {
// The detail container view will be present only in the
// large-screen layouts (res/values-w900dp).
// If this view is present, then the
// activity should be in two-pane mode.
mTwoPane = true;
}
}
@Override
protected void onStop() {
super.onStop();
flushHttpCache();
}
private void installHttpCache() {
try {
File httpCacheDir = new File(this.getCacheDir(), "http");
long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
HttpResponseCache.install(httpCacheDir, httpCacheSize);
} catch (IOException e) {
Log.i(TAG, "HTTP response cache installation failed:" + e);
}
}
private void flushHttpCache() {
HttpResponseCache cache = HttpResponseCache.getInstalled();
if (cache != null) {
cache.flush();
}
}
/**
* Represents an asynchronous task to retrieve workouts from the api and populate
* the recycle view adapter
*/
private class WorkoutListGetter extends AsyncTask<Void, Void, Boolean> {
private final RecyclerView mRecyclerView;
private List<Interval> mWorkouts;
private boolean mInvalidSession = false;
WorkoutListGetter(RecyclerView recyclerView) {
mRecyclerView = recyclerView;
}
@Override
protected Boolean doInBackground(Void... params) {
try {
mWorkouts = mClient.getWorkouts(mExerciser, 30);
} catch (WebbException ex) {
Response response = ex.getResponse();
if (response.getStatusCode() == 403) {
mInvalidSession = true;
return false;
} else {
throw ex;
}
}
return mWorkouts != null;
}
@Override
protected void onPostExecute(Boolean success) {
super.onPostExecute(success);
if (success) {
WorkoutRecyclerAdapter adapter = new WorkoutRecyclerAdapter(mWorkouts);
mRecyclerView.setAdapter(adapter);
} else if (mInvalidSession) {
Intent loginActivity = new Intent(WorkoutListActivity.this, LoginActivity.class);
startActivity(loginActivity);
}
}
}
/**
* Adapter to display workouts as a list of cards
*/
private class WorkoutRecyclerAdapter
extends RecyclerView.Adapter<WorkoutRecyclerAdapter.WorkoutViewHolder> {
private final List<Interval> mWorkouts;
WorkoutRecyclerAdapter(List<Interval> workouts) {
mWorkouts = workouts;
}
@Override
public WorkoutViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.workout_card_view, parent, false);
return new WorkoutViewHolder(view);
}
@Override
public void onBindViewHolder(final WorkoutViewHolder holder, int position) {
Interval workout = mWorkouts.get(position);
if (workout != null) {
holder.fillView(workout);
holder.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mTwoPane) {
Bundle arguments = new Bundle();
arguments.putString(WorkoutDetailFragment.ARG_EXERCISER_UUID, mExerciser.getUuid());
arguments.putInt(WorkoutDetailFragment.ARG_WORKOUT_ID, holder.getWorkout().getId());
arguments.putString(WorkoutDetailFragment.ARG_WORKOUT_TITLE, holder.getTitle());
WorkoutDetailFragment fragment = new WorkoutDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.workout_detail_container, fragment)
.commit();
} else {
Context context = v.getContext();
Intent intent = new Intent(context, WorkoutDetailActivity.class);
intent.putExtra(WorkoutDetailFragment.ARG_EXERCISER_UUID, mExerciser.getUuid());
intent.putExtra(WorkoutDetailFragment.ARG_WORKOUT_ID, holder.getWorkout().getId());
intent.putExtra(WorkoutDetailFragment.ARG_WORKOUT_TITLE, holder.getTitle());
context.startActivity(intent);
}
}
});
}
}
@Override
public int getItemCount() {
return mWorkouts.size();
}
class WorkoutViewHolder extends RecyclerView.ViewHolder {
private final View mView;
private final TextView mWorkoutDateView;
private final TextView mWorkoutCaloriesView;
private final TextView mWorkoutMinutesView;
private final TextView mWorkoutPointsView;
private Interval mWorkout;
Interval getWorkout() {
return mWorkout;
}
WorkoutViewHolder(View view) {
super(view);
mView = view;
mWorkoutDateView = (TextView) mView.findViewById(R.id.workout_date);
mWorkoutCaloriesView = (TextView) mView.findViewById(R.id.workout_calories);
mWorkoutMinutesView = (TextView) mView.findViewById(R.id.workout_minutes);
mWorkoutPointsView = (TextView) mView.findViewById(R.id.workout_points);
}
@SuppressLint("DefaultLocale")
void fillView(Interval workout) {
mWorkout = workout;
String workoutDate = "Unknown";
String localIsoTime = workout.getStartDateLocal();
if (localIsoTime != null) {
SimpleDateFormat isoParser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US);
SimpleDateFormat formatter = new SimpleDateFormat("MMM d, yyyy", Locale.US);
try {
Date localIso = isoParser.parse(localIsoTime);
workoutDate = formatter.format(localIso);
} catch (ParseException e) {
e.printStackTrace();
}
}
mWorkoutDateView.setText(workoutDate);
mWorkoutCaloriesView.setText(String.format("%d Calories", workout.getTotalCalories()));
mWorkoutMinutesView.setText(String.format("%d minutes", workout.getTotalDuration()/60));
mWorkoutPointsView.setText(String.format("%d Splat Points", workout.getTotalPoints()));
}
void setOnClickListener(View.OnClickListener listener) {
mView.setOnClickListener(listener);
}
String getTitle() {
return (String) mWorkoutDateView.getText();
}
}
}
}