| // Copyright 2016 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package io.v.todos; |
| |
| import android.app.Activity; |
| import android.content.DialogInterface; |
| import android.content.Intent; |
| import android.os.Bundle; |
| import android.support.v7.app.AlertDialog; |
| import android.support.v7.widget.RecyclerView; |
| import android.support.v7.widget.helper.ItemTouchHelper; |
| import android.util.Log; |
| import android.view.Menu; |
| import android.view.MenuItem; |
| import android.view.View; |
| import android.view.WindowManager; |
| import android.widget.EditText; |
| import android.widget.Toolbar; |
| |
| import com.firebase.client.ChildEventListener; |
| import com.firebase.client.DataSnapshot; |
| import com.firebase.client.Firebase; |
| import com.firebase.client.FirebaseError; |
| import com.firebase.client.ValueEventListener; |
| |
| import io.v.todos.persistence.FirebasePersistence; |
| |
| /** |
| * TodoListActivity for Vanadium TODOs |
| * |
| * This activity shows a list of tasks. |
| * - Tap on a Task in order to edit it. |
| * - Swipe Left on a Task to delete it. |
| * - Swipe Right in order to mark the Task as done. |
| * - Select Edit from the menu to Edit the Todo List. |
| * - Toggle Show Done in the menu to show/hide completed Tasks. |
| * |
| * @author alexfandrianto |
| */ |
| public class TodoListActivity extends Activity { |
| private Firebase myFirebaseRef; |
| |
| private final static String SNACKOO_LISTS = "snackoo lists (Task)"; |
| private String snackooKey; |
| private TodoList snackoo; |
| private DataList<Task> snackoosList = new DataList<Task>(); |
| private boolean showDone = false; // TODO(alexfandrianto): Load from shared preferences... |
| |
| // This adapter handle mirrors the firebase list values and generates the corresponding todo |
| // item View children for a list view. |
| private TaskRecyclerAdapter adapter; |
| private ValueEventListener snackooEventListener; |
| private ChildEventListener snackoosEventListener; |
| |
| @Override |
| protected void onDestroy() { |
| myFirebaseRef.removeEventListener(snackooEventListener); |
| myFirebaseRef.removeEventListener(snackoosEventListener); |
| super.onDestroy(); |
| } |
| |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| setContentView(R.layout.activity_main); |
| |
| Intent intent = getIntent(); |
| snackooKey = intent.getStringExtra(MainActivity.INTENT_SNACKOO_KEY); |
| |
| Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar); |
| setActionBar(toolbar); |
| |
| // Set up the todo list adapter |
| final Activity self = this; |
| adapter = new TaskRecyclerAdapter(snackoosList, new View.OnClickListener() { |
| @Override |
| public void onClick(View view) { |
| String key = (String) view.getTag(); |
| |
| initiateTaskEdit(key); |
| } |
| }); |
| |
| RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler); |
| recyclerView.setAdapter(adapter); |
| |
| new ItemTouchHelper(new SwipeableTouchHelperCallback() { |
| @Override |
| public void onSwiped(final RecyclerView.ViewHolder viewHolder, final int direction) { |
| if (direction == ItemTouchHelper.RIGHT) { |
| Log.d(SNACKOO_LISTS, "Gonna mark all tasks as done"); |
| markAsDone((String)viewHolder.itemView.getTag()); |
| } else if (direction == ItemTouchHelper.LEFT) { |
| Log.d(SNACKOO_LISTS, "Gonna delete this todo list"); |
| deleteTodoItem((String)viewHolder.itemView.getTag()); |
| } |
| } |
| }).attachToRecyclerView(recyclerView); |
| |
| // Prepare our Firebase Reference and the primary listener (SNACKOOS). |
| FirebasePersistence.getDatabase(this); |
| myFirebaseRef = new Firebase(MainActivity.FIREBASE_EXAMPLE_URL); |
| setUpSnackoo(); |
| setUpSnackoos(); |
| } |
| |
| private Firebase firebaseListReference() { |
| return myFirebaseRef.child(MainActivity.SNACKOOS).child(snackooKey); |
| } |
| |
| private Firebase firebaseTasksReference() { |
| return myFirebaseRef.child(SNACKOO_LISTS).child(snackooKey); |
| } |
| |
| private void setUpSnackoo() { |
| snackooEventListener = firebaseListReference().addValueEventListener(new ValueEventListener() { |
| @Override |
| public void onDataChange(DataSnapshot dataSnapshot) { |
| snackoo = dataSnapshot.getValue(TodoList.class); |
| if (snackoo == null) { |
| // The list has been deleted. Get the heck out of here! |
| finish(); |
| return; |
| } |
| getActionBar().setTitle(snackoo.getName()); |
| } |
| |
| @Override |
| public void onCancelled(FirebaseError firebaseError) { |
| |
| } |
| }); |
| } |
| |
| // Set the visibility based on what the adapter thinks is the visible item count. |
| private void setEmptyVisiblity() { |
| View v = findViewById(R.id.empty); |
| v.setVisibility(adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE); |
| } |
| |
| // Any time a child of SNACKOOS is added/changed/removed, we mirror the changes locally. |
| private void setUpSnackoos() { |
| snackoosEventListener = firebaseTasksReference().addChildEventListener(new ChildEventListener() { |
| @Override |
| public void onChildAdded(DataSnapshot dataSnapshot, String prevKey) { |
| String fbKey = dataSnapshot.getKey(); |
| Task task = dataSnapshot.getValue(Task.class); |
| task.setKey(fbKey); |
| snackoosList.insertInOrder(task); |
| adapter.notifyDataSetChanged(); |
| |
| setEmptyVisiblity(); |
| } |
| |
| @Override |
| public void onChildChanged(DataSnapshot dataSnapshot, String prevKey) { |
| String fbKey = dataSnapshot.getKey(); |
| Task task = dataSnapshot.getValue(Task.class); |
| task.setKey(fbKey); |
| snackoosList.updateInOrder(task); |
| adapter.notifyDataSetChanged(); |
| } |
| |
| @Override |
| public void onChildRemoved(DataSnapshot dataSnapshot) { |
| String fbKey = dataSnapshot.getKey(); |
| snackoosList.removeByKey(fbKey); |
| adapter.notifyDataSetChanged(); |
| |
| setEmptyVisiblity(); |
| } |
| |
| @Override |
| public void onChildMoved(DataSnapshot dataSnapshot, String prevKey) { |
| |
| } |
| |
| @Override |
| public void onCancelled(FirebaseError firebaseError) { |
| |
| } |
| }); |
| } |
| |
| public void addTodoItem(String todo) { |
| // TODO(alexfandrianto): Turns out these are all batch changes that change the parents updatedAt |
| firebaseTasksReference().push().setValue(new Task(todo)); |
| } |
| |
| public void updateTodoItem(String fbKey, String todo) { |
| // TODO(alexfandrianto): Turns out these are all batch changes that change the parents updatedAt |
| Task task = snackoosList.findByKey(fbKey).copy(); |
| task.setText(todo); |
| firebaseTasksReference().child(fbKey).setValue(task); |
| } |
| public void markAsDone(String fbKey) { |
| // TODO(alexfandrianto): Turns out these are all batch changes that change the parents updatedAt |
| Task task = snackoosList.findByKey(fbKey).copy(); |
| task.setDone(!task.getDone()); |
| firebaseTasksReference().child(fbKey).setValue(task); |
| } |
| |
| public void deleteTodoItem(String fbKey) { |
| // TODO(alexfandrianto): Turns out these are all batch changes that change the parents updatedAt |
| firebaseTasksReference().child(fbKey).removeValue(); |
| } |
| |
| public void addCallback(View view) { |
| final EditText todoItem = new EditText(this); |
| |
| AlertDialog dialog = new AlertDialog.Builder(this) |
| .setTitle("New Todo") |
| .setView(todoItem) |
| .setPositiveButton("Add", new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int whichButton) { |
| addTodoItem(todoItem.getText().toString()); |
| } |
| }) |
| .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int whichButton) { |
| } |
| }).show(); |
| dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); |
| } |
| |
| private void initiateTaskEdit(final String fbKey) { |
| final EditText todoItem = new EditText(this); |
| todoItem.setText(snackoosList.findByKey(fbKey).getText()); |
| |
| AlertDialog dialog = new AlertDialog.Builder(this) |
| .setTitle("Editing Task") |
| .setView(todoItem) |
| .setPositiveButton("Save", new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int whichButton) { |
| updateTodoItem(fbKey, todoItem.getText().toString()); |
| } |
| }) |
| .setNeutralButton("Delete", new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int whichButton) { |
| deleteTodoItem(fbKey); |
| } |
| }) |
| .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int whichButton) { |
| } |
| }).show(); |
| dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); |
| } |
| |
| private void initiateTodoListEdit() { |
| final EditText todoItem = new EditText(this); |
| todoItem.setText(snackoo.getName()); |
| |
| AlertDialog dialog = new AlertDialog.Builder(this) |
| .setTitle("Editing Todo List") |
| .setView(todoItem) |
| .setPositiveButton("Save", new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int whichButton) { |
| updateTodoList(todoItem.getText().toString()); |
| } |
| }) |
| .setNeutralButton("Delete", new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int whichButton) { |
| deleteTodoList(); |
| } |
| }) |
| .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { |
| public void onClick(DialogInterface dialog, int whichButton) { |
| } |
| }).show(); |
| dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); |
| } |
| |
| |
| public void updateTodoList(String todo) { |
| firebaseListReference().setValue(new TodoList(todo)); |
| } |
| |
| public void deleteTodoList() { |
| firebaseListReference().removeValue(); |
| } |
| |
| |
| // The following methods are boilerplate for handling the Menu in the top right corner. |
| @Override |
| public boolean onCreateOptionsMenu(Menu menu) { |
| // Inflate the menu; this adds items to the action bar if it is present. |
| getMenuInflater().inflate(R.menu.menu_task, menu); |
| return true; |
| } |
| |
| @Override |
| public boolean onOptionsItemSelected(MenuItem item) { |
| // Handle action bar item clicks here. The action bar will |
| // automatically handle clicks on the Home/Up button, so long |
| // as you specify a parent activity in AndroidManifest.xml. |
| int id = item.getItemId(); |
| |
| switch (id) { |
| case R.id.show_done: |
| if(item.isChecked()){ |
| item.setChecked(false); |
| adapter.setShowDone(false); |
| }else{ |
| item.setChecked(true); |
| adapter.setShowDone(true); |
| } |
| adapter.notifyDataSetChanged(); |
| |
| // TODO(alexfandrianto): You may wish to save this data into SharedPreferences. |
| // You may also wish to save this to a different part of the space which is synced |
| // across your devices. |
| |
| return true; |
| case R.id.action_settings: |
| return true; |
| case R.id.action_edit: |
| initiateTodoListEdit(); |
| return true; |
| case R.id.action_share: |
| return true; |
| } |
| |
| return super.onOptionsItemSelected(item); |
| } |
| } |