diff --git a/Lambdas/Lists/List/src/List.java b/Lambdas/Lists/List/src/List.java index 83b8274..fd73808 100644 --- a/Lambdas/Lists/List/src/List.java +++ b/Lambdas/Lists/List/src/List.java @@ -3,39 +3,48 @@ import java.sql.SQLException; import java.util.ArrayList; public class List { - Integer itemID; + Integer listID; String name; String owner; long lastUpdated; ArrayList entries; boolean shared; + Integer uiPosition; - public List(ResultSet listRow, boolean shared) throws SQLException { - itemID = listRow.getInt("listID"); + public List(ResultSet listRow, boolean shared, Integer uiPosition) throws SQLException { + listID = listRow.getInt("listID"); name = listRow.getString("name"); owner = listRow.getString("owner"); lastUpdated = listRow.getTimestamp("lastUpdated").toInstant().toEpochMilli(); entries = new ArrayList<>(); this.shared = shared; + this.uiPosition = uiPosition; } @Override public String toString() { return "List{" + - "itemID=" + itemID + + "listID=" + listID + ", name='" + name + '\'' + ", owner='" + owner + '\'' + ", lastUpdated=" + lastUpdated + ", entries=" + entries + + ", shared=" + shared + + ", uiPosition=" + uiPosition + '}'; } - public Integer getItemID() { - return itemID; + + public ItemEntry[] getEntries() { + return entries.toArray(new ItemEntry[entries.size()]); } - public void setItemID(Integer itemID) { - this.itemID = itemID; + public Integer getListID() { + return listID; + } + + public void setListID(Integer listID) { + this.listID = listID; } public String getName() { @@ -70,7 +79,14 @@ public class List { this.shared = shared; } - public ItemEntry[] getEntries() { + public Integer getUiPosition() { + return uiPosition; + } + + public void setUiPosition(Integer uiPosition) { + this.uiPosition = uiPosition; + + public ItemEntry[] getEntries() { return entries.toArray(new ItemEntry[entries.size()]); } diff --git a/Lambdas/Lists/List/src/ListAdder.java b/Lambdas/Lists/List/src/ListAdder.java index b94af67..18a7d7e 100644 --- a/Lambdas/Lists/List/src/ListAdder.java +++ b/Lambdas/Lists/List/src/ListAdder.java @@ -9,7 +9,8 @@ public class ListAdder implements CallHandler { private String cognitoID; private final String LIST_CREATE = "INSERT INTO List (name, owner, lastUpdated) VALUES (?, ?, ?);"; - private final String LIST_ACCESS_GRANT = "INSERT INTO ListSharee(listID, userID, permissionLevel) VALUES(?, ?, ?);"; + private final String LIST_ACCESS_GRANT = "INSERT INTO ListSharee(listID, userID, permissionLevel, uiPosition) VALUES(?, ?, ?, ?);"; + private final String UI_POSITION_CHECK = "SELECT Max(uiPosition) as maxUIPosition FROM ListSharee WHERE userID = ?;"; public ListAdder(Connection connection, String cognitoID) { this.connection = connection; @@ -17,9 +18,17 @@ public class ListAdder implements CallHandler { } public Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException { - PreparedStatement statement = connection.prepareStatement(LIST_CREATE, Statement.RETURN_GENERATED_KEYS); - String listName = bodyMap.get("name").toString();//Needs safe checking + + PreparedStatement uiPositionCheck = connection.prepareStatement(UI_POSITION_CHECK); + uiPositionCheck.setString(1, cognitoID); + ResultSet uiPositionCheckRS = uiPositionCheck.executeQuery(); + int nextPosition = 1; + if (uiPositionCheckRS.next()) { + nextPosition = uiPositionCheckRS.getInt("maxUIPosition") + 1; + } + + PreparedStatement statement = connection.prepareStatement(LIST_CREATE, Statement.RETURN_GENERATED_KEYS); statement.setString(1, listName); statement.setString(2, cognitoID); statement.setTimestamp(3, Timestamp.from(Instant.now())); @@ -32,6 +41,7 @@ public class ListAdder implements CallHandler { accessGrant.setInt(1, newID); accessGrant.setString(2, cognitoID); accessGrant.setInt(3, ListPermissions.getAll()); + accessGrant.setInt(4, nextPosition); System.out.println(accessGrant); accessGrant.executeUpdate(); connection.commit(); diff --git a/Lambdas/Lists/List/src/ListGetter.java b/Lambdas/Lists/List/src/ListGetter.java index 982a948..e29267c 100644 --- a/Lambdas/Lists/List/src/ListGetter.java +++ b/Lambdas/Lists/List/src/ListGetter.java @@ -12,7 +12,7 @@ public class ListGetter implements CallHandler{ private final String cognitoID; private final String GET_LIST = "SELECT * FROM List WHERE listID = ?;"; - private final String GET_LISTS = "SELECT listID FROM ListSharee WHERE userID = ?;"; + private final String GET_LISTS = "SELECT listID FROM ListSharee WHERE userID = ? ORDER BY uiPosition;"; private final String SHARE_CHECK = "SELECT * FROM ListSharee WHERE listID = ?;"; private final String GET_ENTRIES = "SELECT * FROM ListProduct WHERE listID = ?;"; @@ -42,6 +42,7 @@ public class ListGetter implements CallHandler{ ResultSet accessResults = checkAccess.executeQuery(); int sharees = 0; boolean verifiedAccess = false; + int uiPosition = 1; while ((sharees < 2 && accessResults.next()) || !verifiedAccess) { int permissionLevel = accessResults.getInt("permissionLevel"); if (accessResults.getString("userID").equals(cognitoID)) { @@ -49,6 +50,7 @@ public class ListGetter implements CallHandler{ if (!ListPermissions.hasPermission(permissionLevel, "Read")) { throw new AccessControlException("User " + cognitoID + " does not have permission to read list " + id); } + uiPosition = accessResults.getInt("uiPosition"); } if (permissionLevel > 0) { sharees++; @@ -64,7 +66,7 @@ public class ListGetter implements CallHandler{ ResultSet getListResults = getList.executeQuery(); getListResults.first(); System.out.println(getListResults); - List retrievedList = new List(getListResults, shared); + List retrievedList = new List(getListResults, shared, uiPosition); System.out.println(retrievedList); PreparedStatement getListEntries = connection.prepareStatement(GET_ENTRIES); getListEntries.setInt(1, id); diff --git a/Lambdas/Lists/List/src/ListPUT.java b/Lambdas/Lists/List/src/ListPUT.java new file mode 100644 index 0000000..a1ecb06 --- /dev/null +++ b/Lambdas/Lists/List/src/ListPUT.java @@ -0,0 +1,11 @@ +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import java.util.Map; + +public class ListPUT implements RequestHandler, Object> { + + public Object handleRequest(Map inputMap, Context unfilled) { + return BasicHandler.handleRequest(inputMap, unfilled, ListPutter.class); + } +} diff --git a/Lambdas/Lists/List/src/ListPutter.java b/Lambdas/Lists/List/src/ListPutter.java new file mode 100644 index 0000000..4909a7c --- /dev/null +++ b/Lambdas/Lists/List/src/ListPutter.java @@ -0,0 +1,44 @@ +import java.security.AccessControlException; +import java.sql.*; +import java.time.Instant; +import java.util.HashMap; +import java.util.Map; + +public class ListPutter implements CallHandler { + private final Connection connection; + private final String cognitoID; + + private final String ACCESS_CHECK = "SELECT * from ListSharee WHERE userID = ? and listID = ?;"; + private final String LIST_RENAME = "UPDATE List SET name = ?, lastUpdated = ? WHERE listID = ?;"; + + public ListPutter(Connection connection, String cognitoID) { + this.connection = connection; + this.cognitoID = cognitoID; + } + + @Override + public Object conductAction(Map bodyMap, HashMap queryMap, String cognitoID) throws SQLException { + Integer listID = Integer.parseInt(bodyMap.get("listID").toString()); + + PreparedStatement accessCheck = connection.prepareStatement(ACCESS_CHECK); + accessCheck.setString(1, cognitoID); + accessCheck.setInt(2, listID); + System.out.println(accessCheck); + ResultSet userLists = accessCheck.executeQuery(); + if (!userLists.next()) { + throw new AccessControlException("User does not have access to list"); + } else { + if (!ListPermissions.hasPermission(userLists.getInt("permissionLevel"), "Delete")) { + throw new AccessControlException("User " + cognitoID + " does not have permission to edit list " + listID); + } + } + PreparedStatement renameList = connection.prepareStatement(LIST_RENAME); + renameList.setString(1, bodyMap.get("name").toString()); + renameList.setTimestamp(2, Timestamp.from(Instant.now())); + renameList.setInt(3, listID); + System.out.println(renameList); + renameList.executeUpdate(); + connection.commit(); + return null; + } +} diff --git a/Lambdas/Lists/ListDuplicate/src/ListDuplicatePOST.java b/Lambdas/Lists/ListDuplicate/src/ListDuplicatePOST.java new file mode 100644 index 0000000..8c98d5a --- /dev/null +++ b/Lambdas/Lists/ListDuplicate/src/ListDuplicatePOST.java @@ -0,0 +1,11 @@ +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import java.util.Map; + +public class ListDuplicatePOST implements RequestHandler, Object>{ + + public Object handleRequest(Map inputMap, Context unfilled) { + return BasicHandler.handleRequest(inputMap, unfilled, ListDuplicater.class); + } +} diff --git a/Lambdas/Lists/ListDuplicate/src/ListDuplicater.java b/Lambdas/Lists/ListDuplicate/src/ListDuplicater.java new file mode 100644 index 0000000..b80dea7 --- /dev/null +++ b/Lambdas/Lists/ListDuplicate/src/ListDuplicater.java @@ -0,0 +1,73 @@ +import com.amazonaws.services.lambda.AWSLambdaClientBuilder; +import com.amazonaws.services.lambda.model.InvokeRequest; +import com.amazonaws.services.lambda.model.InvokeResult; + +import java.security.AccessControlException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.InputMismatchException; +import java.util.Map; + +public class ListDuplicater implements CallHandler { + + private Connection connection; + private String cognitoID; + + private final String LIST_POPULATE = "INSERT INTO ListProduct(listID, productID, quantity, addedDate, purchased) SELECT ?, productID, quantity, addedDate, purchased FROM ListProduct WHERE listID = ?;"; + private final String ACCESS_CHECK = "SELECT * from ListSharee WHERE userID = ? and listID = ?;"; + + public ListDuplicater(Connection connection, String cognitoID) { + this.connection = connection; + this.cognitoID = cognitoID; + } + + public Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException { + String listName = bodyMap.get("name").toString();//Needs safe checking + Integer copyListID = (Integer) bodyMap.get("listID"); + + PreparedStatement accessCheck = connection.prepareStatement(ACCESS_CHECK); + accessCheck.setString(1, cognitoID); + accessCheck.setInt(2, copyListID); + ResultSet access = accessCheck.executeQuery(); + if (access.next()) { + if (!ListPermissions.hasPermission(access.getInt("permissionLevel"), "Read")) { + throw new AccessControlException("User " + cognitoID + " does not have write permissions for list " + copyListID); + } + } else { + throw new AccessControlException("User " + cognitoID + " does not have any permissions to access list " + copyListID); + } + + + InvokeRequest invokeRequest = new InvokeRequest(); + invokeRequest.setFunctionName("ListPOST"); + invokeRequest.setPayload("{" + + " \"body\": {" + + " \"name\": \"" + listName + "\"" + + " }," + + " \"params\": {" + + " \"querystring\": {" + + " }" + + " }," + + " \"context\": {" + + " \"sub\": \"" + cognitoID + "\"" + + " }" + + "}"); + System.out.println(invokeRequest); + InvokeResult listCreateResult = AWSLambdaClientBuilder.defaultClient().invoke(invokeRequest); + if (listCreateResult.getStatusCode() != 200) { + throw new InputMismatchException("Could not find specified user to share with"); + } + Integer newListID = Integer.parseInt(new String(listCreateResult.getPayload().array()).replace("\"", "")); + + PreparedStatement populateList = connection.prepareStatement(LIST_POPULATE); + populateList.setInt(1, newListID); + populateList.setInt(2, copyListID); + System.out.println(populateList); + populateList.executeUpdate(); + connection.commit(); + return newListID; + } +} diff --git a/Lambdas/Lists/ListReposition/src/ListRepositionActor.java b/Lambdas/Lists/ListReposition/src/ListRepositionActor.java new file mode 100644 index 0000000..a1d7517 --- /dev/null +++ b/Lambdas/Lists/ListReposition/src/ListRepositionActor.java @@ -0,0 +1,70 @@ +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +public class ListRepositionActor implements CallHandler { + + private Connection connection; + private String cognitoID; + + public ListRepositionActor(Connection connection, String cognitoID) { + this.connection = connection; + this.cognitoID = cognitoID; + } + + final private String GET_PRIOR_POSITION = "SELECT uiPosition FROM ListSharee WHERE userID = ? AND listID = ?;"; + final private String SET_NEW_POSITION = "UPDATE ListSharee SET uiPosition = ? WHERE userID = ? AND listID = ?;"; + final private String DECREMENT_HIGHER_POSITIONS = "UPDATE ListSharee SET uiPosition = uiPosition - 1 WHERE uiPosition > ? AND userID = ?;"; + final private String INCREMENT_GEQ_POSITIONS = "UPDATE ListSharee SET uiPosition = uiPosition + 1 WHERE uiPosition >= ? AND userID = ?;"; + + + public Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException { + Integer listID = (Integer) bodyMap.get("listID"); + Integer newPosition = (Integer) bodyMap.get("newPosition"); + + PreparedStatement getPriorPosition = connection.prepareStatement(GET_PRIOR_POSITION); + getPriorPosition.setString(1, cognitoID); + getPriorPosition.setInt(2, listID); + ResultSet priorPositionRS = getPriorPosition.executeQuery(); + if (!priorPositionRS.next()) { + throw new IllegalArgumentException("Bad listID for user"); + } + Integer priorPosition = priorPositionRS.getInt("uiPosition"); + + PreparedStatement openNewPosition = connection.prepareStatement(INCREMENT_GEQ_POSITIONS); + + if (newPosition.equals(priorPosition)) { + return null; + } + if (newPosition < priorPosition) { + openNewPosition.setInt(1, newPosition); + } else { + openNewPosition.setInt(1, newPosition + 1); + } + openNewPosition.setString(2, cognitoID); + System.out.println(openNewPosition); + openNewPosition.executeUpdate(); + + PreparedStatement fillPriorPosition = connection.prepareStatement(DECREMENT_HIGHER_POSITIONS); + fillPriorPosition.setInt(1, priorPosition); + fillPriorPosition.setString(2, cognitoID); + System.out.println(fillPriorPosition); + fillPriorPosition.executeUpdate(); + + + + PreparedStatement setNewPosition = connection.prepareStatement(SET_NEW_POSITION); + setNewPosition.setInt(1, newPosition); + setNewPosition.setString(2, cognitoID); + setNewPosition.setInt(3, listID); + System.out.println(setNewPosition); + setNewPosition.executeUpdate(); + + connection.commit(); + return null; + } + +} \ No newline at end of file diff --git a/Lambdas/Lists/ListReposition/src/ListRepositionPUT.java b/Lambdas/Lists/ListReposition/src/ListRepositionPUT.java new file mode 100644 index 0000000..20fc102 --- /dev/null +++ b/Lambdas/Lists/ListReposition/src/ListRepositionPUT.java @@ -0,0 +1,11 @@ +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import java.util.Map; + +public class ListRepositionPUT implements RequestHandler, Object> { + + public Object handleRequest(Map inputMap, Context unfilled) { + return BasicHandler.handleRequest(inputMap, unfilled, ListRepositionActor.class); + } +} diff --git a/Lambdas/Lists/ListShare/src/ListSharer.java b/Lambdas/Lists/ListShare/src/ListSharer.java index f55d337..a80d0d8 100644 --- a/Lambdas/Lists/ListShare/src/ListSharer.java +++ b/Lambdas/Lists/ListShare/src/ListSharer.java @@ -22,9 +22,9 @@ public class ListSharer implements CallHandler { } final private String CHECK_ACCESS = "SELECT * from ListSharee WHERE listID = ? AND userID = ?;"; + private final String UI_POSITION_CHECK = "SELECT Max(uiPosition) as maxUIPosition FROM ListSharee WHERE userID = ?;"; final private String SHARE_LIST = "INSERT INTO ListSharee(listID, userID, permissionLevel, uiPosition) VALUES(?, ?, ?, ?) ON DUPLICATE KEY UPDATE permissionLevel = ?;"; - public Object conductAction(Map bodyMap, HashMap queryString, String cognitoID) throws SQLException { PreparedStatement checkAccess = connection.prepareStatement(CHECK_ACCESS); Integer listID = Integer.parseInt(bodyMap.get("listID").toString()); @@ -63,12 +63,23 @@ public class ListSharer implements CallHandler { // throw new InputMismatchException("The specified user already has access"); // } + PreparedStatement uiPositionCheck = connection.prepareStatement(UI_POSITION_CHECK); + uiPositionCheck.setString(1, shareWithSub); + System.out.println(uiPositionCheck); + ResultSet uiPositionCheckRS = uiPositionCheck.executeQuery(); + int nextPosition = 1; + if (uiPositionCheckRS.next()) { + nextPosition = uiPositionCheckRS.getInt("maxUIPosition") + 1; + } + PreparedStatement shareList = connection.prepareStatement(SHARE_LIST); shareList.setInt(1, listID); shareList.setString(2, shareWithSub); Integer permissionLevel = Integer.parseInt(bodyMap.get("permissionLevel").toString()); shareList.setInt(3, permissionLevel); - shareList.setInt(4, permissionLevel); + shareList.setInt(4, nextPosition); + shareList.setInt(5, permissionLevel); + System.out.println(shareList); shareList.executeUpdate(); connection.commit(); return null; diff --git a/Listify/app/src/main/java/com/example/listify/CreateListAddDialogFragment.java b/Listify/app/src/main/java/com/example/listify/CreateListAddDialogFragment.java index 4d93360..9b8e470 100644 --- a/Listify/app/src/main/java/com/example/listify/CreateListAddDialogFragment.java +++ b/Listify/app/src/main/java/com/example/listify/CreateListAddDialogFragment.java @@ -62,8 +62,12 @@ public class CreateListAddDialogFragment extends DialogFragment { btnMinus.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + if (etQuantity.getText().toString().equals("")) { + etQuantity.setText("1"); + } + int curQauntity = Integer.parseInt(etQuantity.getText().toString()); - if (curQauntity > 0) { + if (curQauntity > 1) { curQauntity--; etQuantity.setText(String.format("%d", curQauntity)); } @@ -74,6 +78,10 @@ public class CreateListAddDialogFragment extends DialogFragment { btnPlus.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + if (etQuantity.getText().toString().equals("")) { + etQuantity.setText("1"); + } + int curQauntity = Integer.parseInt(etQuantity.getText().toString()); curQauntity++; etQuantity.setText(String.format("%d", curQauntity)); diff --git a/Listify/app/src/main/java/com/example/listify/ItemDetails.java b/Listify/app/src/main/java/com/example/listify/ItemDetails.java index 46dd926..9b9ddc6 100644 --- a/Listify/app/src/main/java/com/example/listify/ItemDetails.java +++ b/Listify/app/src/main/java/com/example/listify/ItemDetails.java @@ -1,27 +1,16 @@ package com.example.listify; -import android.app.Dialog; -import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; import android.os.Bundle; -import com.amplifyframework.auth.AuthException; +import android.view.View; +import android.widget.*; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; import com.bumptech.glide.Glide; import com.example.listify.data.List; import com.example.listify.data.ListEntry; import com.example.listify.model.Product; import com.google.android.material.floatingactionbutton.FloatingActionButton; -import androidx.appcompat.app.AppCompatActivity; -import androidx.appcompat.widget.Toolbar; -import android.view.View; -import android.view.Window; -import android.view.WindowManager; -import android.widget.ImageButton; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; -import android.widget.Toast; - import org.json.JSONException; import java.io.IOException; @@ -215,7 +204,7 @@ public class ItemDetails extends AppCompatActivity implements ListPickerDialogFr try { - ListEntry entry = new ListEntry(shoppingLists.get(selectedListIndex).getItemID(), curProduct.getItemId(), quantity, Instant.now().toEpochMilli(),false); + ListEntry entry = new ListEntry(shoppingLists.get(selectedListIndex).getListID(), curProduct.getItemId(), quantity, Instant.now().toEpochMilli(),false); requestor.postObject(entry); Toast.makeText(this, String.format("%d of Item added to %s", quantity, shoppingLists.get(selectedListIndex).getName()), Toast.LENGTH_LONG).show(); } catch (Exception e) { @@ -239,7 +228,7 @@ public class ItemDetails extends AppCompatActivity implements ListPickerDialogFr Requestor requestor = new Requestor(am, configs.getProperty("apiKey")); SynchronousReceiver idReceiver = new SynchronousReceiver<>(); - com.example.listify.data.List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli()); + com.example.listify.data.List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli(), -1); Thread t = new Thread(new Runnable() { @Override diff --git a/Listify/app/src/main/java/com/example/listify/ListPage.java b/Listify/app/src/main/java/com/example/listify/ListPage.java index 309eb2d..f536ea4 100644 --- a/Listify/app/src/main/java/com/example/listify/ListPage.java +++ b/Listify/app/src/main/java/com/example/listify/ListPage.java @@ -10,6 +10,8 @@ import android.widget.*; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; +import com.example.listify.ui.home.HomeFragment; import com.bumptech.glide.Glide; import com.example.listify.data.*; import org.json.JSONException; @@ -27,6 +29,7 @@ public class ListPage extends AppCompatActivity implements Requestor.Receiver { ListView listView; MyAdapter myAdapter; Requestor requestor; + SwipeRefreshLayout refreshList; Button incrQuan; Button decrQuan; @@ -59,7 +62,9 @@ public class ListPage extends AppCompatActivity implements Requestor.Receiver { super.onCreate(savedInstanceState); setContentView(R.layout.activity_list); - final int listID = (int) getIntent().getSerializableExtra("listID"); + final int LIST_ID = (int) getIntent().getSerializableExtra("listID"); + final String LIST_NAME = (String) getIntent().getSerializableExtra("listName"); + setTitle(LIST_NAME); Properties configs = new Properties(); try { @@ -68,7 +73,7 @@ public class ListPage extends AppCompatActivity implements Requestor.Receiver { e.printStackTrace(); } requestor = new Requestor(am, configs.getProperty("apiKey")); - requestor.getObject(Integer.toString(listID), List.class, this); + requestor.getObject(Integer.toString(LIST_ID), List.class, this); listView = findViewById(R.id.listView); myAdapter = new MyAdapter(this, pNames, pStores, pPrices, pQuantity, pImages); @@ -77,6 +82,8 @@ public class ListPage extends AppCompatActivity implements Requestor.Receiver { loadingListItems = findViewById(R.id.progress_loading_list_items); loadingListItems.setVisibility(View.VISIBLE); + tvTotalPrice = (TextView) findViewById(R.id.total_price); + clearAll = (Button) findViewById(R.id.buttonClear); clearAll.setOnClickListener(new View.OnClickListener() { @Override @@ -114,7 +121,8 @@ public class ListPage extends AppCompatActivity implements Requestor.Receiver { public void onClick(DialogInterface dialog, int which) { EditText sharedEmailText = (EditText) codeView.findViewById(R.id.editTextTextSharedEmail); String sharedEmail = sharedEmailText.getText().toString(); - ListShare listShare = new ListShare(listID, sharedEmail, "Read, Write, Delete, Share"); + + ListShare listShare = new ListShare(LIST_ID, sharedEmail, "Read, Write, Delete, Share"); try { requestor.putObject(listShare); } @@ -131,6 +139,22 @@ public class ListPage extends AppCompatActivity implements Requestor.Receiver { dialog.show(); } }); + + refreshList = (SwipeRefreshLayout) findViewById(R.id.refresh_list); + refreshList.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + Properties configs = new Properties(); + try { + configs = AuthManager.loadProperties(ListPage.this, "android.resource://" + getPackageName() + "/raw/auths.json"); + } catch (IOException | JSONException e) { + e.printStackTrace(); + } + + requestor = new Requestor(am, configs.getProperty("apiKey")); + requestor.getObject(Integer.toString(LIST_ID), List.class, ListPage.this); + } + }); } @Override @@ -180,6 +204,24 @@ public class ListPage extends AppCompatActivity implements Requestor.Receiver { @Override public void acceptDelivery(Object delivered) { + // Clear out old values + runOnUiThread(new Runnable() { + @Override + public void run() { + pNames.clear(); + pStores.clear(); + pPrices.clear(); + pQuantity.clear(); + pImages.clear(); + totalPriceByStore.clear(); + storeID2Name.clear(); + storeHeaderIndex.clear(); + pListItemPair.clear(); + totalPrice = 0; + tvTotalPrice.setText(String.format("$%.2f", totalPrice)); + } + }); + List list = (List) delivered; if(list != null) { @@ -260,8 +302,6 @@ public class ListPage extends AppCompatActivity implements Requestor.Receiver { } } - - tvTotalPrice = (TextView) findViewById(R.id.total_price); runOnUiThread(new Runnable() { @Override public void run() { @@ -271,6 +311,8 @@ public class ListPage extends AppCompatActivity implements Requestor.Receiver { } }); } + + refreshList.setRefreshing(false); } class MyAdapter extends ArrayAdapter { @@ -330,7 +372,7 @@ public class ListPage extends AppCompatActivity implements Requestor.Receiver { catch (Exception e) { Log.i("Authentication", e.toString()); } - listView.setAdapter(myAdapter); + myAdapter.notifyDataSetChanged(); } }); if(Integer.parseInt(pQuantity.get(position)) <= 1) { @@ -365,7 +407,7 @@ public class ListPage extends AppCompatActivity implements Requestor.Receiver { catch (Exception e) { Log.i("Authentication", e.toString()); } - listView.setAdapter(myAdapter); + myAdapter.notifyDataSetChanged(); } }); if(Integer.parseInt(pQuantity.get(position)) > 1) { @@ -391,7 +433,7 @@ public class ListPage extends AppCompatActivity implements Requestor.Receiver { pImages.remove(position); requestor.deleteObject(pListItemPair.remove(position)); - listView.setAdapter(myAdapter); + myAdapter.notifyDataSetChanged(); } }); diff --git a/Listify/app/src/main/java/com/example/listify/ListPickerDialogFragment.java b/Listify/app/src/main/java/com/example/listify/ListPickerDialogFragment.java index b9c4959..01331c5 100644 --- a/Listify/app/src/main/java/com/example/listify/ListPickerDialogFragment.java +++ b/Listify/app/src/main/java/com/example/listify/ListPickerDialogFragment.java @@ -90,8 +90,13 @@ public class ListPickerDialogFragment extends DialogFragment { btnMinus.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + // Set to 1 if it is empty + if (etQuantity.getText().toString().equals("")) { + etQuantity.setText("1"); + } + int curQauntity = Integer.parseInt(etQuantity.getText().toString()); - if (curQauntity > 0) { + if (curQauntity > 1) { curQauntity--; etQuantity.setText(String.format("%d", curQauntity)); } @@ -102,6 +107,11 @@ public class ListPickerDialogFragment extends DialogFragment { btnPlus.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + // Set to 1 if it is empty + if (etQuantity.getText().toString().equals("")) { + etQuantity.setText("1"); + } + int curQauntity = Integer.parseInt(etQuantity.getText().toString()); curQauntity++; etQuantity.setText(String.format("%d", curQauntity)); diff --git a/Listify/app/src/main/java/com/example/listify/MainActivity.java b/Listify/app/src/main/java/com/example/listify/MainActivity.java index ec0c89b..a7cc876 100644 --- a/Listify/app/src/main/java/com/example/listify/MainActivity.java +++ b/Listify/app/src/main/java/com/example/listify/MainActivity.java @@ -17,6 +17,8 @@ import androidx.navigation.ui.AppBarConfiguration; import androidx.navigation.ui.NavigationUI; import com.amplifyframework.auth.AuthException; import com.example.listify.data.List; +import com.example.listify.data.ListDuplicate; +import com.example.listify.data.ListReposition; import com.example.listify.data.SearchHistory; import com.example.listify.ui.LoginPage; import com.google.android.material.navigation.NavigationView; @@ -107,7 +109,10 @@ public class MainActivity extends AppCompatActivity implements CreateListDialogF SynchronousReceiver historyReceiver = new SynchronousReceiver<>(); requestor.getObject("N/A", SearchHistory.class, historyReceiver, historyReceiver); try { + requestor.putObject(new List(293, "Java.py", "me!", 1)); System.out.println(historyReceiver.await()); + requestor.putObject(new ListReposition(291, 1)); + requestor.postObject(new ListDuplicate(290, "yet another list")); } catch (Exception e) { e.printStackTrace(); } @@ -153,7 +158,7 @@ public class MainActivity extends AppCompatActivity implements CreateListDialogF DrawerLayout drawer = findViewById(R.id.drawer_layout); NavigationView navigationView = findViewById(R.id.nav_view); mAppBarConfiguration = new AppBarConfiguration.Builder( - R.id.nav_home, R.id.nav_profile) + R.id.nav_home, R.id.nav_profile, R.id.nav_logout) .setDrawerLayout(drawer) .build(); NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment); @@ -178,20 +183,14 @@ public class MainActivity extends AppCompatActivity implements CreateListDialogF } public void onClickSignout(MenuItem m) { - m.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - try { - am.signOutUser(); - Intent intent = new Intent(MainActivity.this, com.example.listify.ui.LoginPage.class); - startActivity(intent); - } - catch (Exception e) { - Log.i("Authentication", e.toString()); - } - return false; - } - }); + try { + am.signOutUser(); + Intent intent = new Intent(MainActivity.this, com.example.listify.ui.LoginPage.class); + startActivity(intent); + } + catch (Exception e) { + Log.i("Authentication", e.toString()); + } } @Override @@ -205,7 +204,7 @@ public class MainActivity extends AppCompatActivity implements CreateListDialogF Requestor requestor = new Requestor(am, configs.getProperty("apiKey")); SynchronousReceiver idReceiver = new SynchronousReceiver<>(); - List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli()); + List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli(), -1); try { requestor.postObject(newList, idReceiver, idReceiver); diff --git a/Listify/app/src/main/java/com/example/listify/SearchResults.java b/Listify/app/src/main/java/com/example/listify/SearchResults.java index 7390cb0..379ac8d 100644 --- a/Listify/app/src/main/java/com/example/listify/SearchResults.java +++ b/Listify/app/src/main/java/com/example/listify/SearchResults.java @@ -13,6 +13,8 @@ import android.widget.ImageView; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.SearchView; +import android.widget.TextView; + import com.example.listify.adapter.SearchResultsListAdapter; import com.example.listify.data.Chain; import com.example.listify.data.ItemSearch; @@ -28,9 +30,10 @@ import java.util.Properties; import static com.example.listify.MainActivity.am; public class SearchResults extends AppCompatActivity implements FilterDialogFragment.OnFilterListener, SortDialogFragment.OnSortListener, Requestor.Receiver { - private ListView listView; + private ListView resultsListView; private MenuItem filterItem; private ProgressBar loadingSearch; + private TextView tvNoResults; private SearchResultsListAdapter searchResultsListAdapter; private List resultsProductList = new ArrayList<>(); private List resultsProductListSorted = new ArrayList<>(); @@ -64,6 +67,7 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag setSupportActionBar(toolbar); loadingSearch = (ProgressBar) findViewById(R.id.progress_loading_search); + tvNoResults = (TextView) findViewById(R.id.tv_search_no_results); // Back button closes this activity and returns to previous activity (MainActivity) ImageButton backButton = (ImageButton) findViewById(R.id.backToHomeButton); @@ -95,10 +99,10 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag } }); - ListView listView = (ListView) findViewById(R.id.search_results_list); + resultsListView = (ListView) findViewById(R.id.search_results_list); searchResultsListAdapter = new SearchResultsListAdapter(this, resultsProductListSorted); - listView.setAdapter(searchResultsListAdapter); - listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + resultsListView.setAdapter(searchResultsListAdapter); + resultsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { Intent itemDetailsPage = new Intent(SearchResults.this, ItemDetails.class); @@ -207,13 +211,22 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag requestor.getObject(query, ItemSearch.class, this); } - // TODO: Scroll the list back to the top when a search, sort, or filter is performed // Sorts the search results private void sortResults() { // Reset the filtered list resultsProductListSorted.clear(); resultsProductListSorted.addAll(resultsProductList); + // Scroll the user back to the top of the results + if (resultsListView != null) { + runOnUiThread(new Runnable() { + @Override + public void run() { + resultsListView.smoothScrollToPosition(0); + } + }); + } + // Sort Modes // 0 default (no sorting) // 1 itemName @@ -311,10 +324,22 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag } // This is called after the search results come back from the server - // TODO: Display a "no results" message if nothing is found when searching @Override public void acceptDelivery(Object delivered) { ItemSearch results = (ItemSearch) delivered; + + // Display "no results" message if the search returns none + runOnUiThread(new Runnable() { + @Override + public void run() { + if (results.getResults().size() == 0) { + tvNoResults.setVisibility(View.VISIBLE); + } else { + tvNoResults.setVisibility(View.GONE); + } + } + }); + try { HashMap chainNameMap = new HashMap<>(); for (int i = 0; i < results.getResults().size(); i++) { diff --git a/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java b/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java index 5fa13ec..2f17836 100644 --- a/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java +++ b/Listify/app/src/main/java/com/example/listify/SortDialogFragment.java @@ -35,7 +35,6 @@ public class SortDialogFragment extends DialogFragment { } - // TODO: Sorting should scroll the user back to the top of the page @Override public Dialog onCreateDialog(final Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); diff --git a/Listify/app/src/main/java/com/example/listify/adapter/SearchResultsListAdapter.java b/Listify/app/src/main/java/com/example/listify/adapter/SearchResultsListAdapter.java index bc02c73..9b3ddf7 100644 --- a/Listify/app/src/main/java/com/example/listify/adapter/SearchResultsListAdapter.java +++ b/Listify/app/src/main/java/com/example/listify/adapter/SearchResultsListAdapter.java @@ -10,6 +10,7 @@ import android.widget.ImageView; import android.widget.TextView; import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; import com.example.listify.model.Product; import com.example.listify.R; @@ -55,8 +56,12 @@ public class SearchResultsListAdapter extends BaseAdapter { TextView itemStore = (TextView) convertView.findViewById(R.id.item_store); Product product = productList.get(position); - // TODO: If image url is broken, display @drawable/ic_baseline_broken_image_600.xml - Glide.with(activity).load(product.getImageUrl()).into(productImage); + + Glide.with(activity) + .applyDefaultRequestOptions(new RequestOptions().placeholder(R.drawable.ic_baseline_image_600).error(R.drawable.ic_baseline_broken_image_600)) + .load(product.getImageUrl()) + .into(productImage); + if (product.getItemName().length() >= 60) { itemName.setText(product.getItemName().substring(0, 60) + "..."); } else { diff --git a/Listify/app/src/main/java/com/example/listify/adapter/ShoppingListsSwipeableAdapter.java b/Listify/app/src/main/java/com/example/listify/adapter/ShoppingListsSwipeableAdapter.java index 8fa0d6a..fd13b79 100644 --- a/Listify/app/src/main/java/com/example/listify/adapter/ShoppingListsSwipeableAdapter.java +++ b/Listify/app/src/main/java/com/example/listify/adapter/ShoppingListsSwipeableAdapter.java @@ -80,7 +80,8 @@ public class ShoppingListsSwipeableAdapter extends BaseAdapter { holder.frontView = convertView.findViewById(R.id.front_layout); holder.deleteList = convertView.findViewById(R.id.delete_list); holder.shareList = convertView.findViewById(R.id.share_list); - holder.textView = (TextView) convertView.findViewById(R.id.shopping_list_name); + holder.listName = (TextView) convertView.findViewById(R.id.shopping_list_name); + holder.itemCount = (TextView) convertView.findViewById(R.id.shopping_list_item_count); convertView.setTag(holder); } else { @@ -90,19 +91,22 @@ public class ShoppingListsSwipeableAdapter extends BaseAdapter { final List curList = lists.get(position); // Bind the view to the unique list ID - binderHelper.bind(holder.swipeLayout, Integer.toString(curList.getItemID())); + binderHelper.bind(holder.swipeLayout, Integer.toString(curList.getListID())); if(curList.isShared()) { - holder.textView.setText(curList.getName() + " (shared)"); + holder.listName.setText(curList.getName() + " (shared)"); } else { - holder.textView.setText(curList.getName()); + holder.listName.setText(curList.getName()); } + + holder.itemCount.setText(String.format("%d items", curList.getEntries().length)); + holder.deleteList.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { - requestor.deleteObject(Integer.toString(curList.getItemID()), List.class); + requestor.deleteObject(Integer.toString(curList.getListID()), List.class); } catch(Exception e) { e.printStackTrace(); @@ -129,7 +133,7 @@ public class ShoppingListsSwipeableAdapter extends BaseAdapter { public void onClick(DialogInterface dialog, int which) { EditText sharedEmailText = (EditText) codeView.findViewById(R.id.editTextTextSharedEmail); String sharedEmail = sharedEmailText.getText().toString(); - ListShare listShare = new ListShare(curList.getItemID(), sharedEmail, "Read, Write, Delete, Share"); + ListShare listShare = new ListShare(curList.getListID(), sharedEmail, "Read, Write, Delete, Share"); try { requestor.putObject(listShare); } @@ -148,7 +152,7 @@ public class ShoppingListsSwipeableAdapter extends BaseAdapter { Toast.makeText(activity, String.format("Share %s", curList.getName()), Toast.LENGTH_SHORT).show(); // Close the layout - binderHelper.closeLayout(Integer.toString(curList.getItemID())); + binderHelper.closeLayout(Integer.toString(curList.getListID())); } }); @@ -157,8 +161,10 @@ public class ShoppingListsSwipeableAdapter extends BaseAdapter { public void onClick(View v) { Intent listPage = new Intent(activity, ListPage.class); - // Send the list ID - listPage.putExtra("listID", curList.getItemID()); + // Send the list ID and list name + listPage.putExtra("listID", curList.getListID()); + listPage.putExtra("listName", curList.getName()); + activity.startActivity(listPage); } }); @@ -171,6 +177,7 @@ public class ShoppingListsSwipeableAdapter extends BaseAdapter { View frontView; View deleteList; View shareList; - TextView textView; + TextView listName; + TextView itemCount; } } diff --git a/Listify/app/src/main/java/com/example/listify/data/List.java b/Listify/app/src/main/java/com/example/listify/data/List.java index 6a3fab0..a52a122 100644 --- a/Listify/app/src/main/java/com/example/listify/data/List.java +++ b/Listify/app/src/main/java/com/example/listify/data/List.java @@ -3,44 +3,47 @@ package com.example.listify.data; import java.util.Arrays; public class List { - Integer itemID; + Integer listID; String name; String owner; long lastUpdated; final ListEntry[] entries; boolean shared; + Integer uiPosition; - public List(Integer itemID, String name, String owner, long lastUpdated, ListEntry[] entries, boolean shared) { - this.itemID = itemID; + public List(Integer listID, String name, String owner, long lastUpdated, ListEntry[] entries, boolean shared, Integer uiPosition) { + this.listID = listID; this.name = name; this.owner = owner; this.lastUpdated = lastUpdated; this.entries = entries; this.shared = false; + this.uiPosition = uiPosition; } - public List(Integer itemID, String name, String owner, long lastUpdated) { - this(itemID, name, owner, lastUpdated, null, false); + public List(Integer listID, String name, String owner, long lastUpdated, Integer uiPosition) { + this(listID, name, owner, lastUpdated, null, false, uiPosition); } @Override public String toString() { return "List{" + - "itemID=" + itemID + + "listID=" + listID + ", name='" + name + '\'' + ", owner='" + owner + '\'' + ", lastUpdated=" + lastUpdated + ", entries=" + Arrays.toString(entries) + ", shared=" + shared + + ", uiPosition=" + uiPosition + '}'; } - public Integer getItemID() { - return itemID; + public Integer getListID() { + return listID; } - public void setItemID(Integer itemID) { - this.itemID = itemID; + public void setListID(Integer listID) { + this.listID = listID; } public String getName() { @@ -75,6 +78,13 @@ public class List { this.shared = shared; } + public Integer getUiPosition() { + return uiPosition; + } + + public void setUiPosition(Integer uiPosition) { + this.uiPosition = uiPosition; + public ListEntry[] getEntries() { return entries; } diff --git a/Listify/app/src/main/java/com/example/listify/data/ListDuplicate.java b/Listify/app/src/main/java/com/example/listify/data/ListDuplicate.java new file mode 100644 index 0000000..2e398f7 --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/data/ListDuplicate.java @@ -0,0 +1,37 @@ +package com.example.listify.data; + +// Info on List to copy +public class ListDuplicate { + Integer listID; + String name; + + public ListDuplicate(Integer listID, String name) { + this.listID = listID; + this.name = name; + } + + @Override + public String toString() { + return "ListDuplicate{" + + "listID=" + listID + + ", name='" + name + '\'' + + '}'; + } + + public Integer getListID() { + return listID; + } + + public void setListID(Integer listID) { + this.listID = listID; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/Listify/app/src/main/java/com/example/listify/data/ListReposition.java b/Listify/app/src/main/java/com/example/listify/data/ListReposition.java new file mode 100644 index 0000000..6d3e5ef --- /dev/null +++ b/Listify/app/src/main/java/com/example/listify/data/ListReposition.java @@ -0,0 +1,35 @@ +package com.example.listify.data; + +public class ListReposition { + Integer listID; + Integer newPosition; + + public ListReposition(Integer listID, Integer newPosition) { + this.listID = listID; + this.newPosition = newPosition; + } + + @Override + public String toString() { + return "ListReposition{" + + "listID=" + listID + + ", newPosition=" + newPosition + + '}'; + } + + public Integer getListID() { + return listID; + } + + public void setListID(Integer listID) { + this.listID = listID; + } + + public Integer getNewPosition() { + return newPosition; + } + + public void setNewPosition(Integer newPosition) { + this.newPosition = newPosition; + } +} diff --git a/Listify/app/src/main/java/com/example/listify/ui/home/HomeFragment.java b/Listify/app/src/main/java/com/example/listify/ui/home/HomeFragment.java index bd44ea3..3a93463 100644 --- a/Listify/app/src/main/java/com/example/listify/ui/home/HomeFragment.java +++ b/Listify/app/src/main/java/com/example/listify/ui/home/HomeFragment.java @@ -6,11 +6,14 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ListView; import android.widget.ProgressBar; +import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + import com.example.listify.AuthManager; import com.example.listify.CreateListDialogFragment; import com.example.listify.LoadingCircleDialog; @@ -37,6 +40,7 @@ public class HomeFragment extends Fragment implements CreateListDialogFragment.O ListView shoppingListsView; ProgressBar loadingLists; TextView emptyMessage; + SwipeRefreshLayout refreshLists; public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = inflater.inflate(R.layout.fragment_home, container, false); @@ -44,6 +48,7 @@ public class HomeFragment extends Fragment implements CreateListDialogFragment.O loadingLists = (ProgressBar) root.findViewById(R.id.progress_loading_lists); loadingLists.setVisibility(View.VISIBLE); emptyMessage = (TextView) root.findViewById(R.id.textViewEmpty); + refreshLists = (SwipeRefreshLayout) root.findViewById(R.id.refresh_lists); Properties configs = new Properties(); try { @@ -55,8 +60,8 @@ public class HomeFragment extends Fragment implements CreateListDialogFragment.O requestor = new Requestor(am, configs.getProperty("apiKey")); SynchronousReceiver listIdsReceiver = new SynchronousReceiver<>(); - final Requestor.Receiver recv = this; - requestor.getListOfIds(List.class, recv, null); +// final Requestor.Receiver recv = this; + requestor.getListOfIds(List.class, this, null); FloatingActionButton fab = (FloatingActionButton) root.findViewById(R.id.new_list_fab); @@ -70,6 +75,23 @@ public class HomeFragment extends Fragment implements CreateListDialogFragment.O } }); + refreshLists.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + Properties configs = new Properties(); + try { + configs = AuthManager.loadProperties(getContext(), "android.resource://" + getActivity().getPackageName() + "/raw/auths.json"); + } catch (IOException | JSONException e) { + e.printStackTrace(); + } + + requestor = new Requestor(am, configs.getProperty("apiKey")); + SynchronousReceiver listIdsReceiver = new SynchronousReceiver<>(); + + requestor.getListOfIds(List.class, HomeFragment.this, null); + } + }); + return root; } @@ -88,7 +110,7 @@ public class HomeFragment extends Fragment implements CreateListDialogFragment.O Requestor requestor = new Requestor(am, configs.getProperty("apiKey")); SynchronousReceiver idReceiver = new SynchronousReceiver<>(); - List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli()); + List newList = new List(-1, name, "user filled by lambda", Instant.now().toEpochMilli() , -1); try { requestor.postObject(newList, idReceiver, idReceiver); @@ -101,7 +123,7 @@ public class HomeFragment extends Fragment implements CreateListDialogFragment.O @Override public void run() { try { - newList.setItemID(idReceiver.await()); + newList.setListID(idReceiver.await()); } catch (Exception e) { getActivity().runOnUiThread(new Runnable() { @Override @@ -130,6 +152,9 @@ public class HomeFragment extends Fragment implements CreateListDialogFragment.O @Override public void acceptDelivery(Object delivered) { + // Remove old lists on refresh + shoppingLists.clear(); + Integer[] listIds = (Integer[]) delivered; // Create threads and add them to a list Thread[] threads = new Thread[listIds.length]; @@ -169,16 +194,6 @@ public class HomeFragment extends Fragment implements CreateListDialogFragment.O @Override public void run() { shoppingListsView.setAdapter(shoppingListsSwipeableAdapter); -// shoppingListsView.setOnItemClickListener(new AdapterView.OnItemClickListener() { -// @Override -// public void onItemClick(AdapterView parent, View view, int position, long id) { -// Intent listPage = new Intent(getContext(), ListPage.class); -// -// // Send the list ID -// listPage.putExtra("listID", shoppingLists.get(position).getItemID()); -// startActivity(listPage); -// } -// }); loadingLists.setVisibility(View.GONE); if(listIds.length == 0) { @@ -187,5 +202,6 @@ public class HomeFragment extends Fragment implements CreateListDialogFragment.O } }); + refreshLists.setRefreshing(false); } } \ No newline at end of file diff --git a/Listify/app/src/main/java/com/example/listify/ui/home/HomeViewModel.java b/Listify/app/src/main/java/com/example/listify/ui/home/HomeViewModel.java deleted file mode 100644 index 22e1280..0000000 --- a/Listify/app/src/main/java/com/example/listify/ui/home/HomeViewModel.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.example.listify.ui.home; - -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; - -public class HomeViewModel extends ViewModel { - - private MutableLiveData mText; - - public HomeViewModel() { - mText = new MutableLiveData<>(); - mText.setValue("This is home fragment"); - } - - public LiveData getText() { - return mText; - } -} \ No newline at end of file diff --git a/Listify/app/src/main/res/drawable/ic_baseline_exit_to_app_24.xml b/Listify/app/src/main/res/drawable/ic_baseline_exit_to_app_24.xml new file mode 100644 index 0000000..83cdf05 --- /dev/null +++ b/Listify/app/src/main/res/drawable/ic_baseline_exit_to_app_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/Listify/app/src/main/res/drawable/ic_baseline_image_600.xml b/Listify/app/src/main/res/drawable/ic_baseline_image_600.xml new file mode 100644 index 0000000..1f1ec73 --- /dev/null +++ b/Listify/app/src/main/res/drawable/ic_baseline_image_600.xml @@ -0,0 +1,5 @@ + + + diff --git a/Listify/app/src/main/res/layout/activity_list.xml b/Listify/app/src/main/res/layout/activity_list.xml index 94d1b61..7ecaabf 100644 --- a/Listify/app/src/main/res/layout/activity_list.xml +++ b/Listify/app/src/main/res/layout/activity_list.xml @@ -37,12 +37,19 @@ - + android:layout_height="wrap_content"> + + + + + + \ No newline at end of file diff --git a/Listify/app/src/main/res/layout/dialog_add_to_list.xml b/Listify/app/src/main/res/layout/dialog_add_to_list.xml index 5e255f9..4273676 100644 --- a/Listify/app/src/main/res/layout/dialog_add_to_list.xml +++ b/Listify/app/src/main/res/layout/dialog_add_to_list.xml @@ -38,6 +38,7 @@ android:layout_width="60dp" android:layout_height="50dp" android:text="@string/_1" + android:digits="0123456789" android:inputType="number"/>