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 { private final RecyclerView mRecyclerView; private List 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 { private final List mWorkouts; WorkoutRecyclerAdapter(List 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(); } } } }