diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml index 54ed3d1..1b4f5ce 100644 --- a/.idea/assetWizardSettings.xml +++ b/.idea/assetWizardSettings.xml @@ -23,7 +23,7 @@ @@ -33,7 +33,7 @@ diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 67fe5f6..e57b8e6 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/README.md b/README.md index 3b0c3e6..691690c 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,8 @@ ## Landing Page https://habit-rabbit.000webhostapp.com/ -## Beta Release -https://youtu.be/Xox4mv7I9XQ - +## Official Release +https://youtu.be/j23T9routSI ## Project Description: @@ -83,3 +82,6 @@ https://youtu.be/g607Lzud3Ss ## Alpha Release https://youtu.be/jdsvigK7bPs +## Beta Release +https://youtu.be/Xox4mv7I9XQ + diff --git a/app/.idea/workspace.xml b/app/.idea/workspace.xml index 63b3fac..d5d9d22 100644 --- a/app/.idea/workspace.xml +++ b/app/.idea/workspace.xml @@ -24,10 +24,10 @@ - @@ -44,8 +44,6 @@ - - @@ -60,8 +58,10 @@ - + + + @@ -164,35 +164,35 @@ - + - - - - - - + + + + + + - - - - - - - + + + + + + + - + - + + + - - diff --git a/app/build.gradle b/app/build.gradle index 27a1735..0ca4a3d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -25,17 +25,17 @@ android { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'com.android.support:appcompat-v7:27.1.0' - implementation 'com.android.support:design:27.1.0' - implementation 'com.android.support:support-v4:27.1.0' - implementation 'com.android.support:recyclerview-v7:27.1.0' + implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'com.android.support:design:27.1.1' + implementation 'com.android.support:support-v4:27.1.1' + implementation 'com.android.support:recyclerview-v7:27.1.1' implementation 'com.squareup:android-times-square:1.6.5@aar' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' - implementation 'com.android.support.constraint:constraint-layout:1.0.2' + implementation 'com.android.support.constraint:constraint-layout:1.1.0' implementation 'de.hdodenhof:circleimageview:2.2.0' implementation 'com.android.volley:volley:1.1.0' - implementation 'com.android.support:cardview-v7:27.1.0' + implementation 'com.android.support:cardview-v7:27.1.1' implementation 'com.google.code.gson:gson:2.8.2' } diff --git a/app/local.properties b/app/local.properties index b77f908..392fe13 100644 --- a/app/local.properties +++ b/app/local.properties @@ -7,5 +7,5 @@ # Location of the SDK. This is only used by Gradle. # For customization when using a Version Control System, please read the # header note. -#Mon Mar 12 08:20:23 EDT 2018 -sdk.dir=C\:\\Users\\SunnyD\\AppData\\Local\\Android\\Sdk +#Mon Apr 30 11:43:07 EDT 2018 +sdk.dir=C\:\\Users\\john\\AppData\\Local\\Android\\Sdk diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b851607..218f241 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -53,7 +53,8 @@ android:name="android.support.PARENT_ACTIVITY" android:value="comjianzhaojohnhabit_rabbit.httpsgithub.habit_rabbit.MainActivity" /> - - + + + + + + + + - \ No newline at end of file + diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/AboutusActivity.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/AboutusActivity.java new file mode 100644 index 0000000..fe2deea --- /dev/null +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/AboutusActivity.java @@ -0,0 +1,76 @@ +package comjianzhaojohnhabit_rabbit.httpsgithub.habit_rabbit; + +import android.content.Intent; +import android.net.Uri; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; + +import java.io.File; + +public class AboutusActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_aboutus2); + } + public void github(View view) { + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/jianzhaojohn/Habit-Rabbit")); + startActivity(browserIntent); + } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.navigation_menu, menu); + return true; + } + + /** + * This hook is called whenever an item in your options menu is selected. + * + * @param item-The menu item that was selected. + * @return boolean Return false to allow normal menu processing to proceed, true to consume it here. + */ + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + + case R.id.nav_Profile: + startActivity(new Intent(AboutusActivity.this, ProfileActivity.class)); + break; + case R.id.nav_agenda: + startActivity(new Intent(AboutusActivity.this, CalendarActivity.class)); + break; + case R.id.nav_habits: + startActivity(new Intent(AboutusActivity.this, HabitListActivity.class)); + break; + + case R.id.nav_logout: + try { + // getApplicationContext().deleteFile("autionloginfile"); + File autologin = getApplicationContext().getFileStreamPath("autionloginfile"); + autologin.delete(); + // clear and delete data file, then logout + SharedPref.clearAll(AboutusActivity.this); + String fileName = SharedPref.FILE_NAME; + File file = new File(this.getFilesDir().getParent() + "/shared_prefs/" + fileName + ".xml"); + file.delete(); + + Intent intent = new Intent(this, LoginActivity.class); + intent.setFlags(intent.FLAG_ACTIVITY_NEW_TASK | intent.FLAG_ACTIVITY_CLEAR_TOP | intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + } catch (Exception e) { + } + break; + + default: + } + return super.onOptionsItemSelected(item); + } + +} + diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/AddHabitActivity.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/AddHabitActivity.java index abc6ddc..a2e980f 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/AddHabitActivity.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/AddHabitActivity.java @@ -1,9 +1,14 @@ package comjianzhaojohnhabit_rabbit.httpsgithub.habit_rabbit; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.annotation.TargetApi; import android.app.Activity; -import android.app.AlertDialog; import android.content.Intent; +import android.os.Build; import android.os.Bundle; +import android.support.design.widget.Snackbar; +import android.text.TextUtils; import android.view.View; import android.widget.Button; import android.widget.Spinner; @@ -15,7 +20,6 @@ import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.StringRequest; -import com.android.volley.toolbox.Volley; import org.json.JSONException; import org.json.JSONObject; @@ -24,6 +28,15 @@ import java.util.Map; public class AddHabitActivity extends Activity { + + private TextView mTitleView, mDesView, mTimesView; + private Spinner mPeriodView; + private Switch mReminder; + private View mAddHabitView; + private View mProgressView; + + private String username, title, description, times, period, reminder; + private int valTimes; /** * * Called when the activity is starting. This is where most initialization should go: calling setContentView(int) to inflate the activity's UI, using findViewById(int) to programmatically interact with widgets in the UI, calling managedQuery(android.net.Uri, String[], String, String[], String) to retrieve cursors for data being displayed, etc. @@ -43,13 +56,21 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_new_habit); + mTitleView = (TextView)findViewById(R.id.editText_title); + mDesView = (TextView)findViewById(R.id.editText_description); + mTimesView = (TextView)findViewById(R.id.editText_times); + mPeriodView = (Spinner)findViewById(R.id.spinner_f); + mReminder = (Switch)findViewById(R.id.switch_reminder); + mAddHabitView = (View) findViewById(R.id.new_habit_form); + mProgressView = (View) findViewById(R.id.add_progress); + Button ok_button = (Button) findViewById(R.id.button_habit_ok); - final Button cancel_btn = (Button) findViewById(R.id.button_habit_cancel); + Button cancel_btn = (Button) findViewById(R.id.button_habit_cancel); ok_button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - addHabitRequest(); + attemptAddHabit(); } } ); @@ -64,26 +85,60 @@ public void onClick(View v) { }); } + private void attemptAddHabit() { + // Reset errors. + mTitleView.setError(null); + mTimesView.setError(null); - private void addHabitRequest() { // get params - TextView mTitleView = (TextView)findViewById(R.id.editText_title); - TextView mDesView = (TextView)findViewById(R.id.editText_description); - TextView mTimesView = (TextView)findViewById(R.id.editText_times); - Spinner mPeriodView = (Spinner)findViewById(R.id.spinner_f); - Switch mRemider = (Switch)findViewById(R.id.switch_reminder); - - final String username = SharedPref.getUser(this); - final String title = mTitleView.getText().toString(); - final String description = mDesView.getText().toString(); - final String times; - if(mTimesView.getText().toString()=="0"){ - times="1"; - }else{ - times = mTimesView.getText().toString(); + username = SharedPref.getUser(this); + title = mTitleView.getText().toString(); + times = mTimesView.getText().toString(); + description = mDesView.getText().toString(); + period = mPeriodView.getSelectedItem().toString(); + reminder = mReminder.isChecked()?"1":"0"; + + boolean cancel = false; + View focusView = null; + + // check the validation of times + if(TextUtils.isEmpty(times)){ + mTimesView.setError("Enter a non-zero repeat times."); + focusView = mTimesView; + cancel = true; + } else { + try { + valTimes = Integer.parseInt(times); + if (valTimes == 0){ + mTimesView.setError("Enter a non-zero integer."); + focusView = mTimesView; + cancel = true; + } + } catch (NumberFormatException e){ + mTimesView.setError("Enter a non-zero integer."); + focusView = mTimesView; + cancel = true; + } + } + + // check the validation of title + if(TextUtils.isEmpty(title) || title == "") { + mTitleView.setError("Habit title cannot be empty."); + focusView = mTitleView; + cancel = true; + } + + if(cancel) { + focusView.requestFocus(); + } else { + showProgress(true); + addHabitRequest(); + Snackbar.make(mTitleView, "Adding new habit...", Snackbar.LENGTH_SHORT) + .show(); } - final String period = mPeriodView.getSelectedItem().toString(); - final String reminder = mRemider.isChecked()?"1":"0"; + } + + private void addHabitRequest() { // send add new habit request RequestQueue queue = VolleySingleton.getInstance(this).getRequestQueue(this); @@ -104,32 +159,22 @@ public void onResponse(String response) { int habit_id = jsonRes.getInt("habit_id"); // update local file to store this new habit - Habit habit = new Habit(habit_id, title, period, Integer.parseInt(times)); + Habit habit = new Habit(habit_id, title, period, valTimes); SharedPref.saveHabit(AddHabitActivity.this, habit); HabitList.addHabit(habit); - //TODO: notify adapter - // jump to habit list page -// startActivity(new Intent(AddHabitActivity.this, HabitListActivity.class)); finish(); - HabitListActivity.adapter.notifyItemInserted(HabitList.HABITS_list.size() - 1); + int position = HabitList.HABITS_list.size() - 1; + HabitListActivity.adapter.notifyItemInserted(position); + HabitListActivity.recyclerView.scrollToPosition(position); } else { // show message when fails - AlertDialog.Builder builder = new AlertDialog.Builder(AddHabitActivity.this); - builder.setTitle("Add New Habit") - .setMessage("Add new habit failed!") - .setNegativeButton("Retry", null) - .setPositiveButton("OK", null) - .create() + Snackbar.make(mTitleView, "Adding new habit \"" + title + "\" failed!", Snackbar.LENGTH_SHORT) .show(); } } catch (JSONException e) { //show message when catch exception - AlertDialog.Builder builder = new AlertDialog.Builder(AddHabitActivity.this); - builder.setTitle("Response error") - .setMessage(e.toString()) - .setNegativeButton("OK", null) - .create() + Snackbar.make(mTitleView, "Response Error: " + e.toString(), Snackbar.LENGTH_SHORT) .show(); e.printStackTrace(); } @@ -139,11 +184,7 @@ public void onResponse(String response) { // on errorResponse @Override public void onErrorResponse(VolleyError error) { - AlertDialog.Builder builder = new AlertDialog.Builder(AddHabitActivity.this); - builder.setTitle("Volley Error") - .setMessage(error.toString()) - .setNegativeButton("OK", null) - .create() + Snackbar.make(mTitleView, "Volley Error! Please check your connection or try again later.", Snackbar.LENGTH_SHORT) .show(); } }) { @@ -166,4 +207,38 @@ protected Map getParams() { queue.add(addHabitReq); } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) + private void showProgress(final boolean show) { + // On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow + // for very easy animations. If available, use these APIs to fade-in + // the progress spinner. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { + int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime); + + mAddHabitView.setVisibility(show ? View.GONE : View.VISIBLE); + mAddHabitView.animate().setDuration(shortAnimTime).alpha( + show ? 0 : 1).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mAddHabitView.setVisibility(show ? View.GONE : View.VISIBLE); + } + }); + + mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); + mProgressView.animate().setDuration(shortAnimTime).alpha( + show ? 1 : 0).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); + } + }); + } else { + // The ViewPropertyAnimator APIs are not available, so simply show + // and hide the relevant UI components. + mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); + mAddHabitView.setVisibility(show ? View.GONE : View.VISIBLE); + } + } + } diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/AgendaAdapeter.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/AgendaAdapeter.java index 768aee5..8238f44 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/AgendaAdapeter.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/AgendaAdapeter.java @@ -1,8 +1,9 @@ package comjianzhaojohnhabit_rabbit.httpsgithub.habit_rabbit; -import android.app.AlertDialog; +import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; +import android.support.design.widget.Snackbar; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.MenuItem; @@ -12,12 +13,10 @@ import android.widget.PopupMenu; import android.widget.ProgressBar; import android.widget.TextView; -import android.widget.Toast; import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.toolbox.StringRequest; -import com.android.volley.toolbox.Volley; import org.json.JSONException; import org.json.JSONObject; @@ -26,31 +25,32 @@ import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.Hashtable; +import java.util.LinkedList; import java.util.Map; /** * Created by john on 2018/3/22. */ -public class AgendaAdapeter extends RecyclerView.Adapter{ +public class AgendaAdapeter extends RecyclerView.Adapter { private ArrayList mList; private int mNumItems; - public AgendaAdapeter( ArrayList list){ + public AgendaAdapeter(ArrayList list) { mList = list; mNumItems = list.size(); } /** - * * Called when RecyclerView needs a new RecyclerView.ViewHolder of the given type to represent an item. - - This new ViewHolder should be constructed with a new View that can represent the items of the given type. You can either create a new View manually or inflate it from an XML layout file. - - The new ViewHolder will be used to display items of the adapter using onBindViewHolder(ViewHolder, int, List). Since it will be re-used to display different items in the data set, it is a good idea to cache references to sub views of the View to avoid unnecessary findViewById(int) calls. + *

+ * This new ViewHolder should be constructed with a new View that can represent the items of the given type. You can either create a new View manually or inflate it from an XML layout file. + *

+ * The new ViewHolder will be used to display items of the adapter using onBindViewHolder(ViewHolder, int, List). Since it will be re-used to display different items in the data set, it is a good idea to cache references to sub views of the View to avoid unnecessary findViewById(int) calls. * - * @param parent-The ViewGroup into which the new View will be added after it is bound to an adapter position. + * @param parent-The ViewGroup into which the new View will be added after it is bound to an adapter position. * @param viewType-The view type of the new View. * @return A new ViewHolder that holds a View of the given view type. */ @@ -67,10 +67,9 @@ public AgendaAdapeter.EventViewHolder onCreateViewHolder(ViewGroup parent, int v } /** - * * Called by RecyclerView to display the data at the specified position. This method should update the contents of the itemView to reflect the item at the given position. * - * @param holder-The ViewHolder which should be updated to represent the contents of the item at the given position in the data set. + * @param holder-The ViewHolder which should be updated to represent the contents of the item at the given position in the data set. * @param position-The position of the item within the adapter's data set. */ @Override @@ -84,7 +83,7 @@ public int getItemCount() { } - class EventViewHolder extends RecyclerView.ViewHolder{ + class EventViewHolder extends RecyclerView.ViewHolder { TextView titleTextView; TextView detailTextView; @@ -93,29 +92,28 @@ class EventViewHolder extends RecyclerView.ViewHolder{ ImageView progressDone; //constructor - public EventViewHolder(View itemView){ + public EventViewHolder(View itemView) { super(itemView); - titleTextView = (TextView)itemView.findViewById(R.id.tv_event_name); - detailTextView=(TextView)itemView.findViewById(R.id.tv_event_detail); - mProgress=(ProgressBar)itemView.findViewById(R.id.completion_progressBar); - progressTxt=itemView.findViewById(R.id.progress_txt); - progressDone =itemView.findViewById(R.id.done_img); + titleTextView = (TextView) itemView.findViewById(R.id.tv_event_name); + detailTextView = (TextView) itemView.findViewById(R.id.tv_event_detail); + mProgress = (ProgressBar) itemView.findViewById(R.id.completion_progressBar); + progressTxt = itemView.findViewById(R.id.progress_txt); + progressDone = itemView.findViewById(R.id.done_img); } /** - * * bind the information to the view and display them in the fragement * * @param event- user habbit */ - void bind(Habit event){ + void bind(Habit event) { titleTextView.setText(event.getName()); detailTextView.setText(event.getDescription()); // set progress mProgress.setMax(event.getTimesPerPeriod()); mProgress.setProgress(event.getStreak()); - progressTxt.setText(event.getStreak()+"/"+event.getTimesPerPeriod()); + progressTxt.setText(event.getStreak() + "/" + event.getTimesPerPeriod()); // on click listeners progressDone.setOnClickListener(v -> addRecordRequest(event)); @@ -135,16 +133,20 @@ void bind(Habit event){ popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { - switch (item.getItemId()) { - case R.id.detail: - Intent intent = new Intent(context, HabitDetailActivity.class); - intent.putExtra(HabitDetailFragment.ARG_ITEM_ID, event.getHabitID()+""); - context.startActivity(intent); - break; - case R.id.check: - addRecordRequest(event); - break; - } + switch (item.getItemId()) { + case R.id.detail: + Intent intent = new Intent(context, HabitDetailActivity.class); + intent.putExtra(HabitDetailFragment.ARG_ITEM_ID, event.getHabitID() + ""); + context.startActivity(intent); + break; + case R.id.check: + addRecordRequest(event); + break; + case R.id.decrease: + attemptRemoveRecord(event); +// removeRecordRequest(event); + break; + } return false; } }); @@ -154,15 +156,94 @@ public boolean onMenuItemClick(MenuItem item) { }); } + private void attemptRemoveRecord(Habit habit) { + Date currentDate = new Date(); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); + final String date = dateFormat.format(currentDate); + Context context = itemView.getContext(); + + LinkedList records = habit.getTodayRecords(); + if(records.size() > 0) { + removeRecordRequest(habit, records.peek()); + } else { + Snackbar.make(titleTextView, "No record today to remove!", Snackbar.LENGTH_SHORT) + .show(); + } + } + + private void removeRecordRequest(Habit habit, Date dateTime) { + // get params + final String username = HabitList.getUserName(); + final String habit_id = habit.getHabitID() + ""; +// Date currentDate = new Date(); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); + final String date = dateFormat.format(dateTime); + Context context = itemView.getContext(); + // send delete habit request + RequestQueue queue = VolleySingleton.getInstance(context).getRequestQueue(context); + final String remove_record_url = "https://habit-rabbit.000webhostapp.com/remove_record.php"; + + ProgressDialog progress = new ProgressDialog(context); + progress.setProgressStyle(ProgressDialog.STYLE_SPINNER); + progress.setMessage("Decrementing records of habit: " + habit.getName()); + progress.show(); + + // request server to add a new record to this habit to database + StringRequest recordReq = new StringRequest(Request.Method.POST, remove_record_url, + response -> { + progress.dismiss(); + try { + // parse the response + JSONObject jsonRes = new JSONObject(response); + Boolean success = jsonRes.getBoolean("success"); + + if (success) { + // update local records + habit.updateStreaks(dateTime, -1); + SharedPref.saveRecords(context, jsonRes.getJSONArray("records")); + notifyItemChanged(mList.indexOf(habit)); + + Snackbar.make(titleTextView, "Decremented records of \""+habit.getName()+"\" by 1!", Snackbar.LENGTH_SHORT) + .show(); + } else { + //show message when fails + Snackbar.make(titleTextView, "Decrementing records of \""+habit.getName()+"\" failed!", Snackbar.LENGTH_SHORT) + .show(); + } + } catch (JSONException e) { + //show message when catch exception + Snackbar.make(titleTextView, "Decrementing records of \""+habit.getName()+"\" failed! Please retry later.", Snackbar.LENGTH_SHORT) + .show(); + e.printStackTrace(); + } + }, error -> { + progress.dismiss(); + Snackbar.make(titleTextView, "Decrementing record failed! Please check your network and try again.", Snackbar.LENGTH_SHORT) + .show(); + }) { + @Override + protected Map getParams() { + Map params = new HashMap<>(); + params.put("username", username); + params.put("habit_id", habit_id); + params.put("date", date); + return params; + } + }; + + queue.add(recordReq); + } + /** - * update the local change to dtatbase + * update the local change to database * * @param habit- user habbit */ private void addRecordRequest(Habit habit) { + // get params final String username = HabitList.getUserName(); - final String habit_id = habit.getHabitID()+""; + final String habit_id = habit.getHabitID() + ""; Date currentDate = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); final String date = dateFormat.format(currentDate); @@ -171,9 +252,15 @@ private void addRecordRequest(Habit habit) { RequestQueue queue = VolleySingleton.getInstance(context).getRequestQueue(context); final String add_record_url = "https://habit-rabbit.000webhostapp.com/add_record.php"; - // request server to add this habit to database - StringRequest loginReq = new StringRequest(Request.Method.POST, add_record_url, + ProgressDialog progress = new ProgressDialog(context); + progress.setProgressStyle(ProgressDialog.STYLE_SPINNER); + progress.setMessage("Checking habit: " + habit.getName()); + progress.show(); + + // request server to add a new record to this habit to database + StringRequest recordReq = new StringRequest(Request.Method.POST, add_record_url, response -> { + progress.dismiss(); try { // parse the response JSONObject jsonRes = new JSONObject(response); @@ -182,38 +269,27 @@ private void addRecordRequest(Habit habit) { if (success) { // update local records habit.updateStreaks(currentDate, 1); - SharedPref.saveRecords(context,jsonRes.getJSONArray("records")); + SharedPref.saveRecords(context, jsonRes.getJSONArray("records")); notifyItemChanged(mList.indexOf(habit)); -// mProgress.setProgress(habit.getStreak()); -// progressTxt.setText(habit.getStreak()+"/"+habit.getTimesPerPeriod()); + + Snackbar.make(titleTextView, "New record added!", Snackbar.LENGTH_SHORT) + .show(); } else { //show message when fails - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle("Adding Record") - .setMessage("Adding record failed!") - .setNegativeButton("Retry", null) - .setPositiveButton("OK", null) - .create() + Snackbar.make(titleTextView, "Checking the habit failed!", Snackbar.LENGTH_SHORT) .show(); } } catch (JSONException e) { //show message when catch exception - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle("Response error") - .setMessage(e.toString()) - .setNegativeButton("OK", null) - .create() + Snackbar.make(titleTextView, "Checking the habit failed! Please retry later.", Snackbar.LENGTH_SHORT) .show(); e.printStackTrace(); } }, error -> { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle("Volley Error") - .setMessage(error.toString()) - .setNegativeButton("OK", null) - .create() - .show(); - }) { + progress.dismiss(); + Snackbar.make(titleTextView, "Checking failed! Please check your network and try again.", Snackbar.LENGTH_SHORT) + .show(); + }) { @Override protected Map getParams() { Map params = new HashMap<>(); @@ -224,7 +300,7 @@ protected Map getParams() { } }; - queue.add(loginReq); + queue.add(recordReq); } diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/AgendaItem_Fragment.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/AgendaItem_Fragment.java index 79b2cf4..b8432a4 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/AgendaItem_Fragment.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/AgendaItem_Fragment.java @@ -52,6 +52,4 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, return rootView; } - - } diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/CalendarActivity.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/CalendarActivity.java index 5edce09..00d6c7d 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/CalendarActivity.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/CalendarActivity.java @@ -37,8 +37,12 @@ public boolean onOptionsItemSelected(MenuItem item) { case R.id.nav_Profile: startActivity(new Intent(CalendarActivity.this, ProfileActivity.class)); break; + case R.id.nav_aboutus: + startActivity(new Intent(CalendarActivity.this, AboutusActivity.class)); + break; case R.id.nav_agenda: break; + case R.id.nav_logout: try{ // getApplicationContext().deleteFile("autionloginfile"); diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/EditProfileActivity.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/EditProfileActivity.java index 78e27f0..ee71eaf 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/EditProfileActivity.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/EditProfileActivity.java @@ -6,6 +6,9 @@ import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; public class EditProfileActivity extends AppCompatActivity { @@ -14,10 +17,34 @@ public class EditProfileActivity extends AppCompatActivity { * generate the view for this page * @param savedInstanceState If the activity is being re-initialized after previously being shut down then this Bundle contains the data it most recently supplied in onSaveInstanceState(Bundle). Note: Otherwise it is null. */ + + Button saveButton; + EditText change; + TextView userName; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_edit_profile); + + saveButton = (Button) findViewById(R.id.saveButton); + change = (EditText) findViewById(R.id.ChangeName_Field); + userName = (TextView) findViewById(R.id.change_prof_pic); + + saveButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + userName.setText(change.getText().toString()); + } + } + + + + ); + } + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + userName.setText(change.getText().toString()); } } diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/Habit.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/Habit.java index 0d98412..12cd0a6 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/Habit.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/Habit.java @@ -10,8 +10,10 @@ import java.util.Calendar; import java.util.Date; import java.util.Hashtable; +import java.util.LinkedList; +import java.util.List; -public class Habit implements Parcelable{ +public class Habit implements Parcelable { @SerializedName("habit_id") private int habitID; @@ -28,9 +30,11 @@ public class Habit implements Parcelable{ private transient int streak; // history record of this habit private transient Hashtable records; + // list of today's records as datetime + private transient LinkedList todayRecords; //one constructor - public Habit () { + public Habit() { habitID = -1; name = ""; period = "day"; @@ -41,8 +45,9 @@ public Habit () { streak = 0; records = new Hashtable<>(); } + //constructor - public Habit(int id, String name, String period, int times){ + public Habit(int id, String name, String period, int times) { setHabitID(id); this.name = name; this.period = period; @@ -54,6 +59,7 @@ public Habit(int id, String name, String period, int times){ streak = 0; this.records = new Hashtable<>(); } + //constructor public Habit(int id, String name, String period, int times, String description, boolean reminder, Date startDate) { setHabitID(id); @@ -69,13 +75,13 @@ public Habit(int id, String name, String period, int times, String description, // following are what we need for implementing parcelabel------------------------------------------------------------------------------------------ //constructor - public Habit(Parcel in){ + public Habit(Parcel in) { habitID = Integer.valueOf(in.readString()); name = in.readString(); period = in.readString(); - timesPerPeriod=Integer.valueOf(in.readString()); + timesPerPeriod = Integer.valueOf(in.readString()); description = in.readString(); - reminder=false; + reminder = false; startDate = new Date(); streak = 0; } @@ -105,6 +111,7 @@ public Habit[] newArray(int size) { /** * Describe the kinds of special objects contained in this Parcelable instance's marshaled representation + * * @return a bitmask indicating the set of special object types marshaled by this Parcelable object instance.Value is either 0 or CONTENTS_FILE_DESCRIPTOR. */ @Override @@ -113,10 +120,11 @@ public int describeContents() { } /** - *Flatten this object in to a Parcel. - * @param dest The Parcel in which the object should be written. + * Flatten this object in to a Parcel. + * + * @param dest The Parcel in which the object should be written. * @param flags Additional flags about how the object should be written. May be 0 or PARCELABLE_WRITE_RETURN_VALUE. - Value is either 0 or PARCELABLE_WRITE_RETURN_VALUE. + * Value is either 0 or PARCELABLE_WRITE_RETURN_VALUE. */ @Override public void writeToParcel(Parcel dest, int flags) { @@ -162,6 +170,9 @@ public void setDescription(String description) { } public Hashtable getRecords() { + if (this.records == null) { + this.records = new Hashtable<>(); + } return records; } @@ -174,6 +185,9 @@ public void updateStreaks(Date date, int count) { if (this.records == null) { this.records = new Hashtable<>(); } + + if (todayRecords == null) todayRecords = new LinkedList<>(); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); // records.merge(dateFormat.format(date), count, Integer::sum); String dateString = dateFormat.format(date); @@ -189,19 +203,26 @@ public void updateStreaks(Date date, int count) { calendar.setTime(date); if (period.equals("day") && (calendar.get(Calendar.YEAR) == today.get(Calendar.YEAR)) && calendar.get(Calendar.DAY_OF_YEAR) == today.get(Calendar.DAY_OF_YEAR)) { - streak += 1; + streak += count; } if (period.equals("week") && calendar.get(Calendar.YEAR) == today.get(Calendar.YEAR) && calendar.get(Calendar.WEEK_OF_YEAR) == today.get(Calendar.WEEK_OF_YEAR)) { - streak += 1; + streak += count; } if (period.equals("month") && calendar.get(Calendar.YEAR) == today.get(Calendar.YEAR) && calendar.get(Calendar.MONTH) == today.get(Calendar.MONTH)) { - streak += 1; + streak += count; + } + + if ((calendar.get(Calendar.YEAR) == today.get(Calendar.YEAR)) && + calendar.get(Calendar.DAY_OF_YEAR) == today.get(Calendar.DAY_OF_YEAR)) { + if (count > 0) + todayRecords.add(date); + else todayRecords.remove(date); } } -//following are all setter and getter for the variable + //following are all setter and getter for the variable public Integer getHabitID() { return habitID; } @@ -226,8 +247,12 @@ public Date getStartDate() { return startDate; } + public LinkedList getTodayRecords() { + if (todayRecords == null) todayRecords = new LinkedList<>(); + return todayRecords; + } - /* +/* private static SharedPreferences.Editor editor; private static SharedPreferences sharedPref; private static Context sharedContext; @@ -313,10 +338,11 @@ public static void setSharedContext(Context inputContext){ */ //toString method - public String makeString(Context mContext){ + public String makeString(Context mContext) { return this.habitID + ", " + name + ',' + this.period + ',' + reminder + ',' + startDate.toString() + ',' + records.size() + ',' + SharedPref.getRecords(mContext).size(); } + //getter public int getStreak() { return streak; diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitCheckReciever.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitCheckReciever.java index 360e0e1..8e63b1b 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitCheckReciever.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitCheckReciever.java @@ -16,30 +16,66 @@ public class HabitCheckReciever extends BroadcastReceiver { - private static boolean timerOn = false; private static SharedPreferences sharedPref; private static SharedPreferences.Editor editor; - private static Context shared_context; - private static PendingIntent pendingIntent; + private Calendar midnight; private static NotificationHelper notificationHelper; @Override public void onReceive(Context context, Intent intent) { Log.d("alarm", "reciever"); - checkHabits(); + setAlarm(context); + setEditorAndSharedPref(context); + initializeNotificationHelper(context); + if (haveNotCheckedHabitsToday()){ + checkHabits(); + changeLastDayCheckedToToday(); + } + } + + private void initializeNotificationHelper(Context context){ + if (notificationHelper==null){ + notificationHelper = new NotificationHelper(context); + } + } + + private void changeLastDayCheckedToToday() { + int today = Calendar.getInstance().get(Calendar.DAY_OF_YEAR); + editor.putInt("DayOfYear",today); + } + + private boolean haveNotCheckedHabitsToday(){ + return Calendar.getInstance().get(Calendar.DAY_OF_YEAR) != sharedPref.getInt("DayOfYear",-1); + } + + private void setAlarm(Context context) { + Intent intent = new Intent(context,HabitCheckReciever.class); + PendingIntent pendingIntent = PendingIntent.getBroadcast(context,0,intent,0); + + AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + alarmManager.set(AlarmManager.RTC,getMidnight().getTimeInMillis(),pendingIntent); } - public static boolean isTimerOn() { return timerOn; } - public void setTimerOn(){timerOn = true; } + private Calendar getMidnight() { + if (midnight==null){ + midnight = Calendar.getInstance(); + midnight.add(Calendar.DATE,1); + midnight.set(Calendar.HOUR, 0); + midnight.set(Calendar.MINUTE, 1); + } + return midnight; + } - public static void setShared_context(Context context){ - shared_context = context; - sharedPref = shared_context.getSharedPreferences("UserInfo", Context.MODE_PRIVATE); - editor = sharedPref.edit(); - notificationHelper = new NotificationHelper(shared_context); + private void setEditorAndSharedPref(Context context) { + if (sharedPref==null){ + sharedPref = context.getSharedPreferences("UserInfo",Context.MODE_PRIVATE); + editor = sharedPref.edit(); + } } + + public static boolean rabbitIsAlive() { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); int complete = 0; @@ -121,7 +157,6 @@ public static void checkHabits(){ editor.putBoolean("RabbitAlive",rabbitAlive); editor.apply(); - //TODO send to notification helper - } + } diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitDetailActivity.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitDetailActivity.java index 61dc883..5819a4f 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitDetailActivity.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitDetailActivity.java @@ -1,13 +1,19 @@ package comjianzhaojohnhabit_rabbit.httpsgithub.habit_rabbit; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.annotation.TargetApi; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; +import android.os.Build; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; +import android.support.design.widget.Snackbar; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; +import android.text.TextUtils; import android.util.Log; import android.view.MenuItem; import android.view.View; @@ -35,6 +41,15 @@ * in a {@link HabitListActivity}. */ public class HabitDetailActivity extends AppCompatActivity { + private TextView mTitleView, mDesView, mTimesView; + private Spinner mPeriodView; + private Switch mReminder; + private View mProgressView; + private View mDetailView; + + private Habit currentHabit; + private String username, title, description, times, period, reminder, habit_id; + private int valTimes; @Override protected void onCreate(Bundle savedInstanceState) { @@ -51,12 +66,12 @@ protected void onCreate(Bundle savedInstanceState) { public void onClick(View v) { AlertDialog.Builder builder = new AlertDialog.Builder(HabitDetailActivity.this); builder.setTitle("Edit Habit") - .setMessage("Do you want to save your change on this habit?") + .setMessage("Do you want to save your changes on this habit?") .setNegativeButton("NO", null) .setPositiveButton("YES", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - editHabitRequest(); + preRequest(); } }) .create() @@ -90,6 +105,9 @@ public void onClick(DialogInterface dialog, int which) { .add(R.id.habit_detail_container, fragment) .commit(); } + + mDetailView = (View) findViewById(R.id.habit_detail_container); + mProgressView = (View) findViewById(R.id.edit_progress); } @Override @@ -108,27 +126,65 @@ public boolean onOptionsItemSelected(MenuItem item) { return super.onOptionsItemSelected(item); } - private void editHabitRequest() { + private void preRequest(){ // get params - final Habit habit = HabitList.Habit_table.get(getIntent().getStringExtra(HabitDetailFragment.ARG_ITEM_ID)); - TextView mTitleView = (TextView)findViewById(R.id.title_txt); - TextView mDesView = (TextView)findViewById(R.id.detail_txt); - TextView mTimesView = (TextView)findViewById(R.id.times_txt); - Spinner mPeriodView = (Spinner)findViewById(R.id.period_spinner); - final Switch mReminder = (Switch)findViewById(R.id.reminder_switch); - - final String username = SharedPref.getUser(HabitDetailActivity.this); - final String habit_id = habit.getHabitID()+""; - final String title = mTitleView.getText().toString(); - final String description = mDesView.getText().toString(); - final String times; - if(Integer.parseInt(mTimesView.getText().toString()) > 0){ - times = mTimesView.getText().toString(); - }else{ - times = "1"; + + mTitleView = findViewById(R.id.title_txt); + mDesView = findViewById(R.id.detail_txt); + mTimesView = findViewById(R.id.times_txt); + mPeriodView = (Spinner)findViewById(R.id.period_spinner); + mReminder = (Switch)findViewById(R.id.reminder_switch); + + username = SharedPref.getUser(HabitDetailActivity.this); + currentHabit = HabitList.Habit_table.get(getIntent().getStringExtra(HabitDetailFragment.ARG_ITEM_ID)); + habit_id = currentHabit.getHabitID()+""; + description = mDesView.getText().toString(); + title = mTitleView.getText().toString(); + times = mTimesView.getText().toString(); + period = mPeriodView.getSelectedItem().toString(); + reminder = mReminder.isChecked()?"1":"0"; + + boolean cancel = false; + View focusView = null; + + // check the validation of times + if(TextUtils.isEmpty(times)){ + mTimesView.setError("Enter a non-zero repeat times."); + focusView = mTimesView; + cancel = true; + } else { + try { + valTimes = Integer.parseInt(times); + if (valTimes == 0){ + mTimesView.setError("Enter a non-zero integer."); + focusView = mTimesView; + cancel = true; + } + } catch (NumberFormatException e){ + mTimesView.setError("Enter a non-zero integer."); + focusView = mTimesView; + cancel = true; + } + } + + // check the validation of title + if(TextUtils.isEmpty(title) || title == "") { + mTitleView.setError("Habit title cannot be empty."); + focusView = mTitleView; + cancel = true; + } + + if(cancel) { + focusView.requestFocus(); + } else { + showProgress(true); + editHabitRequest(); + Snackbar.make(mTitleView, "Saving changes...", Snackbar.LENGTH_SHORT) + .show(); } - final String period = mPeriodView.getSelectedItem().toString(); - final String reminder = mReminder.isChecked()?"1":"0"; + } + + private void editHabitRequest() { // send edit habit request RequestQueue queue = VolleySingleton.getInstance(this).getRequestQueue(this); @@ -139,6 +195,7 @@ private void editHabitRequest() { new Response.Listener(){ @Override public void onResponse(String response) { + showProgress(false); try { // parse the response JSONObject jsonRes = new JSONObject(response); @@ -146,37 +203,25 @@ public void onResponse(String response) { if (success) { // update local file - habit.setName(title); - habit.setTimesPerPeriod(Integer.parseInt(times)); - habit.setPeriod(period); - habit.setReminder(mReminder.isChecked()); - habit.setDescription(description); - SharedPref.editHabit(HabitDetailActivity.this, habit); + currentHabit.setName(title); + currentHabit.setTimesPerPeriod(valTimes); + currentHabit.setPeriod(period); + currentHabit.setReminder(mReminder.isChecked()); + currentHabit.setDescription(description); + SharedPref.editHabit(HabitDetailActivity.this, currentHabit); + HabitListActivity.adapter.notifyItemChanged(HabitList.HABITS_list.indexOf(currentHabit)); // alert user - AlertDialog.Builder builder = new AlertDialog.Builder(HabitDetailActivity.this); - builder.setTitle("Edit Habit") - .setMessage("Changes have been saved!") - .setPositiveButton("OK", null) - .create() + Snackbar.make(mTitleView, "Habit has been saved.", Snackbar.LENGTH_SHORT) .show(); } else { //show message when fails - AlertDialog.Builder builder = new AlertDialog.Builder(HabitDetailActivity.this); - builder.setTitle("Edit Habit") - .setMessage("Edit habit failed!") - .setNegativeButton("Retry", null) - .setPositiveButton("OK", null) - .create() + Snackbar.make(mTitleView, "Failed on Saving this habit!", Snackbar.LENGTH_SHORT) .show(); } } catch (JSONException e) { //show message when catch exception - AlertDialog.Builder builder = new AlertDialog.Builder(HabitDetailActivity.this); - builder.setTitle("Response error") - .setMessage(e.toString()) - .setNegativeButton("OK", null) - .create() + Snackbar.make(mTitleView, "Response Error: " + e.toString(), Snackbar.LENGTH_SHORT) .show(); e.printStackTrace(); } @@ -185,11 +230,8 @@ public void onResponse(String response) { //On errorResponse @Override public void onErrorResponse(VolleyError error) { - AlertDialog.Builder builder = new AlertDialog.Builder(HabitDetailActivity.this); - builder.setTitle("Volley Error") - .setMessage(error.toString()) - .setNegativeButton("OK", null) - .create() + showProgress(false); + Snackbar.make(mTitleView, "Volley Error! Please check your connection or try again later.", Snackbar.LENGTH_SHORT) .show(); } }) { @@ -211,4 +253,37 @@ protected Map getParams() { queue.add(loginReq); } + @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) + private void showProgress(final boolean show) { + // On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow + // for very easy animations. If available, use these APIs to fade-in + // the progress spinner. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { + int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime); + + mDetailView.setVisibility(show ? View.GONE : View.VISIBLE); + mDetailView.animate().setDuration(shortAnimTime).alpha( + show ? 0 : 1).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mDetailView.setVisibility(show ? View.GONE : View.VISIBLE); + } + }); + + mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); + mProgressView.animate().setDuration(shortAnimTime).alpha( + show ? 1 : 0).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); + } + }); + } else { + // The ViewPropertyAnimator APIs are not available, so simply show + // and hide the relevant UI components. + mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); + mDetailView.setVisibility(show ? View.GONE : View.VISIBLE); + } + } + } diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitDetailFragment.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitDetailFragment.java index 98e4388..6b2175e 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitDetailFragment.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitDetailFragment.java @@ -93,10 +93,10 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.habit_detail, container, false); GraphView graph = (GraphView) rootView.findViewById(R.id.graph); - Log.e("DetailFragment", "CreatedView"); +// Log.e("DetailFragment", "CreatedView"); // Show habit details if (mItem != null) { - Log.e("DetailFragment_mItem", mItem.getName()); +// Log.d("DetailFragment_mItem", mItem.getName()); ((TextView) rootView.findViewById(R.id.title_txt)).setText(mItem.getName()); ((TextView) rootView.findViewById(R.id.times_txt)).setText(mItem.getTimesPerPeriod() + ""); Spinner spinner = rootView.findViewById(R.id.period_spinner); @@ -112,6 +112,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, // show habit history in graph as line private void drawLineGraph(GraphView graph, Habit habit) { +// Log.d("HabitDetail", "Draw Line Graph"); String period = habit.getPeriod(); // draw expected points List expectedPoints = getExpectedPoints(habit); diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitList.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitList.java index 6e44402..5e84d97 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitList.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitList.java @@ -4,8 +4,6 @@ import com.google.gson.annotations.SerializedName; -import org.json.JSONObject; - import java.util.ArrayList; import java.util.Date; import java.util.Hashtable; diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitListActivity.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitListActivity.java index 94facd8..1e0ccca 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitListActivity.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/HabitListActivity.java @@ -1,9 +1,10 @@ package comjianzhaojohnhabit_rabbit.httpsgithub.habit_rabbit; import android.app.AlertDialog; +import android.app.ProgressDialog; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; +import android.media.MediaPlayer; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.FloatingActionButton; @@ -17,7 +18,12 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; + + +import android.widget.Button; import android.widget.ImageView; +import android.widget.ProgressBar; + import android.widget.TextView; import com.android.volley.Request; @@ -25,7 +31,6 @@ import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.StringRequest; -import com.android.volley.toolbox.Volley; import org.json.JSONException; import org.json.JSONObject; @@ -35,8 +40,6 @@ import java.util.List; import java.util.Map; -import static android.app.PendingIntent.getActivity; -import static android.support.v4.app.NavUtils.navigateUpFromSameTask; /** * An activity representing a list of Habits. This activity @@ -53,11 +56,13 @@ public class HabitListActivity extends AppCompatActivity { * device. */ private boolean mTwoPane; + protected static RecyclerView recyclerView; protected static RecyclerView.Adapter adapter; /** * Called when the activity is starting. * generate the view for this page + * * @param savedInstanceState If the activity is being re-initialized after previously being shut down then this Bundle contains the data it most recently supplied in onSaveInstanceState(Bundle). Note: Otherwise it is null. */ @Override @@ -70,30 +75,16 @@ protected void onCreate(Bundle savedInstanceState) { toolbar.setTitle(getTitle()); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); - /*fab.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } - }); - */ + final MediaPlayer mp = MediaPlayer.create(this, R.raw.button); // jump to newHabitActivity in responding to click the fab - fab.setOnClickListener(new View.OnClickListener(){ + fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + mp.start(); startActivity(new Intent(HabitListActivity.this, AddHabitActivity.class)); } }); - /* FloatingActionButton fab2 = (FloatingActionButton) findViewById(R.id.fab_agenda); - fab2.setOnClickListener(new View.OnClickListener(){ - @Override - public void onClick(View v) { - startActivity(new Intent(HabitListActivity.this, CalendarActivity.class)); - } - }); -*/ // Show the Up button in the action bar. ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { @@ -108,13 +99,14 @@ public void onClick(View v) { mTwoPane = true; } - View recyclerView = findViewById(R.id.habit_list); + recyclerView = findViewById(R.id.habit_list); assert recyclerView != null; setupRecyclerView((RecyclerView) recyclerView); } /** * Initialize the contents of the Activity's standard options menu. You should place your menu items in to menu. + * * @param menu-The options menu in which you place your items. * @return You must return true for the menu to be displayed; if you return false it will not be shown. */ @@ -126,7 +118,8 @@ public boolean onCreateOptionsMenu(Menu menu) { } /** - *This hook is called whenever an item in your options menu is selected. + * This hook is called whenever an item in your options menu is selected. + * * @param item-The menu item that was selected. * @return boolean Return false to allow normal menu processing to proceed, true to consume it here. */ @@ -138,26 +131,31 @@ public boolean onOptionsItemSelected(MenuItem item) { case R.id.nav_Profile: startActivity(new Intent(HabitListActivity.this, ProfileActivity.class)); break; - case R.id.nav_agenda: + case R.id.nav_agenda: startActivity(new Intent(HabitListActivity.this, CalendarActivity.class)); break; - case R.id.nav_logout: - try{ + case R.id.nav_aboutus: + startActivity(new Intent(HabitListActivity.this, AboutusActivity.class)); + break; + + case R.id.nav_logout: + try { // getApplicationContext().deleteFile("autionloginfile"); File autologin = getApplicationContext().getFileStreamPath("autionloginfile"); autologin.delete(); // clear and delete data file, then logout SharedPref.clearAll(HabitListActivity.this); String fileName = SharedPref.FILE_NAME; - File file= new File(this.getFilesDir().getParent()+"/shared_prefs/"+fileName+".xml"); + File file = new File(this.getFilesDir().getParent() + "/shared_prefs/" + fileName + ".xml"); file.delete(); Intent intent = new Intent(this, LoginActivity.class); intent.setFlags(intent.FLAG_ACTIVITY_NEW_TASK | intent.FLAG_ACTIVITY_CLEAR_TOP | intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(intent); - }catch(Exception e){} + } catch (Exception e) { + } break; - case R.id.nav_habits: + case R.id.nav_habits: // startActivity(new Intent(HabitListActivity.this, HabitListActivity.class)); break; default: @@ -206,15 +204,16 @@ public void onClick(View view) { }; //onLongClickListener - private final View.OnLongClickListener mOnLongClickListener = v -> { + private final View.OnLongClickListener mOnLongClickListener = v -> { // respond the delete button with a dialog box final Context context = v.getContext(); final Habit currentHabit = (Habit) v.getTag(); AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle("Edit Habit") - .setMessage("Do you want to delete this habit?") + builder.setTitle("Delete Habit") + .setMessage("Do you want to remove this habit?\nThe bunny will be upset...") .setNegativeButton("NO", null) .setPositiveButton("YES", (dialog, which) -> deleteHabitRequest(context, currentHabit)) + .setIcon(R.drawable.ic_delete_forever_black_24dp) .create() .show(); return true; @@ -230,8 +229,9 @@ public void onClick(View view) { } /** - *Called when RecyclerView needs a new RecyclerView.ViewHolder of the given type to represent an item. - * @param parent The ViewGroup into which the new View will be added after it is bound to an adapter position. + * Called when RecyclerView needs a new RecyclerView.ViewHolder of the given type to represent an item. + * + * @param parent The ViewGroup into which the new View will be added after it is bound to an adapter position. * @param viewType The view type of the new View. * @return A new ViewHolder that holds a View of the given view type. */ @@ -244,7 +244,8 @@ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { /** * Called by RecyclerView to display the data at the specified position. This method should update the contents of the itemView to reflect the item at the given position. - * @param holder-The ViewHolder which should be updated to represent the contents of the item at the given position in the data set. + * + * @param holder-The ViewHolder which should be updated to represent the contents of the item at the given position in the data set. * @param position-The position of the item within the adapter's data set. */ @Override @@ -254,40 +255,36 @@ public void onBindViewHolder(final ViewHolder holder, final int position) { final Habit currentHabit = HabitList.HABITS_list.get(position); // holder.mIdView.setText(mValues.get(position).getHabitID()+""); - holder.mIdView.setText(position+1+""); + holder.mIdView.setText(position + 1 + ""); holder.mContentView.setText(mValues.get(position).getName()); holder.itemView.setTag(mValues.get(position)); holder.itemView.setOnClickListener(mOnClickListener); holder.itemView.setOnLongClickListener(mOnLongClickListener); - holder.mDeleteImg.setTag(mValues.get(currentPosition)); - holder.mDeleteImg.setOnClickListener(v -> { + holder.mIdView.setTag(mValues.get(currentPosition)); + holder.mIdView.setOnClickListener(v -> { // respond the delete button with a dialog box AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle("Edit Habit") - .setMessage("Do you want to delete this habit?") - .setNegativeButton("NO", null) - .setPositiveButton("YES", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - deleteHabitRequest(context, currentHabit); - } - }) - .create() - .show(); + builder.setTitle("Delete Habit") + .setMessage("Do you want to remove this habit?\nThe bunny will be upset...") + .setNegativeButton("NO", null) + .setPositiveButton("YES", (dialog, which) -> deleteHabitRequest(context, currentHabit)) + .setIcon(R.drawable.ic_delete_forever_black_24dp) + .create() + .show(); }); } //deleted the database private void deleteHabit(Context mContext, Habit habit) { + int currentPosition = HabitList.HABITS_list.indexOf(habit); // delete habit locally SharedPref.deleteHabit(mContext, habit); HabitList.deleteHabit(habit); - int currentPosition = HabitList.HABITS_list.indexOf(habit); notifyItemRemoved(currentPosition); if (currentPosition != mValues.size()) { - notifyItemRangeChanged(currentPosition, mValues.size()-currentPosition); + notifyItemRangeChanged(currentPosition, mValues.size() - currentPosition); } } @@ -298,9 +295,14 @@ public int getItemCount() { //update the deletion to the database private void deleteHabitRequest(final Context context, final Habit habit) { + ProgressDialog progress = new ProgressDialog(context); + progress.setProgressStyle(ProgressDialog.STYLE_SPINNER); + progress.setMessage("Removing the habit: " + habit.getName()); + progress.show(); + // get params final String username = SharedPref.getUser(context); - final String habit_id = habit.getHabitID()+""; + final String habit_id = habit.getHabitID() + ""; // send delete habit request RequestQueue queue = VolleySingleton.getInstance(context) .getRequestQueue(context); @@ -308,9 +310,10 @@ private void deleteHabitRequest(final Context context, final Habit habit) { // request server to add this habit to database StringRequest loginReq = new StringRequest(Request.Method.POST, add_habit_url, - new Response.Listener(){ + new Response.Listener() { @Override public void onResponse(String response) { + progress.dismiss(); try { // parse the response JSONObject jsonRes = new JSONObject(response); @@ -318,22 +321,14 @@ public void onResponse(String response) { if (success) { deleteHabit(context, habit); - + Snackbar.make(recyclerView, "Deleted habit " + habit.getName(), Snackbar.LENGTH_SHORT) + .show(); } else { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle("Delete Habit") - .setMessage("Delete habit failed!") - .setNegativeButton("Retry", null) - .setPositiveButton("OK", null) - .create() + Snackbar.make(recyclerView, "Failed on deleting habit " + habit.getName(), Snackbar.LENGTH_SHORT) .show(); } } catch (JSONException e) { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle("Response error") - .setMessage(e.toString()) - .setNegativeButton("OK", null) - .create() + Snackbar.make(recyclerView, "Response Error: " + e.toString(), Snackbar.LENGTH_SHORT) .show(); e.printStackTrace(); } @@ -341,11 +336,8 @@ public void onResponse(String response) { }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle("Volley Error") - .setMessage(error.toString()) - .setNegativeButton("OK", null) - .create() + progress.dismiss(); + Snackbar.make(recyclerView, "Volley Error! Please check your connection or try again later.", Snackbar.LENGTH_SHORT) .show(); } }) { @@ -366,13 +358,13 @@ protected Map getParams() { class ViewHolder extends RecyclerView.ViewHolder { final TextView mIdView; final TextView mContentView; - final ImageView mDeleteImg; +// final ImageView mDeleteImg; ViewHolder(View view) { super(view); mIdView = (TextView) view.findViewById(R.id.id_text); mContentView = (TextView) view.findViewById(R.id.content); - mDeleteImg = (ImageView) view.findViewById(R.id.delete_image); +// mDeleteImg = (ImageView) view.findViewById(R.id.delete_image); } } diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/LoginActivity.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/LoginActivity.java index cb2f026..a813ac8 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/LoginActivity.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/LoginActivity.java @@ -96,7 +96,7 @@ protected void onCreate(Bundle savedInstanceState) { catch(Exception e){ } - + /* if (!HabitCheckReciever.isTimerOn()){ Context context = getApplicationContext(); HabitCheckReciever.setShared_context(context); @@ -122,7 +122,7 @@ protected void onCreate(Bundle savedInstanceState) { if (lastCheckedDay != Calendar.getInstance().get(Calendar.DAY_OF_YEAR)) { HabitCheckReciever.checkHabits(); } - + */ @@ -266,6 +266,7 @@ private void requestLogin(String email, String password) { new Response.Listener(){ @Override public void onResponse(String response) { + showProgress(false); try { // parse the response @@ -299,17 +300,13 @@ public void onResponse(String response) { finish(); } else { - showProgress(false); +// showProgress(false); mPasswordView.setError("Email and password do not match"); mPasswordView.requestFocus(); } } catch (JSONException e) { - showProgress(false); - AlertDialog.Builder builder = new AlertDialog.Builder(LoginActivity.this); - builder.setTitle("Response error") - .setMessage(e.toString()) - .setNegativeButton("OK", null) - .create() +// showProgress(false); + Snackbar.make(mEmailView, "Response Error. Please try again later.", Snackbar.LENGTH_SHORT) .show(); e.printStackTrace(); } @@ -318,11 +315,7 @@ public void onResponse(String response) { @Override public void onErrorResponse(VolleyError error) { showProgress(false); - AlertDialog.Builder builder = new AlertDialog.Builder(LoginActivity.this); - builder.setMessage(error.toString()) - .setTitle("Volley Error") - .setNegativeButton("OK", null) - .create() + Snackbar.make(mEmailView, "Volley Error! Please check your connection or try again later.", Snackbar.LENGTH_SHORT) .show(); } }) { @@ -433,7 +426,7 @@ private void addEmailsToAutoComplete(List emailAddressCollection) { // go to register page public void goRegister(View view) { Intent intent = new Intent(this, RegisterActivity.class); -// getIntent().putExtra("email", mEmailView.getText().toString()); + intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); startActivity(intent); } diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/MainActivity.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/MainActivity.java index 839df0d..31addc6 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/MainActivity.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/MainActivity.java @@ -1,6 +1,9 @@ package comjianzhaojohnhabit_rabbit.httpsgithub.habit_rabbit; +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.Context; import android.content.Intent; import android.support.design.widget.NavigationView; import android.support.v4.widget.DrawerLayout; @@ -11,6 +14,8 @@ import android.view.MenuItem; import android.view.View; import android.widget.ImageButton; +import android.widget.TextView; +import android.widget.Toast; import java.io.File; import java.text.SimpleDateFormat; @@ -43,8 +48,19 @@ protected void onCreate(Bundle savedInstanceState) { navigationView.setNavigationItemSelectedListener(this); getSupportActionBar().setDisplayHomeAsUpEnabled(true); + Intent intent = new Intent(this, HabitCheckReciever.class); + PendingIntent pendingIntent = PendingIntent.getBroadcast(this,0,intent,0); + AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); + alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent); + NavigationView navView = (NavigationView) findViewById(R.id.nav_view); + navView.setNavigationItemSelectedListener(this); + View header=navigationView.getHeaderView(0); + TextView username = header.findViewById(R.id.user); + username.setText(HabitList.getUserName()); + + Toast.makeText(MainActivity.this, "Welcome! The bunny is missing you!", Toast.LENGTH_SHORT).show(); } public static boolean isRabbitAlive() { @@ -109,27 +125,32 @@ public static boolean isRabbitAlive() { } +/* - /** + */ +/** *Initialize the contents of the Activity's standard options menu * * @param menu-The options menu in which you place your items * @return You must return true for the menu to be displayed; if you return false it will not be shown. - */ + *//* + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.navigation_menu, menu); return true; } - /** + */ +/** *This hook is called whenever an item in your options menu is selected. * You can use this method for any items for which you would like to do processing without those other facilities. * * @param item- The menu item that was selected. * @return boolean Return false to allow normal menu processing to proceed, true to consume it here. - */ + *//* + @Override public boolean onOptionsItemSelected(MenuItem item) { if (mToggle.onOptionsItemSelected(item)) { @@ -166,6 +187,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } return super.onOptionsItemSelected(item); } +*/ /** * same as above function but this one is for naviagation bar @@ -183,6 +205,10 @@ public boolean onNavigationItemSelected(MenuItem item) { case R.id.nav_habits: startActivity(new Intent(MainActivity.this, HabitListActivity.class)); break; + case R.id.nav_aboutus: + startActivity(new Intent(MainActivity.this, AboutusActivity.class)); + break; + case R.id.nav_logout: try{ File autologin = getApplicationContext().getFileStreamPath("autionloginfile"); @@ -191,7 +217,10 @@ public boolean onNavigationItemSelected(MenuItem item) { String fileName = SharedPref.FILE_NAME; File file= new File(this.getFilesDir().getParent()+"/shared_prefs/"+fileName+".xml"); file.delete(); - startActivity(new Intent(MainActivity.this, LoginActivity.class)); + //open the login page + Intent intent = new Intent(this, LoginActivity.class); + intent.setFlags(intent.FLAG_ACTIVITY_NEW_TASK | intent.FLAG_ACTIVITY_CLEAR_TOP | intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); }catch(Exception e){} break; default: diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/NotificationHelper.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/NotificationHelper.java index 25b66a1..51e6c42 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/NotificationHelper.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/NotificationHelper.java @@ -3,8 +3,10 @@ import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; +import android.app.PendingIntent; import android.content.Context; import android.content.ContextWrapper; +import android.content.Intent; import android.graphics.Color; import android.os.Build; import android.util.Log; @@ -42,11 +44,15 @@ public NotificationManager getManager(){ return manager; } public void sendNotification(String message){ + Intent intent = new Intent(context,CalendarActivity.class); + PendingIntent pendingIntent = PendingIntent.getActivity(context,0,intent,0); + Notification.Builder notification = new Notification.Builder(context) .setAutoCancel(false) .setWhen(System.currentTimeMillis()+ 1000) .setContentTitle("How did you do today?") .setContentText(message) + .setContentIntent(pendingIntent) .setSmallIcon(R.drawable.icon); if (Build.VERSION.SDK_INT > 25 ) { notification.setChannelId(CHANNEL_ID); @@ -56,4 +62,4 @@ public void sendNotification(String message){ notificationManager.notify(100,notification.build()); } -} +} \ No newline at end of file diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/ProfileActivity.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/ProfileActivity.java index 46cbec0..3001c08 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/ProfileActivity.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/ProfileActivity.java @@ -8,11 +8,14 @@ import android.view.MenuItem; import android.view.View; import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; import java.io.File; public class ProfileActivity extends AppCompatActivity { public Button editproflebutton; + TextView email; /** * Called when the activity is starting. @@ -23,6 +26,8 @@ public class ProfileActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_profile); + email = (TextView) findViewById(R.id.username); + email.setText(HabitList.getUserName()); } /** @@ -55,6 +60,10 @@ public boolean onOptionsItemSelected(MenuItem item) { case R.id.nav_agenda: startActivity(new Intent(ProfileActivity.this, CalendarActivity.class)); break; + case R.id.nav_aboutus: + startActivity(new Intent(ProfileActivity.this, AboutusActivity.class)); + break; + case R.id.nav_logout: try{ // getApplicationContext().deleteFile("autionloginfile"); @@ -85,16 +94,16 @@ public void Set_onClick(View view) { startActivity(intent); } //another clickListener - public void editprofile(View view){ - editproflebutton = (Button) findViewById(R.id.EditProfileButton); - editproflebutton.setOnClickListener(new View.OnClickListener(){ - - - @Override - public void onClick(View v) { - Intent showEditProfile = new Intent(ProfileActivity.this, EditProfileActivity.class); - startActivity(showEditProfile); - } - }); - } +// public void editprofile(View view){ +// editproflebutton = (Button) findViewById(R.id.EditProfileButton); +// editproflebutton.setOnClickListener(new View.OnClickListener(){ +// +// +// @Override +// public void onClick(View v) { +// Intent showEditProfile = new Intent(ProfileActivity.this, EditProfileActivity.class); +// startActivity(showEditProfile); +// } +// }); +// } } diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/RabbitReview.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/RabbitReview.java index 2d7cf7f..30f1903 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/RabbitReview.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/RabbitReview.java @@ -1,12 +1,16 @@ package comjianzhaojohnhabit_rabbit.httpsgithub.habit_rabbit; import android.content.Context; +import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; +import android.support.v4.view.GestureDetectorCompat; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; +import android.view.GestureDetector; +import android.view.MotionEvent; import android.view.View; import android.view.animation.*; import android.widget.ImageView; @@ -14,6 +18,7 @@ public class RabbitReview extends AppCompatActivity { Animation animShake; + private GestureDetectorCompat detector; /** * Called when the activity is starting. @@ -23,10 +28,7 @@ public class RabbitReview extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - - setContentView(R.layout.activity_rabbit_view_); - - + setContentView(R.layout.activity_rabbit_view_); } //shake the rabbit when you click opn the rabbit @@ -35,5 +37,4 @@ public void shake(View view) { Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.shake); image.startAnimation(animation); } - } diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/RegisterActivity.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/RegisterActivity.java index 05c105f..5a22817 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/RegisterActivity.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/RegisterActivity.java @@ -1,9 +1,13 @@ package comjianzhaojohnhabit_rabbit.httpsgithub.habit_rabbit; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; +import android.os.Build; import android.os.Bundle; import android.support.design.widget.Snackbar; import android.text.TextUtils; @@ -33,6 +37,8 @@ public class RegisterActivity extends Activity { private EditText mEmailView; private EditText mPassword_1View; private EditText mPassword_2View; + private View mProgressView; + private View mRegisterView; /** * Called when the activity is starting. @@ -47,6 +53,8 @@ protected void onCreate(Bundle savedInstanceState) { mEmailView = (EditText) findViewById(R.id.email); mPassword_1View = (EditText) findViewById(R.id.password_1); mPassword_2View = (EditText) findViewById(R.id.password2); + mProgressView = (View) findViewById(R.id.register_progress); + mRegisterView = (View) findViewById(R.id.register_form); //cretae a editorActionListener mPassword_2View.setOnEditorActionListener(new TextView.OnEditorActionListener() { @@ -89,7 +97,7 @@ private void attemptRegister() { mPassword_1View.setError(getString(R.string.error_field_required)); focusView = mPassword_1View; cancel = true; - } else if (!isPasswordValid(password1)) { + } else if (!isPasswordValid(password1,email)) { mPassword_1View.setError(getString(R.string.error_invalid_password)); focusView = mPassword_1View; cancel = true; @@ -120,6 +128,7 @@ private void attemptRegister() { } else { // Show a progress spinner, and kick off a background task to // perform the user login attempt. + showProgress(true); requestRegister(email, password1); } } @@ -139,12 +148,15 @@ private void requestRegister(String email, String password) { new Response.Listener(){ @Override public void onResponse(String response) { + showProgress(false); try { // parse the response JSONObject jsonRes = new JSONObject(response); Boolean success = jsonRes.getBoolean("success"); if (success) { + Snackbar.make(mEmailView, "Registration Succeed!", Snackbar.LENGTH_SHORT) + .show(); // jump to next page startActivity(new Intent(RegisterActivity.this, LoginActivity.class)); finish(); @@ -155,11 +167,7 @@ public void onResponse(String response) { } } catch (JSONException e) { //display the error message when catch a exception - AlertDialog.Builder builder = new AlertDialog.Builder(RegisterActivity.this); - builder.setMessage(e.toString()) - .setTitle("Response error") - .setNegativeButton("", null) - .create() + Snackbar.make(mEmailView, "Response Error: " + e.toString(), Snackbar.LENGTH_SHORT) .show(); e.printStackTrace(); } @@ -167,11 +175,8 @@ public void onResponse(String response) { }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { - AlertDialog.Builder builder = new AlertDialog.Builder(RegisterActivity.this); - builder.setMessage(error.toString()) - .setTitle("Volley Error") - .setNegativeButton("OK", null) - .create() + showProgress(false); + Snackbar.make(mEmailView, "Volley Error! Please check your connection or try again later.", Snackbar.LENGTH_SHORT) .show(); } }) { @@ -202,14 +207,76 @@ private boolean isEmailValid(String email) { * @param password- your passowrd * @return true if passwrods is valid, false otherwise */ - private boolean isPasswordValid(String password) { - //TODO: Replace this with your own logic - return password.length() > 3; + private boolean isPasswordValid(String password, String email) { + + boolean len=false; + boolean uppercase = false; + boolean lowercase = false; + boolean specialcase = false; + //boolean user = false; + if(password.equals(email)){ + //user = true; + return false; + } + int pass_length = password.length(); + if(pass_length > 8) len=true; + for(int i = 0; i< pass_length; i++){ + + if(password.charAt(i) >= 65 && password.charAt(i) <=90) { + uppercase = true; + } + else if(password.charAt(i) >= 97 && password.charAt(i) <=122) { + lowercase = true; + } + else if((password.charAt(i) >=33 && password.charAt(i) <= 47) || (password.charAt(i) >=58 && password.charAt(i) <= 64) || (password.charAt(i) >=91 && password.charAt(i) <= 97) || (password.charAt(i) >=123 && password.charAt(i) <= 126)) + { + specialcase = true; + } + + } + return (len && uppercase && lowercase && specialcase); } //clickListener, which open the login page when clicked public void goLogin(View view) { Intent intent = new Intent(this, LoginActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); startActivity(intent); } + + /** + * Shows the progress UI and hides the login form. + */ + @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) + private void showProgress(final boolean show) { + // On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow + // for very easy animations. If available, use these APIs to fade-in + // the progress spinner. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { + int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime); + + mRegisterView.setVisibility(show ? View.GONE : View.VISIBLE); + mRegisterView.animate().setDuration(shortAnimTime).alpha( + show ? 0 : 1).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mRegisterView.setVisibility(show ? View.GONE : View.VISIBLE); + } + }); + + mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); + mProgressView.animate().setDuration(shortAnimTime).alpha( + show ? 1 : 0).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); + } + }); + } else { + // The ViewPropertyAnimator APIs are not available, so simply show + // and hide the relevant UI components. + mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); + mRegisterView.setVisibility(show ? View.GONE : View.VISIBLE); + } + } } diff --git a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/SharedPref.java b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/SharedPref.java index d98294c..4cc37c8 100644 --- a/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/SharedPref.java +++ b/app/src/main/java/comjianzhaojohnhabit_rabbit/httpsgithub/habit_rabbit/SharedPref.java @@ -230,7 +230,6 @@ public static String getRecordsString(Context mContext) { return res; } - //use for testing purposes public static void saveRecords(Context mContext, JSONArray jsonArray) { SharedPreferences mPref = mContext.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = mPref.edit(); diff --git a/app/src/main/res/drawable/github.png b/app/src/main/res/drawable/github.png new file mode 100644 index 0000000..36d820a Binary files /dev/null and b/app/src/main/res/drawable/github.png differ diff --git a/app/src/main/res/drawable/grass.png b/app/src/main/res/drawable/grass.png new file mode 100644 index 0000000..3e5ae1f Binary files /dev/null and b/app/src/main/res/drawable/grass.png differ diff --git a/app/src/main/res/drawable/ic_tag_faces_black_24dp.xml b/app/src/main/res/drawable/ic_tag_faces_black_24dp.xml new file mode 100644 index 0000000..43d5552 --- /dev/null +++ b/app/src/main/res/drawable/ic_tag_faces_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/mushroom.png b/app/src/main/res/drawable/mushroom.png new file mode 100644 index 0000000..a494ac3 Binary files /dev/null and b/app/src/main/res/drawable/mushroom.png differ diff --git a/app/src/main/res/drawable/rabbit_balloons.png b/app/src/main/res/drawable/rabbit_balloons.png new file mode 100644 index 0000000..69554d0 Binary files /dev/null and b/app/src/main/res/drawable/rabbit_balloons.png differ diff --git a/app/src/main/res/drawable/rabbit_login.png b/app/src/main/res/drawable/rabbit_login.png index 9765499..d4e9f8f 100644 Binary files a/app/src/main/res/drawable/rabbit_login.png and b/app/src/main/res/drawable/rabbit_login.png differ diff --git a/app/src/main/res/drawable/rabbit_water.png b/app/src/main/res/drawable/rabbit_water.png new file mode 100644 index 0000000..c04f23d Binary files /dev/null and b/app/src/main/res/drawable/rabbit_water.png differ diff --git a/app/src/main/res/drawable/rabbithouse.png b/app/src/main/res/drawable/rabbithouse.png index db80553..8665aef 100644 Binary files a/app/src/main/res/drawable/rabbithouse.png and b/app/src/main/res/drawable/rabbithouse.png differ diff --git a/app/src/main/res/drawable/rabbithouse2.jpg b/app/src/main/res/drawable/rabbithouse2.jpg index 697243e..444bfc0 100644 Binary files a/app/src/main/res/drawable/rabbithouse2.jpg and b/app/src/main/res/drawable/rabbithouse2.jpg differ diff --git a/app/src/main/res/drawable/rabbits_cheers.png b/app/src/main/res/drawable/rabbits_cheers.png new file mode 100644 index 0000000..b7cec92 Binary files /dev/null and b/app/src/main/res/drawable/rabbits_cheers.png differ diff --git a/app/src/main/res/layout/activity_aboutus2.xml b/app/src/main/res/layout/activity_aboutus2.xml new file mode 100644 index 0000000..1dcb532 --- /dev/null +++ b/app/src/main/res/layout/activity_aboutus2.xml @@ -0,0 +1,34 @@ + + + + + +