mirror of
https://github.com/ClaytonWWilson/Listify.git
synced 2025-12-16 02:38:47 +00:00
Merge remote-tracking branch 'origin/master' into aaron-branch
This commit is contained in:
commit
28b916c326
5
.gitignore
vendored
5
.gitignore
vendored
@ -44,6 +44,7 @@ captures/
|
||||
.idea/assetWizardSettings.xml
|
||||
.idea/dictionaries
|
||||
.idea/libraries
|
||||
*.idea*
|
||||
# Android Studio 3 in .gitignore file.
|
||||
.idea/caches
|
||||
.idea/modules.xml
|
||||
@ -83,3 +84,7 @@ lint/generated/
|
||||
lint/outputs/
|
||||
lint/tmp/
|
||||
# lint/reports/
|
||||
Lambdas/Lists/src/main/resources/dbProperties.json
|
||||
Lambdas/Lists/target/classes/dbProperties.json
|
||||
Lambdas/Lists/target/classes/META-INF/Lists.kotlin_module
|
||||
Listify/app/src/main/res/raw/auths.json
|
||||
|
||||
47
Lambdas/Lists/pom.xml
Normal file
47
Lambdas/Lists/pom.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>groupId</groupId>
|
||||
<artifactId>Lists</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-lambda-java-core</artifactId>
|
||||
<version>1.2.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-lambda-java-events</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-lambda-java-log4j2</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>20200518</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mariadb.jdbc</groupId>
|
||||
<artifactId>mariadb-java-client</artifactId>
|
||||
<version>2.7.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<maven.compiler.source>1.11</maven.compiler.source>
|
||||
<maven.compiler.target>1.11</maven.compiler.target>
|
||||
</properties>
|
||||
</project>
|
||||
53
Lambdas/Lists/src/main/java/DBConnector.java
Normal file
53
Lambdas/Lists/src/main/java/DBConnector.java
Normal file
@ -0,0 +1,53 @@
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
public class DBConnector {
|
||||
|
||||
Connection connection;
|
||||
|
||||
DBConnector() throws IOException, SQLException, ClassNotFoundException {
|
||||
this(loadProperties("dbProperties.json"));
|
||||
}
|
||||
|
||||
DBConnector(Properties dbProperties) throws SQLException, ClassNotFoundException {
|
||||
Class.forName("org.mariadb.jdbc.Driver");
|
||||
System.out.println(dbProperties);
|
||||
System.out.println(DBConnector.buildURL(dbProperties));
|
||||
connection = DriverManager.getConnection(dbProperties.get("url").toString(), dbProperties.get("user").toString(), dbProperties.get("password").toString());
|
||||
System.out.println(connection);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
connection.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public Connection getConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
public static Properties loadProperties(String path) throws IOException {
|
||||
Properties toReturn = new Properties();
|
||||
String propertiesJSONString = Files.readString(Path.of(path));
|
||||
JSONObject propertiesJSON = new JSONObject(propertiesJSONString);
|
||||
propertiesJSON.keys().forEachRemaining(key -> toReturn.setProperty(key, propertiesJSON.get(key).toString()));
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public static String buildURL(Properties dbProperties) {
|
||||
String dbURL = dbProperties.get("url").toString();
|
||||
dbURL += "?user=" + dbProperties.get("user").toString();
|
||||
dbURL += "&password=" + dbProperties.get("password").toString();
|
||||
return dbURL;
|
||||
}
|
||||
}
|
||||
28
Lambdas/Lists/src/main/java/InputUtils.java
Normal file
28
Lambdas/Lists/src/main/java/InputUtils.java
Normal file
@ -0,0 +1,28 @@
|
||||
import java.util.Map;
|
||||
|
||||
public class InputUtils {
|
||||
public static String getCognitoIDFromBody(Map<String, Object> inputMap) {
|
||||
System.out.println(inputMap.keySet());
|
||||
System.out.println(inputMap.entrySet());
|
||||
Map<String, Object> contextMap;
|
||||
if ((inputMap.get("context") != null) && (inputMap.get("context") instanceof Map<?, ?>)) {
|
||||
contextMap = ((Map<String, Object>) inputMap.get("context"));
|
||||
} else {
|
||||
throw new IllegalArgumentException("The key \"context\" must exist and be a map");
|
||||
}
|
||||
System.out.println(inputMap.get("context"));
|
||||
System.out.println(contextMap.get("sub"));
|
||||
return contextMap.get("sub").toString();
|
||||
}
|
||||
|
||||
public static Map<String, Object> getBody(Map<String, Object> inputMap) {
|
||||
return getMap(inputMap, "body");
|
||||
}
|
||||
|
||||
public static Map<String, Object> getMap(Map<String, Object> parentMap, String childKey) {
|
||||
if ((parentMap.get(childKey) != null) && (parentMap.get(childKey) instanceof Map<?, ?>)) {
|
||||
return ((Map<String, Object>) parentMap.get(childKey));
|
||||
}
|
||||
throw new IllegalArgumentException("The key \"" + childKey + "\" must exist and be a map");
|
||||
}
|
||||
}
|
||||
27
Lambdas/Lists/src/main/java/ListAdder.java
Normal file
27
Lambdas/Lists/src/main/java/ListAdder.java
Normal file
@ -0,0 +1,27 @@
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
|
||||
public class ListAdder {
|
||||
|
||||
private DBConnector connector;
|
||||
private String cognitoID;
|
||||
|
||||
private final String LIST_CREATE = "INSERT INTO Lists (Name, Owner) VALUES (?, ?)";
|
||||
|
||||
ListAdder(DBConnector connector, String cognitoID) {
|
||||
this.connector = connector;
|
||||
this.cognitoID = cognitoID;
|
||||
}
|
||||
|
||||
public void add(Map<String, Object> bodyMap) throws SQLException {
|
||||
Connection connection = connector.getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement(LIST_CREATE);
|
||||
statement.setString(1, bodyMap.get("name").toString());//Needs safe checking
|
||||
statement.setString(2, cognitoID);
|
||||
System.out.println(statement);
|
||||
statement.executeUpdate();
|
||||
connection.commit();
|
||||
}
|
||||
}
|
||||
28
Lambdas/Lists/src/main/java/ListPOST.java
Normal file
28
Lambdas/Lists/src/main/java/ListPOST.java
Normal file
@ -0,0 +1,28 @@
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
|
||||
import com.amazonaws.services.lambda.runtime.Context;
|
||||
import com.amazonaws.services.lambda.runtime.RequestHandler;
|
||||
|
||||
public class ListPOST implements RequestHandler<Map<String,Object>, String>{
|
||||
|
||||
|
||||
public String handleRequest(Map<String, Object> inputMap, Context unfilled) {
|
||||
String cognitoID = InputUtils.getCognitoIDFromBody(inputMap);
|
||||
try {
|
||||
DBConnector connector = new DBConnector();
|
||||
try {
|
||||
new ListAdder(connector, cognitoID).add(InputUtils.getBody(inputMap));
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
connector.close();
|
||||
}
|
||||
} catch (IOException|SQLException|ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
16
Listify/.gitignore
vendored
16
Listify/.gitignore
vendored
@ -12,3 +12,19 @@
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
|
||||
#amplify
|
||||
amplify/\#current-cloud-backend
|
||||
amplify/.config/local-*
|
||||
amplify/mock-data
|
||||
amplify/backend/amplify-meta.json
|
||||
amplify/backend/awscloudformation
|
||||
build/
|
||||
dist/
|
||||
node_modules/
|
||||
aws-exports.js
|
||||
awsconfiguration.json
|
||||
amplifyconfiguration.json
|
||||
amplify-build-config.json
|
||||
amplify-gradle-config.json
|
||||
amplifytools.xcconfig
|
||||
@ -4,6 +4,7 @@
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="delegatedBuild" value="false" />
|
||||
<option name="testRunner" value="PLATFORM" />
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="false" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
||||
11
Listify/Pipfile
Normal file
11
Listify/Pipfile
Normal file
@ -0,0 +1,11 @@
|
||||
[[source]]
|
||||
name = "pypi"
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[packages]
|
||||
|
||||
[requires]
|
||||
python_version = "3.8"
|
||||
13
Listify/amplify/.config/project-config.json
Normal file
13
Listify/amplify/.config/project-config.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"projectName": "Listify",
|
||||
"version": "3.0",
|
||||
"frontend": "android",
|
||||
"android": {
|
||||
"config": {
|
||||
"ResDir": "app/src/main/res"
|
||||
}
|
||||
},
|
||||
"providers": [
|
||||
"awscloudformation"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,396 @@
|
||||
AWSTemplateFormatVersion: 2010-09-09
|
||||
|
||||
Parameters:
|
||||
env:
|
||||
Type: String
|
||||
authRoleArn:
|
||||
Type: String
|
||||
unauthRoleArn:
|
||||
Type: String
|
||||
|
||||
|
||||
|
||||
|
||||
identityPoolName:
|
||||
Type: String
|
||||
|
||||
allowUnauthenticatedIdentities:
|
||||
Type: String
|
||||
|
||||
resourceNameTruncated:
|
||||
Type: String
|
||||
|
||||
userPoolName:
|
||||
Type: String
|
||||
|
||||
autoVerifiedAttributes:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
mfaConfiguration:
|
||||
Type: String
|
||||
|
||||
mfaTypes:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
smsAuthenticationMessage:
|
||||
Type: String
|
||||
|
||||
smsVerificationMessage:
|
||||
Type: String
|
||||
|
||||
emailVerificationSubject:
|
||||
Type: String
|
||||
|
||||
emailVerificationMessage:
|
||||
Type: String
|
||||
|
||||
defaultPasswordPolicy:
|
||||
Type: String
|
||||
|
||||
passwordPolicyMinLength:
|
||||
Type: Number
|
||||
|
||||
passwordPolicyCharacters:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
requiredAttributes:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
userpoolClientGenerateSecret:
|
||||
Type: String
|
||||
|
||||
userpoolClientRefreshTokenValidity:
|
||||
Type: Number
|
||||
|
||||
userpoolClientWriteAttributes:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
userpoolClientReadAttributes:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
userpoolClientLambdaRole:
|
||||
Type: String
|
||||
|
||||
userpoolClientSetAttributes:
|
||||
Type: String
|
||||
|
||||
sharedId:
|
||||
Type: String
|
||||
|
||||
resourceName:
|
||||
Type: String
|
||||
|
||||
authSelections:
|
||||
Type: String
|
||||
|
||||
useDefault:
|
||||
Type: String
|
||||
|
||||
usernameAttributes:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
triggers:
|
||||
Type: String
|
||||
|
||||
userPoolGroupList:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
serviceName:
|
||||
Type: String
|
||||
|
||||
parentStack:
|
||||
Type: String
|
||||
|
||||
permissions:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
dependsOn:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
Conditions:
|
||||
ShouldNotCreateEnvResources: !Equals [ !Ref env, NONE ]
|
||||
|
||||
Resources:
|
||||
|
||||
|
||||
# BEGIN SNS ROLE RESOURCE
|
||||
SNSRole:
|
||||
# Created to allow the UserPool SMS Config to publish via the Simple Notification Service during MFA Process
|
||||
Type: AWS::IAM::Role
|
||||
Properties:
|
||||
RoleName: !If [ShouldNotCreateEnvResources, 'listiff4fad454_sns-role', !Join ['',[ 'sns', 'f4fad454', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]]
|
||||
AssumeRolePolicyDocument:
|
||||
Version: "2012-10-17"
|
||||
Statement:
|
||||
- Sid: ""
|
||||
Effect: "Allow"
|
||||
Principal:
|
||||
Service: "cognito-idp.amazonaws.com"
|
||||
Action:
|
||||
- "sts:AssumeRole"
|
||||
Condition:
|
||||
StringEquals:
|
||||
sts:ExternalId: listiff4fad454_role_external_id
|
||||
Policies:
|
||||
-
|
||||
PolicyName: listiff4fad454-sns-policy
|
||||
PolicyDocument:
|
||||
Version: "2012-10-17"
|
||||
Statement:
|
||||
-
|
||||
Effect: "Allow"
|
||||
Action:
|
||||
- "sns:Publish"
|
||||
Resource: "*"
|
||||
# BEGIN USER POOL RESOURCES
|
||||
UserPool:
|
||||
# Created upon user selection
|
||||
# Depends on SNS Role for Arn if MFA is enabled
|
||||
Type: AWS::Cognito::UserPool
|
||||
UpdateReplacePolicy: Retain
|
||||
Properties:
|
||||
UserPoolName: !If [ShouldNotCreateEnvResources, !Ref userPoolName, !Join ['',[!Ref userPoolName, '-', !Ref env]]]
|
||||
|
||||
Schema:
|
||||
|
||||
-
|
||||
Name: email
|
||||
Required: true
|
||||
Mutable: true
|
||||
|
||||
|
||||
|
||||
|
||||
AutoVerifiedAttributes: !Ref autoVerifiedAttributes
|
||||
|
||||
|
||||
EmailVerificationMessage: !Ref emailVerificationMessage
|
||||
EmailVerificationSubject: !Ref emailVerificationSubject
|
||||
|
||||
Policies:
|
||||
PasswordPolicy:
|
||||
MinimumLength: !Ref passwordPolicyMinLength
|
||||
RequireLowercase: false
|
||||
RequireNumbers: false
|
||||
RequireSymbols: false
|
||||
RequireUppercase: false
|
||||
|
||||
UsernameAttributes: !Ref usernameAttributes
|
||||
|
||||
MfaConfiguration: !Ref mfaConfiguration
|
||||
SmsVerificationMessage: !Ref smsVerificationMessage
|
||||
SmsConfiguration:
|
||||
SnsCallerArn: !GetAtt SNSRole.Arn
|
||||
ExternalId: listiff4fad454_role_external_id
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Updating lambda role with permissions to Cognito
|
||||
|
||||
|
||||
UserPoolClientWeb:
|
||||
# Created provide application access to user pool
|
||||
# Depends on UserPool for ID reference
|
||||
Type: "AWS::Cognito::UserPoolClient"
|
||||
Properties:
|
||||
ClientName: listiff4fad454_app_clientWeb
|
||||
|
||||
RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity
|
||||
UserPoolId: !Ref UserPool
|
||||
DependsOn: UserPool
|
||||
UserPoolClient:
|
||||
# Created provide application access to user pool
|
||||
# Depends on UserPool for ID reference
|
||||
Type: "AWS::Cognito::UserPoolClient"
|
||||
Properties:
|
||||
ClientName: listiff4fad454_app_client
|
||||
|
||||
GenerateSecret: !Ref userpoolClientGenerateSecret
|
||||
RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity
|
||||
UserPoolId: !Ref UserPool
|
||||
DependsOn: UserPool
|
||||
# BEGIN USER POOL LAMBDA RESOURCES
|
||||
UserPoolClientRole:
|
||||
# Created to execute Lambda which gets userpool app client config values
|
||||
Type: 'AWS::IAM::Role'
|
||||
Properties:
|
||||
RoleName: !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',['upClientLambdaRole', 'f4fad454', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]]
|
||||
AssumeRolePolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Principal:
|
||||
Service:
|
||||
- lambda.amazonaws.com
|
||||
Action:
|
||||
- 'sts:AssumeRole'
|
||||
DependsOn: UserPoolClient
|
||||
UserPoolClientLambda:
|
||||
# Lambda which gets userpool app client config values
|
||||
# Depends on UserPool for id
|
||||
# Depends on UserPoolClientRole for role ARN
|
||||
Type: 'AWS::Lambda::Function'
|
||||
Properties:
|
||||
Code:
|
||||
ZipFile: !Join
|
||||
- |+
|
||||
- - 'const response = require(''cfn-response'');'
|
||||
- 'const aws = require(''aws-sdk'');'
|
||||
- 'const identity = new aws.CognitoIdentityServiceProvider();'
|
||||
- 'exports.handler = (event, context, callback) => {'
|
||||
- ' if (event.RequestType == ''Delete'') { '
|
||||
- ' response.send(event, context, response.SUCCESS, {})'
|
||||
- ' }'
|
||||
- ' if (event.RequestType == ''Update'' || event.RequestType == ''Create'') {'
|
||||
- ' const params = {'
|
||||
- ' ClientId: event.ResourceProperties.clientId,'
|
||||
- ' UserPoolId: event.ResourceProperties.userpoolId'
|
||||
- ' };'
|
||||
- ' identity.describeUserPoolClient(params).promise()'
|
||||
- ' .then((res) => {'
|
||||
- ' response.send(event, context, response.SUCCESS, {''appSecret'': res.UserPoolClient.ClientSecret});'
|
||||
- ' })'
|
||||
- ' .catch((err) => {'
|
||||
- ' response.send(event, context, response.FAILED, {err});'
|
||||
- ' });'
|
||||
- ' }'
|
||||
- '};'
|
||||
Handler: index.handler
|
||||
Runtime: nodejs10.x
|
||||
Timeout: '300'
|
||||
Role: !GetAtt
|
||||
- UserPoolClientRole
|
||||
- Arn
|
||||
DependsOn: UserPoolClientRole
|
||||
UserPoolClientLambdaPolicy:
|
||||
# Sets userpool policy for the role that executes the Userpool Client Lambda
|
||||
# Depends on UserPool for Arn
|
||||
# Marked as depending on UserPoolClientRole for easier to understand CFN sequencing
|
||||
Type: 'AWS::IAM::Policy'
|
||||
Properties:
|
||||
PolicyName: listiff4fad454_userpoolclient_lambda_iam_policy
|
||||
Roles:
|
||||
- !Ref UserPoolClientRole
|
||||
PolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- 'cognito-idp:DescribeUserPoolClient'
|
||||
Resource: !GetAtt UserPool.Arn
|
||||
DependsOn: UserPoolClientLambda
|
||||
UserPoolClientLogPolicy:
|
||||
# Sets log policy for the role that executes the Userpool Client Lambda
|
||||
# Depends on UserPool for Arn
|
||||
# Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing
|
||||
Type: 'AWS::IAM::Policy'
|
||||
Properties:
|
||||
PolicyName: listiff4fad454_userpoolclient_lambda_log_policy
|
||||
Roles:
|
||||
- !Ref UserPoolClientRole
|
||||
PolicyDocument:
|
||||
Version: 2012-10-17
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- 'logs:CreateLogGroup'
|
||||
- 'logs:CreateLogStream'
|
||||
- 'logs:PutLogEvents'
|
||||
Resource: !Sub
|
||||
- arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:*
|
||||
- { region: !Ref "AWS::Region", account: !Ref "AWS::AccountId", lambda: !Ref UserPoolClientLambda}
|
||||
DependsOn: UserPoolClientLambdaPolicy
|
||||
UserPoolClientInputs:
|
||||
# Values passed to Userpool client Lambda
|
||||
# Depends on UserPool for Id
|
||||
# Depends on UserPoolClient for Id
|
||||
# Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing
|
||||
Type: 'Custom::LambdaCallout'
|
||||
Properties:
|
||||
ServiceToken: !GetAtt UserPoolClientLambda.Arn
|
||||
clientId: !Ref UserPoolClient
|
||||
userpoolId: !Ref UserPool
|
||||
DependsOn: UserPoolClientLogPolicy
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# BEGIN IDENTITY POOL RESOURCES
|
||||
|
||||
|
||||
IdentityPool:
|
||||
# Always created
|
||||
Type: AWS::Cognito::IdentityPool
|
||||
Properties:
|
||||
IdentityPoolName: !If [ShouldNotCreateEnvResources, 'listifyf4fad454_identitypool_f4fad454', !Join ['',['listifyf4fad454_identitypool_f4fad454', '__', !Ref env]]]
|
||||
|
||||
CognitoIdentityProviders:
|
||||
- ClientId: !Ref UserPoolClient
|
||||
ProviderName: !Sub
|
||||
- cognito-idp.${region}.amazonaws.com/${client}
|
||||
- { region: !Ref "AWS::Region", client: !Ref UserPool}
|
||||
- ClientId: !Ref UserPoolClientWeb
|
||||
ProviderName: !Sub
|
||||
- cognito-idp.${region}.amazonaws.com/${client}
|
||||
- { region: !Ref "AWS::Region", client: !Ref UserPool}
|
||||
|
||||
AllowUnauthenticatedIdentities: !Ref allowUnauthenticatedIdentities
|
||||
|
||||
|
||||
DependsOn: UserPoolClientInputs
|
||||
|
||||
|
||||
IdentityPoolRoleMap:
|
||||
# Created to map Auth and Unauth roles to the identity pool
|
||||
# Depends on Identity Pool for ID ref
|
||||
Type: AWS::Cognito::IdentityPoolRoleAttachment
|
||||
Properties:
|
||||
IdentityPoolId: !Ref IdentityPool
|
||||
Roles:
|
||||
unauthenticated: !Ref unauthRoleArn
|
||||
authenticated: !Ref authRoleArn
|
||||
DependsOn: IdentityPool
|
||||
|
||||
|
||||
Outputs :
|
||||
|
||||
IdentityPoolId:
|
||||
Value: !Ref 'IdentityPool'
|
||||
Description: Id for the identity pool
|
||||
IdentityPoolName:
|
||||
Value: !GetAtt IdentityPool.Name
|
||||
|
||||
|
||||
|
||||
|
||||
UserPoolId:
|
||||
Value: !Ref 'UserPool'
|
||||
Description: Id for the user pool
|
||||
UserPoolName:
|
||||
Value: !Ref userPoolName
|
||||
AppClientIDWeb:
|
||||
Value: !Ref 'UserPoolClientWeb'
|
||||
Description: The user pool app client id for web
|
||||
AppClientID:
|
||||
Value: !Ref 'UserPoolClient'
|
||||
Description: The user pool app client id
|
||||
AppClientSecret:
|
||||
Value: !GetAtt UserPoolClientInputs.appSecret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
60
Listify/amplify/backend/auth/listifyf4fad454/parameters.json
Normal file
60
Listify/amplify/backend/auth/listifyf4fad454/parameters.json
Normal file
@ -0,0 +1,60 @@
|
||||
{
|
||||
"identityPoolName": "listifyf4fad454_identitypool_f4fad454",
|
||||
"allowUnauthenticatedIdentities": true,
|
||||
"resourceNameTruncated": "listiff4fad454",
|
||||
"userPoolName": "listifyf4fad454_userpool_f4fad454",
|
||||
"autoVerifiedAttributes": [
|
||||
"email"
|
||||
],
|
||||
"mfaConfiguration": "OFF",
|
||||
"mfaTypes": [
|
||||
"SMS Text Message"
|
||||
],
|
||||
"smsAuthenticationMessage": "Your authentication code is {####}",
|
||||
"smsVerificationMessage": "Your verification code is {####}",
|
||||
"emailVerificationSubject": "Your verification code",
|
||||
"emailVerificationMessage": "Your verification code is {####}",
|
||||
"defaultPasswordPolicy": false,
|
||||
"passwordPolicyMinLength": 8,
|
||||
"passwordPolicyCharacters": [],
|
||||
"requiredAttributes": [
|
||||
"email"
|
||||
],
|
||||
"userpoolClientGenerateSecret": true,
|
||||
"userpoolClientRefreshTokenValidity": 30,
|
||||
"userpoolClientWriteAttributes": [
|
||||
"email"
|
||||
],
|
||||
"userpoolClientReadAttributes": [
|
||||
"email"
|
||||
],
|
||||
"userpoolClientLambdaRole": "listiff4fad454_userpoolclient_lambda_role",
|
||||
"userpoolClientSetAttributes": false,
|
||||
"sharedId": "f4fad454",
|
||||
"resourceName": "listifyf4fad454",
|
||||
"authSelections": "identityPoolAndUserPool",
|
||||
"authRoleArn": {
|
||||
"Fn::GetAtt": [
|
||||
"AuthRole",
|
||||
"Arn"
|
||||
]
|
||||
},
|
||||
"unauthRoleArn": {
|
||||
"Fn::GetAtt": [
|
||||
"UnauthRole",
|
||||
"Arn"
|
||||
]
|
||||
},
|
||||
"useDefault": "default",
|
||||
"usernameAttributes": [
|
||||
"email"
|
||||
],
|
||||
"triggers": "{}",
|
||||
"userPoolGroupList": [],
|
||||
"serviceName": "Cognito",
|
||||
"parentStack": {
|
||||
"Ref": "AWS::StackId"
|
||||
},
|
||||
"permissions": [],
|
||||
"dependsOn": []
|
||||
}
|
||||
12
Listify/amplify/backend/backend-config.json
Normal file
12
Listify/amplify/backend/backend-config.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"auth": {
|
||||
"listifyf4fad454": {
|
||||
"service": "Cognito",
|
||||
"providerPlugin": "awscloudformation",
|
||||
"dependsOn": [],
|
||||
"customAuth": false
|
||||
}
|
||||
},
|
||||
"function": {},
|
||||
"api": {}
|
||||
}
|
||||
10
Listify/amplify/backend/tags.json
Normal file
10
Listify/amplify/backend/tags.json
Normal file
@ -0,0 +1,10 @@
|
||||
[
|
||||
{
|
||||
"Key": "user:Stack",
|
||||
"Value": "{project-env}"
|
||||
},
|
||||
{
|
||||
"Key": "user:Application",
|
||||
"Value": "{project-name}"
|
||||
}
|
||||
]
|
||||
3
Listify/amplify/cli.json
Normal file
3
Listify/amplify/cli.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"features": {}
|
||||
}
|
||||
20
Listify/amplify/team-provider-info.json
Normal file
20
Listify/amplify/team-provider-info.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"dev": {
|
||||
"awscloudformation": {
|
||||
"AuthRoleName": "amplify-listify-dev-134836-authRole",
|
||||
"UnauthRoleArn": "arn:aws:iam::569815541706:role/amplify-listify-dev-134836-unauthRole",
|
||||
"AuthRoleArn": "arn:aws:iam::569815541706:role/amplify-listify-dev-134836-authRole",
|
||||
"Region": "us-east-2",
|
||||
"DeploymentBucketName": "amplify-listify-dev-134836-deployment",
|
||||
"UnauthRoleName": "amplify-listify-dev-134836-unauthRole",
|
||||
"StackName": "amplify-listify-dev-134836",
|
||||
"StackId": "arn:aws:cloudformation:us-east-2:569815541706:stack/amplify-listify-dev-134836/5980b520-faa0-11ea-a89c-0650659cf0f8",
|
||||
"AmplifyAppId": "dbnznhwtkbqz6"
|
||||
},
|
||||
"categories": {
|
||||
"auth": {
|
||||
"listifyf4fad454": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,13 +7,20 @@ android {
|
||||
defaultConfig {
|
||||
applicationId "com.example.listify"
|
||||
minSdkVersion 28
|
||||
targetSdkVersion 30
|
||||
targetSdkVersion 28
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
// Support for Java 8 features
|
||||
coreLibraryDesugaringEnabled true
|
||||
sourceCompatibility 1.8
|
||||
targetCompatibility 1.8
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
@ -23,7 +30,7 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'com.google.android.material:material:1.0.0'
|
||||
@ -34,5 +41,14 @@ dependencies {
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||
implementation 'com.amplifyframework:core:1.3.2'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10'
|
||||
implementation 'com.amplifyframework:aws-auth-cognito:1.3.2'
|
||||
implementation 'com.android.volley:volley:1.1.1'
|
||||
implementation 'com.google.code.gson:gson:2.8.6'
|
||||
compileOnly 'javax.annotation:javax.annotation-api:1.3.2'
|
||||
implementation 'org.json:json:20200518'
|
||||
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
|
||||
|
||||
}
|
||||
94
Listify/app/lib/glide/LICENSE
Normal file
94
Listify/app/lib/glide/LICENSE
Normal file
@ -0,0 +1,94 @@
|
||||
License for everything not in third_party and not otherwise marked:
|
||||
|
||||
Copyright 2014 Google, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are
|
||||
permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
of conditions and the following disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE, INC. OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those of the
|
||||
authors and should not be interpreted as representing official policies, either expressed
|
||||
or implied, of Google, Inc.
|
||||
---------------------------------------------------------------------------------------------
|
||||
License for third_party/disklrucache:
|
||||
|
||||
Copyright 2012 Jake Wharton
|
||||
Copyright 2011 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
---------------------------------------------------------------------------------------------
|
||||
License for third_party/gif_decoder:
|
||||
|
||||
Copyright (c) 2013 Xcellent Creations, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
---------------------------------------------------------------------------------------------
|
||||
License for third_party/gif_encoder/AnimatedGifEncoder.java and
|
||||
third_party/gif_encoder/LZWEncoder.java:
|
||||
|
||||
No copyright asserted on the source code of this class. May be used for any
|
||||
purpose, however, refer to the Unisys LZW patent for restrictions on use of
|
||||
the associated LZWEncoder class. Please forward any corrections to
|
||||
kweiner@fmsware.com.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
License for third_party/gif_encoder/NeuQuant.java
|
||||
|
||||
Copyright (c) 1994 Anthony Dekker
|
||||
|
||||
NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. See
|
||||
"Kohonen neural networks for optimal colour quantization" in "Network:
|
||||
Computation in Neural Systems" Vol. 5 (1994) pp 351-367. for a discussion of
|
||||
the algorithm.
|
||||
|
||||
Any party obtaining a copy of these files from the author, directly or
|
||||
indirectly, is granted, free of charge, a full and unrestricted irrevocable,
|
||||
world-wide, paid up, royalty-free, nonexclusive right and license to deal in
|
||||
this software and documentation files (the "Software"), including without
|
||||
limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Software, and to permit persons who
|
||||
receive copies from any such party to do so, with the only requirement being
|
||||
that this copyright notice remain intact.
|
||||
202
Listify/app/lib/glide/LICENSE-2.0.txt
Normal file
202
Listify/app/lib/glide/LICENSE-2.0.txt
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
BIN
Listify/app/lib/glide/glide-3.6.0.jar
Normal file
BIN
Listify/app/lib/glide/glide-3.6.0.jar
Normal file
Binary file not shown.
@ -1,14 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.listify">
|
||||
<uses-permission android:name = "android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:name=".Listify"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
android:theme="@style/AppTheme"
|
||||
android:usesCleartextTraffic="true">
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
@ -18,6 +22,14 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".SearchResults"
|
||||
android:label=""
|
||||
android:theme="@style/AppTheme.NoActionBar"
|
||||
>
|
||||
</activity>
|
||||
|
||||
<activity android:name="com.example.listify.ui.SignupPage" />
|
||||
<activity android:name="com.example.listify.ui.LoginPage" />
|
||||
</application>
|
||||
|
||||
139
Listify/app/src/main/java/com/example/listify/AuthManager.java
Normal file
139
Listify/app/src/main/java/com/example/listify/AuthManager.java
Normal file
@ -0,0 +1,139 @@
|
||||
package com.example.listify;
|
||||
|
||||
import android.content.Context;
|
||||
import com.amplifyframework.auth.AuthException;
|
||||
import com.amplifyframework.auth.AuthSession;
|
||||
import com.amplifyframework.auth.cognito.AWSCognitoAuthSession;
|
||||
import com.amplifyframework.auth.options.AuthSignUpOptions;
|
||||
import com.amplifyframework.auth.result.AuthSignInResult;
|
||||
import com.amplifyframework.auth.result.AuthSignUpResult;
|
||||
import com.amplifyframework.core.Amplify;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Properties;
|
||||
|
||||
public class AuthManager {
|
||||
AWSCognitoAuthSession authSession = null;
|
||||
AuthSignUpResult authSignUpResult = null;
|
||||
AuthSignInResult authSignInResult = null;
|
||||
AuthException authError = null;
|
||||
String email = null;
|
||||
String password = null;
|
||||
volatile boolean waiting = false;
|
||||
|
||||
|
||||
void fetchAuthSession() throws AuthException {
|
||||
waiting = true;
|
||||
Amplify.Auth.fetchAuthSession(
|
||||
result -> setAuthSession(result),
|
||||
error -> setAuthError(error)
|
||||
);
|
||||
throwIfAuthError();
|
||||
}
|
||||
|
||||
public AWSCognitoAuthSession getAuthSession() throws AuthException {
|
||||
if (authSession == null) {
|
||||
fetchAuthSession();
|
||||
}
|
||||
|
||||
return authSession;
|
||||
}
|
||||
|
||||
public String getUserToken() {
|
||||
return authSession.getUserPoolTokens().getValue().getIdToken();
|
||||
}
|
||||
|
||||
|
||||
public void setAuthSession(AuthSession toSet) {
|
||||
authSession = (AWSCognitoAuthSession) toSet;
|
||||
waiting = false;
|
||||
}
|
||||
|
||||
public void setAuthError(AuthException newError) {
|
||||
authError = newError;
|
||||
waiting = false;
|
||||
}
|
||||
|
||||
public void throwIfAuthError() throws AuthException{
|
||||
while (waiting);
|
||||
if (authError == null) {
|
||||
return;
|
||||
}
|
||||
AuthException toThrow = authError;
|
||||
authError = null;
|
||||
throw toThrow;
|
||||
}
|
||||
|
||||
public void setAuthSignUpResult(AuthSignUpResult toSet) {
|
||||
authSignUpResult = toSet;
|
||||
}
|
||||
|
||||
public void setAuthSignInResult(AuthSignInResult toSet) {
|
||||
authSignInResult = toSet;
|
||||
waiting = false;
|
||||
}
|
||||
|
||||
public void startSignUp(String email, String password) throws AuthException {
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
waiting = true;
|
||||
Amplify.Auth.signUp(
|
||||
email,
|
||||
password,
|
||||
AuthSignUpOptions.builder().build(),
|
||||
result -> setAuthSignUpResult(result),
|
||||
error -> setAuthError(error)
|
||||
);
|
||||
throwIfAuthError();
|
||||
|
||||
}
|
||||
|
||||
public void confirmSignUp(String confirmationCode) throws AuthException {
|
||||
waiting = true;
|
||||
Amplify.Auth.confirmSignUp(
|
||||
email,
|
||||
confirmationCode,
|
||||
result -> setAuthSignUpResult(result),
|
||||
error -> setAuthError(error)
|
||||
);
|
||||
throwIfAuthError();
|
||||
}
|
||||
|
||||
public void signIn(String email, String password) throws AuthException{
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
waiting = true;
|
||||
Amplify.Auth.signIn(
|
||||
email,
|
||||
password,
|
||||
result -> setAuthSignInResult(result),
|
||||
error -> setAuthError(error)
|
||||
);
|
||||
throwIfAuthError();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static Properties loadProperties(Context context, String path) throws IOException, JSONException {
|
||||
Properties toReturn = new Properties();
|
||||
String propertiesJSONString = "";
|
||||
for (Object line : new BufferedReader(new InputStreamReader(context.getResources().openRawResource(R.raw.auths))).lines().toArray()) {
|
||||
propertiesJSONString += line.toString();
|
||||
}
|
||||
System.out.println(propertiesJSONString);
|
||||
JSONObject propertiesJSON = new JSONObject(propertiesJSONString);
|
||||
propertiesJSON.keys().forEachRemaining(key -> {
|
||||
try {
|
||||
toReturn.setProperty(key, propertiesJSON.get(key).toString());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
System.out.println(toReturn);
|
||||
return toReturn;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.example.listify;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.navigation.fragment.NavHostFragment;
|
||||
|
||||
public class First2Fragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public View onCreateView(
|
||||
LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState
|
||||
) {
|
||||
// Inflate the layout for this fragment
|
||||
return inflater.inflate(R.layout.fragment_first2, container, false);
|
||||
}
|
||||
|
||||
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
view.findViewById(R.id.button_first).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
NavHostFragment.findNavController(First2Fragment.this)
|
||||
.navigate(R.id.action_First2Fragment_to_Second2Fragment);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.example.listify;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.navigation.fragment.NavHostFragment;
|
||||
|
||||
public class FirstFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public View onCreateView(
|
||||
LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState
|
||||
) {
|
||||
// Inflate the layout for this fragment
|
||||
return inflater.inflate(R.layout.fragment_first, container, false);
|
||||
}
|
||||
|
||||
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
view.findViewById(R.id.button_first).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
NavHostFragment.findNavController(FirstFragment.this)
|
||||
.navigate(R.id.action_FirstFragment_to_SecondFragment);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
8
Listify/app/src/main/java/com/example/listify/List.java
Normal file
8
Listify/app/src/main/java/com/example/listify/List.java
Normal file
@ -0,0 +1,8 @@
|
||||
package com.example.listify;
|
||||
|
||||
public class List {
|
||||
String name;
|
||||
List(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
20
Listify/app/src/main/java/com/example/listify/Listify.java
Normal file
20
Listify/app/src/main/java/com/example/listify/Listify.java
Normal file
@ -0,0 +1,20 @@
|
||||
package com.example.listify;
|
||||
|
||||
import android.util.Log;
|
||||
import com.amplifyframework.AmplifyException;
|
||||
import com.amplifyframework.auth.cognito.AWSCognitoAuthPlugin;
|
||||
import com.amplifyframework.core.Amplify;
|
||||
|
||||
public class Listify extends android.app.Application {
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
try {
|
||||
Amplify.addPlugin(new AWSCognitoAuthPlugin());
|
||||
Amplify.configure(getApplicationContext());
|
||||
Log.i("MyAmplifyApp", "Initialized Amplify");
|
||||
} catch (AmplifyException error) {
|
||||
Log.e("MyAmplifyApp", "Could not initialize Amplify", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,20 +1,23 @@
|
||||
package com.example.listify;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.Menu;
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.android.material.navigation.NavigationView;
|
||||
|
||||
import android.widget.ImageButton;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.Navigation;
|
||||
import androidx.navigation.ui.AppBarConfiguration;
|
||||
import androidx.navigation.ui.NavigationUI;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import com.amplifyframework.auth.AuthException;
|
||||
import com.google.android.material.navigation.NavigationView;
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
private AppBarConfiguration mAppBarConfiguration;
|
||||
@ -22,17 +25,57 @@ public class MainActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
//------------------------------Auth Testing---------------------------------------------//
|
||||
|
||||
AuthManager authManager = new AuthManager();
|
||||
try {
|
||||
authManager.signIn("merzn@purdue.edu", "Password123");
|
||||
Log.i("Authentication", authManager.getAuthSession().toString());
|
||||
Log.i("Token", authManager.getAuthSession().getUserPoolTokens().getValue().getIdToken());
|
||||
} catch (AuthException e) {
|
||||
Log.i("Authentication", "Login failed. User probably needs to register. Exact error: " + e.getMessage());
|
||||
try {
|
||||
authManager.startSignUp("merzn@purdue.edu", "Password123");
|
||||
authManager.confirmSignUp("######");
|
||||
} catch (AuthException signUpError) {
|
||||
Log.e("Authentication", "SignUp error: " + signUpError.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------------//
|
||||
|
||||
//----------------------------------API Testing---------------------------------------------//
|
||||
Properties configs = new Properties();
|
||||
try {
|
||||
configs = AuthManager.loadProperties(this, "android.resource://" + getPackageName() + "/raw/auths.json");
|
||||
} catch (IOException|JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
Requestor requestor = new Requestor(this, authManager,configs.getProperty("apiKey"));
|
||||
List testList = new List("IAmATestList");
|
||||
try {
|
||||
requestor.postObject(testList);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------//
|
||||
|
||||
|
||||
setContentView(R.layout.activity_main);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
FloatingActionButton fab = 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();
|
||||
}
|
||||
});
|
||||
// FloatingActionButton fab = 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();
|
||||
// }
|
||||
// });
|
||||
DrawerLayout drawer = findViewById(R.id.drawer_layout);
|
||||
NavigationView navigationView = findViewById(R.id.nav_view);
|
||||
// Passing each menu ID as a set of Ids because each
|
||||
@ -44,14 +87,29 @@ public class MainActivity extends AppCompatActivity {
|
||||
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
|
||||
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
|
||||
NavigationUI.setupWithNavController(navigationView, navController);
|
||||
|
||||
// Handle search button click
|
||||
ImageButton searchButton = (ImageButton) findViewById(R.id.searchButton);
|
||||
searchButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(MainActivity.this, SearchResults.class);
|
||||
|
||||
// Send user to SearchResults activity
|
||||
startActivity(intent);
|
||||
overridePendingTransition(R.anim.enter_from_left, R.anim.exit_from_left);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.main, menu);
|
||||
return true;
|
||||
}
|
||||
// @Override
|
||||
// public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// // Inflate the menu; this adds items to the action bar if it is present.
|
||||
// getMenuInflater().inflate(R.menu.main, menu);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onSupportNavigateUp() {
|
||||
|
||||
66
Listify/app/src/main/java/com/example/listify/Requestor.java
Normal file
66
Listify/app/src/main/java/com/example/listify/Requestor.java
Normal file
@ -0,0 +1,66 @@
|
||||
package com.example.listify;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import com.android.volley.RequestQueue;
|
||||
import com.android.volley.Response;
|
||||
import com.android.volley.toolbox.JsonObjectRequest;
|
||||
import com.android.volley.toolbox.Volley;
|
||||
import com.google.gson.Gson;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Requestor {
|
||||
|
||||
private final String DEV_BASEURL = "https://datoh7woc9.execute-api.us-east-2.amazonaws.com/Development";
|
||||
|
||||
AuthManager authManager;
|
||||
RequestQueue queue;
|
||||
String apiKey;
|
||||
|
||||
Requestor(Context context, AuthManager authManager, String apiKey) {
|
||||
queue = Volley.newRequestQueue(context);
|
||||
this.authManager = authManager;
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
|
||||
public <T> void getObject(String id, Class<T> classType, Receiver<T> receiver) {
|
||||
String getURL = DEV_BASEURL + "/" + classType.getSimpleName() + "?id=" + id;
|
||||
}
|
||||
|
||||
public void postObject(Object toPost, Response.ErrorListener failureHandler) throws JSONException {
|
||||
String postURL = DEV_BASEURL + "/" + toPost.getClass().getSimpleName();
|
||||
queue.add(buildRequest(postURL, toPost, null, failureHandler));
|
||||
}
|
||||
|
||||
public void postObject(Object toPost) throws JSONException {
|
||||
postObject(toPost, null);
|
||||
}
|
||||
|
||||
private JsonObjectRequest buildRequest(String url, Object toJSONify, Response.Listener<JSONObject> successHandler, Response.ErrorListener failureHandler) throws JSONException {
|
||||
return buildRequest(url, new JSONObject(new Gson().toJson(toJSONify)), successHandler, failureHandler);
|
||||
}
|
||||
|
||||
private JsonObjectRequest buildRequest(String url, JSONObject jsonBody, Response.Listener<JSONObject> successHandler, Response.ErrorListener failureHandler) {
|
||||
return new JsonObjectRequest(url, jsonBody, successHandler, failureHandler) {
|
||||
@Override
|
||||
public Map<String, String> getHeaders() {
|
||||
HashMap<String, String> headers = new HashMap<>();
|
||||
System.out.println(authManager.getUserToken());
|
||||
headers.put("Authorization", authManager.getUserToken());
|
||||
headers.put("Content-Type", "application/json");
|
||||
headers.put("X-API-Key", apiKey);
|
||||
return headers;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public class Receiver<T> {
|
||||
public void acceptDelivery(T delivered) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
118
Listify/app/src/main/java/com/example/listify/SearchResults.java
Normal file
118
Listify/app/src/main/java/com/example/listify/SearchResults.java
Normal file
@ -0,0 +1,118 @@
|
||||
package com.example.listify;
|
||||
import android.media.Image;
|
||||
import android.os.Bundle;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SearchView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.example.listify.adapter.SearchResultsListAdapter;
|
||||
import com.example.listify.model.Product;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SearchResults extends AppCompatActivity {
|
||||
private ListView listView;
|
||||
private SearchResultsListAdapter searchResultsListAdapter;
|
||||
private List<Product> productList = new ArrayList<>();
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_search_results);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
// Back button closes this activity and returns to previous activity (MainActivity)
|
||||
ImageButton backButton = (ImageButton) findViewById(R.id.backToHomeButton);
|
||||
backButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finish();
|
||||
overridePendingTransition(R.anim.enter_from_right, R.anim.exit_from_right);
|
||||
}
|
||||
});
|
||||
|
||||
// Set the search bar to be active and focused
|
||||
final SearchView searchView = (SearchView) findViewById(R.id.searchBar);
|
||||
searchView.setIconified(false);
|
||||
|
||||
// There's no easy way to find the close button on the search bar, so this is the way I'm
|
||||
// doing it
|
||||
int searchCloseButtonId = searchView.getContext().getResources().getIdentifier("android:id/search_close_btn", null, null);
|
||||
ImageView closeButton = (ImageView) searchView.findViewById(searchCloseButtonId);
|
||||
closeButton.setOnClickListener(new View.OnClickListener() {
|
||||
// Override default close behavior to only clear the search text and the query
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// Finding the edit text of the search bar. Same as the method above
|
||||
int searchTextId = searchView.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
|
||||
EditText searchText = (EditText) searchView.findViewById(searchTextId);
|
||||
searchText.setText("");
|
||||
searchView.setQuery("", false);
|
||||
}
|
||||
});
|
||||
|
||||
listView = (ListView) findViewById(R.id.search_results_list);
|
||||
searchResultsListAdapter = new SearchResultsListAdapter(this, productList);
|
||||
listView.setAdapter(searchResultsListAdapter);
|
||||
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
Toast.makeText(SearchResults.this, productList.get(position).getItemName(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
||||
// Handle searches
|
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String query) {
|
||||
|
||||
doSearch(query);
|
||||
// TODO: Display the search results listview
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(String newText) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Override default phone back button to add animation
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
super.onBackPressed();
|
||||
overridePendingTransition(R.anim.enter_from_right, R.anim.exit_from_right);
|
||||
}
|
||||
|
||||
// TODO: This function will handle the search operation with the database and return
|
||||
// a listview to caller to be displayed
|
||||
private ListView doSearch(String query) {
|
||||
// Hardcode some search results...
|
||||
Product a = new Product("Bottled Water", "0000", "Walmart", "0001", "0123456780", "Bro, it's water...", "Grocery", "$13.37", "9/24/2020", "1", "http://3.bp.blogspot.com/-MfroPPQVDKo/UyhUZWqGvkI/AAAAAAAAB-I/DGk622onsvc/s1600/lettuce-b-kool-cat-meme.jpg");
|
||||
Product b = new Product("Tin Foil", "0001", "Walmart", "0001", "0123456781", "Not aluminum foil", "Grocery", "$1.00", "9/24/2020", "1", "https://i.ytimg.com/vi/q9N1doYMxR0/maxresdefault.jpg");
|
||||
Product c = new Product("Lettuce", "0002", "Walmart", "0001", "0123456782", "It's still wet", "Grocery", "$0.60", "9/24/2020", "1", "https://www.cattitudedaily.com/wp-content/uploads/2019/12/white-cat-meme-feature.jpg");
|
||||
Product d = new Product("Video Game", "0003", "Walmart", "0001", "0123456783", "Fun Vidya Gaemz", "Electronics", "$60.00", "9/24/2020", "1", "https://i1.wp.com/bestlifeonline.com/wp-content/uploads/2018/06/cat-meme-67.jpg?resize=1024%2C1024&ssl=1");
|
||||
Product e = new Product("Mountain Dew", "0004", "Walmart", "0001", "0123456784", "Gamer fuel", "Grocery", "$5.87", "9/24/2020", "1", "https://memeguy.com/photos/images/gaming-cat-7680.png");
|
||||
Product f = new Product("Tire", "0005", "Walmart", "0001", "0123456785", "30 inch rims", "Automotive", "$146.97", "9/24/2020", "1", "http://cdn.sheknows.com/articles/2013/05/pet5.jpg");
|
||||
productList.add(a);
|
||||
productList.add(b);
|
||||
productList.add(c);
|
||||
productList.add(d);
|
||||
productList.add(e);
|
||||
productList.add(f);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.example.listify;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.navigation.fragment.NavHostFragment;
|
||||
|
||||
public class Second2Fragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public View onCreateView(
|
||||
LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState
|
||||
) {
|
||||
// Inflate the layout for this fragment
|
||||
return inflater.inflate(R.layout.fragment_second2, container, false);
|
||||
}
|
||||
|
||||
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
view.findViewById(R.id.button_second).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
NavHostFragment.findNavController(Second2Fragment.this)
|
||||
.navigate(R.id.action_Second2Fragment_to_First2Fragment);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.example.listify;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.navigation.fragment.NavHostFragment;
|
||||
|
||||
public class SecondFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public View onCreateView(
|
||||
LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState
|
||||
) {
|
||||
// Inflate the layout for this fragment
|
||||
return inflater.inflate(R.layout.fragment_second, container, false);
|
||||
}
|
||||
|
||||
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
view.findViewById(R.id.button_second).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
NavHostFragment.findNavController(SecondFragment.this)
|
||||
.navigate(R.id.action_SecondFragment_to_FirstFragment);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package com.example.listify.adapter;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.example.listify.model.Product;
|
||||
import com.example.listify.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SearchResultsListAdapter extends BaseAdapter {
|
||||
private Activity activity;
|
||||
private List<Product> productList;
|
||||
private LayoutInflater inflater;
|
||||
|
||||
public SearchResultsListAdapter(Activity activity, List<Product> productList){
|
||||
this.activity = activity;
|
||||
this.productList = productList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return productList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return productList.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
if(inflater == null){
|
||||
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
}if(convertView == null){
|
||||
convertView = inflater.inflate(R.layout.search_list_item, null);
|
||||
}
|
||||
|
||||
ImageView productImage = (ImageView) convertView.findViewById(R.id.item_image);
|
||||
TextView itemName = (TextView) convertView.findViewById(R.id.item_name);
|
||||
TextView description = (TextView) convertView.findViewById(R.id.item_desc);
|
||||
TextView price = (TextView) convertView.findViewById(R.id.item_price);
|
||||
|
||||
Product product = productList.get(position);
|
||||
// product.loadImageView(0, 0, productImage);
|
||||
Glide.with(activity).load(product.getImageUrl()).into(productImage);
|
||||
itemName.setText(product.getItemName());
|
||||
description.setText(product.getDescription());
|
||||
price.setText(product.getPrice());
|
||||
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
168
Listify/app/src/main/java/com/example/listify/model/Product.java
Normal file
168
Listify/app/src/main/java/com/example/listify/model/Product.java
Normal file
@ -0,0 +1,168 @@
|
||||
package com.example.listify.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.example.listify.R;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public class Product {
|
||||
private String itemName;
|
||||
private String itemId;
|
||||
private String chainName;
|
||||
private String chainId;
|
||||
private String upc;
|
||||
private String description;
|
||||
private String department;
|
||||
private String price;
|
||||
private String retrievedDate;
|
||||
private String fetchCounts;
|
||||
private String imageUrl;
|
||||
|
||||
public Product() {}
|
||||
|
||||
public Product(String itemName, String itemId, String chainName, String chainId, String upc,
|
||||
String description, String department, String price, String retrievedDate,
|
||||
String fetchCounts, String imageUrl) {
|
||||
this.itemName = itemName;
|
||||
this.itemId = itemId;
|
||||
this.chainName = chainName;
|
||||
this.chainId = chainId;
|
||||
this.upc = upc;
|
||||
this.description = description;
|
||||
this.department = department;
|
||||
this.price = price;
|
||||
this.retrievedDate = retrievedDate;
|
||||
this.fetchCounts = fetchCounts;
|
||||
this.imageUrl = imageUrl;
|
||||
}
|
||||
|
||||
// private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
|
||||
// ImageView imageView;
|
||||
//
|
||||
// public DownloadImageTask(ImageView imageView) {
|
||||
// this.imageView = imageView;
|
||||
// }
|
||||
//
|
||||
// protected Bitmap doInBackground(String... args) {
|
||||
// String url = args[0];
|
||||
// Bitmap image = null;
|
||||
// try {
|
||||
// InputStream in = new java.net.URL(url).openStream();
|
||||
// image = BitmapFactory.decodeStream(in);
|
||||
// } catch (Exception e) {
|
||||
// Log.e("Error", e.getMessage());
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// return image;
|
||||
// }
|
||||
//
|
||||
// protected void onPostExecute(Bitmap result) {
|
||||
// // Return the broken image icon as a bitmap if the url is invalid
|
||||
// if (result == null) {
|
||||
// imageView.setImageResource(R.drawable.ic_baseline_broken_image_600);
|
||||
// } else {
|
||||
// imageView.setImageBitmap(result);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
public String getItemName() {
|
||||
return itemName;
|
||||
}
|
||||
|
||||
public void setItemName(String itemName) {
|
||||
this.itemName = itemName;
|
||||
}
|
||||
|
||||
public String getItemId() {
|
||||
return itemId;
|
||||
}
|
||||
|
||||
public void setItemId(String itemId) {
|
||||
this.itemId = itemId;
|
||||
}
|
||||
|
||||
public String getChainName() {
|
||||
return chainName;
|
||||
}
|
||||
|
||||
public void setChainName(String chainName) {
|
||||
this.chainName = chainName;
|
||||
}
|
||||
|
||||
public String getChainId() {
|
||||
return chainId;
|
||||
}
|
||||
|
||||
public void setChainId(String chainId) {
|
||||
this.chainId = chainId;
|
||||
}
|
||||
|
||||
public String getUpc() {
|
||||
return upc;
|
||||
}
|
||||
|
||||
public void setUpc(String upc) {
|
||||
this.upc = upc;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getDepartment() {
|
||||
return department;
|
||||
}
|
||||
|
||||
public void setDepartment(String department) {
|
||||
this.department = department;
|
||||
}
|
||||
|
||||
public String getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(String price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public String getRetrievedDate() {
|
||||
return retrievedDate;
|
||||
}
|
||||
|
||||
public void setRetrievedDate(String retrievedDate) {
|
||||
this.retrievedDate = retrievedDate;
|
||||
}
|
||||
|
||||
public String getFetchCounts() {
|
||||
return fetchCounts;
|
||||
}
|
||||
|
||||
public void setFetchCounts(String fetchCounts) {
|
||||
this.fetchCounts = fetchCounts;
|
||||
}
|
||||
|
||||
public String getImageUrl() {
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
public void setImageUrl(String imageUrl) {
|
||||
this.imageUrl = imageUrl;
|
||||
}
|
||||
|
||||
// // TODO: Need to implement image resizing
|
||||
// public void loadImageView(int height, int width, ImageView imageView) {
|
||||
// new DownloadImageTask(imageView).execute(this.imageUrl);
|
||||
// }
|
||||
}
|
||||
8
Listify/app/src/main/res/anim/enter_from_left.xml
Normal file
8
Listify/app/src/main/res/anim/enter_from_left.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="300"
|
||||
android:fromXDelta="100%"
|
||||
android:toXDelta="0%" >
|
||||
</translate>
|
||||
</set>
|
||||
8
Listify/app/src/main/res/anim/enter_from_right.xml
Normal file
8
Listify/app/src/main/res/anim/enter_from_right.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="300"
|
||||
android:fromXDelta="-100%"
|
||||
android:toXDelta="0%" >
|
||||
</translate>
|
||||
</set>
|
||||
8
Listify/app/src/main/res/anim/exit_from_left.xml
Normal file
8
Listify/app/src/main/res/anim/exit_from_left.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="300"
|
||||
android:fromXDelta="0%"
|
||||
android:toXDelta="-100%" >
|
||||
</translate>
|
||||
</set>
|
||||
8
Listify/app/src/main/res/anim/exit_from_right.xml
Normal file
8
Listify/app/src/main/res/anim/exit_from_right.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="300"
|
||||
android:fromXDelta="0%"
|
||||
android:toXDelta="100%" >
|
||||
</translate>
|
||||
</set>
|
||||
@ -0,0 +1,5 @@
|
||||
<vector android:height="600dp" android:tint="?attr/colorControlNormal"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="600dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M21,5v6.59l-3,-3.01 -4,4.01 -4,-4 -4,4 -3,-3.01L3,5c0,-1.1 0.9,-2 2,-2h14c1.1,0 2,0.9 2,2zM18,11.42l3,3.01L21,19c0,1.1 -0.9,2 -2,2L5,21c-1.1,0 -2,-0.9 -2,-2v-6.58l3,2.99 4,-4 4,4 4,-3.99z"/>
|
||||
</vector>
|
||||
@ -8,8 +8,13 @@
|
||||
android:fitsSystemWindows="true"
|
||||
tools:openDrawer="start">
|
||||
|
||||
<!-- <include-->
|
||||
<!-- layout="@layout/app_bar_main"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="match_parent" />-->
|
||||
|
||||
<include
|
||||
layout="@layout/app_bar_main"
|
||||
layout="@layout/app_bar_home"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
|
||||
45
Listify/app/src/main/res/layout/activity_search_results.xml
Normal file
45
Listify/app/src/main/res/layout/activity_search_results.xml
Normal file
@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".SearchResults">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/AppTheme.AppBarOverlay">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay"
|
||||
>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/backToHomeButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
app:srcCompat="@drawable/abc_vector_test"
|
||||
android:background="@null"
|
||||
android:contentDescription="@string/backButton"/>
|
||||
|
||||
<SearchView
|
||||
android:id="@+id/searchBar"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="50dp"
|
||||
android:queryHint="Search Here"
|
||||
>
|
||||
</SearchView>
|
||||
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_search_results" />\
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
46
Listify/app/src/main/res/layout/app_bar_home.xml
Normal file
46
Listify/app/src/main/res/layout/app_bar_home.xml
Normal file
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/AppTheme.AppBarOverlay">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay" >
|
||||
<ImageButton
|
||||
android:id="@+id/searchButton"
|
||||
android:layout_width="30dp"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@android:drawable/ic_menu_search"
|
||||
android:contentDescription="@string/search_button_desc"
|
||||
android:background="@null"/>
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_main" />
|
||||
|
||||
<!-- <com.google.android.material.floatingactionbutton.FloatingActionButton-->
|
||||
<!-- android:id="@+id/fab"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_gravity="bottom|end"-->
|
||||
<!-- android:layout_margin="@dimen/fab_margin"-->
|
||||
<!-- app:srcCompat="@android:drawable/ic_dialog_email" />-->
|
||||
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
24
Listify/app/src/main/res/layout/content_search_results.xml
Normal file
24
Listify/app/src/main/res/layout/content_search_results.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:context=".SearchResults"
|
||||
tools:showIn="@layout/activity_search_results">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/search_results_list"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:divider="@color/list_divider"
|
||||
android:dividerHeight="1dp"/>
|
||||
<!-- android:listSelector="@drawable/list_row_selector"-->
|
||||
<!-- />-->
|
||||
|
||||
</RelativeLayout>
|
||||
28
Listify/app/src/main/res/layout/fragment_first.xml
Normal file
28
Listify/app/src/main/res/layout/fragment_first.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".FirstFragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textview_first"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/hello_first_fragment"
|
||||
app:layout_constraintBottom_toTopOf="@id/button_first"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_first"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/next"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/textview_first" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
28
Listify/app/src/main/res/layout/fragment_first2.xml
Normal file
28
Listify/app/src/main/res/layout/fragment_first2.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".First2Fragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textview_first"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/hello_first_fragment"
|
||||
app:layout_constraintBottom_toTopOf="@id/button_first"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_first"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/next"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/textview_first" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
27
Listify/app/src/main/res/layout/fragment_second.xml
Normal file
27
Listify/app/src/main/res/layout/fragment_second.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".SecondFragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textview_second"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toTopOf="@id/button_second"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_second"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/previous"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/textview_second" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
27
Listify/app/src/main/res/layout/fragment_second2.xml
Normal file
27
Listify/app/src/main/res/layout/fragment_second2.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".Second2Fragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textview_second"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toTopOf="@id/button_second"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_second"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/previous"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/textview_second" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
72
Listify/app/src/main/res/layout/search_list_item.xml
Normal file
72
Listify/app/src/main/res/layout/search_list_item.xml
Normal file
@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="6dp"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingBottom="6dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/item_image"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="40dp"
|
||||
android:src="@drawable/ic_baseline_broken_image_600"
|
||||
android:layout_alignTop="@+id/linearLayout"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAllCaps="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:text=""
|
||||
android:textSize="15dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:gravity="center"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:id="@+id/linearLayout">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_desc"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="12sp"
|
||||
android:text="" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentBottom="true">
|
||||
<TextView
|
||||
android:id="@+id/item_price_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Price: "
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_price"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="12sp"
|
||||
android:text="" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
@ -3,7 +3,12 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:orderInCategory="100"
|
||||
android:orderInCategory="101"
|
||||
android:title="@string/action_settings"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/action_settings1"
|
||||
android:orderInCategory="101"
|
||||
android:title="@string/action_settings"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
||||
48
Listify/app/src/main/res/navigation/nav_graph.xml
Normal file
48
Listify/app/src/main/res/navigation/nav_graph.xml
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/nav_graph"
|
||||
app:startDestination="@id/FirstFragment">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/FirstFragment"
|
||||
android:name="com.example.listify.FirstFragment"
|
||||
android:label="@string/first_fragment_label"
|
||||
tools:layout="@layout/fragment_first">
|
||||
|
||||
<action
|
||||
android:id="@+id/action_FirstFragment_to_SecondFragment"
|
||||
app:destination="@id/SecondFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/SecondFragment"
|
||||
android:name="com.example.listify.SecondFragment"
|
||||
android:label="@string/second_fragment_label"
|
||||
tools:layout="@layout/fragment_second">
|
||||
|
||||
<action
|
||||
android:id="@+id/action_SecondFragment_to_FirstFragment"
|
||||
app:destination="@id/FirstFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/First2Fragment"
|
||||
android:name="com.example.listify.First2Fragment"
|
||||
android:label="@string/first_fragment_label"
|
||||
tools:layout="@layout/fragment_first2">
|
||||
|
||||
<action
|
||||
android:id="@+id/action_First2Fragment_to_Second2Fragment"
|
||||
app:destination="@id/Second2Fragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/Second2Fragment"
|
||||
android:name="com.example.listify.Second2Fragment"
|
||||
android:label="@string/second_fragment_label"
|
||||
tools:layout="@layout/fragment_second2">
|
||||
|
||||
<action
|
||||
android:id="@+id/action_Second2Fragment_to_First2Fragment"
|
||||
app:destination="@id/First2Fragment" />
|
||||
</fragment>
|
||||
</navigation>
|
||||
@ -3,4 +3,11 @@
|
||||
<color name="colorPrimary">#6200EE</color>
|
||||
<color name="colorPrimaryDark">#3700B3</color>
|
||||
<color name="colorAccent">#03DAC5</color>
|
||||
|
||||
<color name="tabsScrollColor">#2097ff</color>
|
||||
<color name="list_divider">#d9d9d9</color>
|
||||
<color name="list_row_start_color">#ffffff</color>
|
||||
<color name="list_row_end_color">#ffffff</color>
|
||||
<color name="list_row_hover_start_color">#ebeef0</color>
|
||||
<color name="list_row_hover_end_color">#1c9ef4</color>
|
||||
</resources>
|
||||
@ -10,4 +10,19 @@
|
||||
<string name="menu_home">Home</string>
|
||||
<string name="menu_gallery">Gallery</string>
|
||||
<string name="menu_slideshow">Slideshow</string>
|
||||
|
||||
<string name="app_label">Listify</string>
|
||||
<string name="search_hint">Search Test</string>
|
||||
<string name="title_activity_search">SearchActivity</string>
|
||||
<!-- Strings used for fragments for navigation -->
|
||||
<string name="first_fragment_label">First Fragment</string>
|
||||
<string name="second_fragment_label">Second Fragment</string>
|
||||
<string name="next">Next</string>
|
||||
<string name="previous">Previous</string>
|
||||
<string name="backButton">Back Button</string>
|
||||
|
||||
<string name="hello_first_fragment">Hello first fragment</string>
|
||||
<string name="hello_second_fragment">Hello second fragment. Arg: %1$s</string>
|
||||
<string name="search_button_desc">Search Button</string>
|
||||
<string name="title_activity_search_results">SearchResults</string>
|
||||
</resources>
|
||||
5
Listify/app/src/main/res/xml/searchable.xml
Normal file
5
Listify/app/src/main/res/xml/searchable.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:label="@string/app_label"
|
||||
android:hint="@string/search_hint" >
|
||||
</searchable>
|
||||
@ -19,6 +19,7 @@ allprojects {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
|
||||
BIN
Listify/gradle/wrapper/gradle-wrapper.jar
vendored
BIN
Listify/gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
@ -1,6 +1,5 @@
|
||||
#Fri Sep 18 14:57:14 EDT 2020
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
|
||||
|
||||
53
Listify/gradlew
vendored
Normal file → Executable file
53
Listify/gradlew
vendored
Normal file → Executable file
@ -1,5 +1,21 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
@ -28,7 +44,7 @@ APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
@ -66,6 +82,7 @@ esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
@ -109,10 +126,11 @@ if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
@ -138,19 +156,19 @@ if $cygwin ; then
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
@ -159,14 +177,9 @@ save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
||||
43
Listify/gradlew.bat
vendored
43
Listify/gradlew.bat
vendored
@ -1,3 +1,19 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
@ -35,7 +54,7 @@ goto fail
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
@ -45,28 +64,14 @@ echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
||||
55
Tooling/EndpointSetup.sh
Normal file
55
Tooling/EndpointSetup.sh
Normal file
@ -0,0 +1,55 @@
|
||||
#!/bin/bash
|
||||
#Base script from: https://github.com/NMerz/DoctorsNote/blob/master/AWS%20Setup/Lambda-GatewayInitialization.sh
|
||||
|
||||
#NOTE: This has been tested and works; however, the apigateway does not properly show as a trigger in AWS's web UI
|
||||
#NOTE2: This assumes that the root Gateway and Lambda role have been set up previously (one-time setup) and their values are set in VarSetup.sh
|
||||
|
||||
echo "Creating a Gateway/Lambda pair."
|
||||
|
||||
REL_SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
|
||||
source ${REL_SCRIPT_DIR}/VarSetup.sh
|
||||
|
||||
|
||||
RAWLAMBDA=$(aws lambda create-function --function-name ${functionName}${method} --zip-file fileb://${jarPath} --runtime ${LANGUAGE} --role ${LAMBDAROLE} --handler ${functionName}${method} 2>${DEBUGFILE})
|
||||
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Unable to create Lamba" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LAMBDAARN=$(echo $RAWLAMBDA | head -n 3 | tail -n 1 | cut -d \" -f 8)
|
||||
|
||||
echo ${LAMBDAARN} > ${DEBUGFILE}
|
||||
|
||||
RAWRESOURCEID=$(aws apigateway create-resource --rest-api-id ${APIID} --parent-id ${ROOTRESOURCEID} --path-part ${functionName} 2>${DEBUGFILE})
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Unable to create resource." > ${DEBUGFILE}
|
||||
RAWRESOURCEID=$(aws apigateway get-resources --rest-api-id datoh7woc9 --query "items[?pathPart==\`${functionName}\`].{id:id}" | head -n 3 | tail -n 1)
|
||||
if [[ $RAWRESOURCEID == "[]" ]]; then
|
||||
echo "Unable to create or find API Gateway resource." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
RESOURCEID=$(echo ${RAWRESOURCEID} | head -n 2 | tail -n 1 | cut -d \" -f 4)
|
||||
|
||||
echo ${RESOURCEID} > ${DEBUGFILE}
|
||||
|
||||
aws apigateway put-method --rest-api-id ${APIID} --resource-id ${RESOURCEID} --http-method ${method} --authorization-type COGNITO_USER_POOLS --authorizer-id awt4cs --api-key-required > ${DEBUGFILE}
|
||||
|
||||
|
||||
|
||||
aws apigateway put-integration --rest-api-id ${APIID} --resource-id ${RESOURCEID} --http-method ${method} --type AWS --integration-http-method POST --uri arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/${LAMBDAARN}/invocations --request-templates "file://${REL_SCRIPT_DIR}/body_and_auth_mapping.json" --passthrough-behavior NEVER > ${DEBUGFILE}
|
||||
|
||||
aws lambda add-permission --function-name ${functionName}${method} --statement-id ${functionName}API --action lambda:InvokeFunction --principal apigateway.amazonaws.com > ${DEBUGFILE}
|
||||
|
||||
aws apigateway put-method-response --rest-api-id ${APIID} --resource-id ${RESOURCEID} --http-method ${method} --status-code 200 > ${DEBUGFILE}
|
||||
|
||||
aws apigateway put-integration-response --rest-api-id ${APIID} --resource-id ${RESOURCEID} --http-method ${method} --status-code 200 --selection-pattern "" > ${DEBUGFILE}
|
||||
|
||||
aws apigateway create-deployment --rest-api-id ${APIID} --stage-name ${DEPLOYSTAGE} --description "Deployment by creation script for function ${functionName}${method}" > ${DEBUGFILE}
|
||||
|
||||
|
||||
17
Tooling/LambdaUpdate.sh
Normal file
17
Tooling/LambdaUpdate.sh
Normal file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
echo "Updating a Lambda."
|
||||
|
||||
REL_SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
|
||||
source ${REL_SCRIPT_DIR}/VarSetup.sh
|
||||
|
||||
|
||||
aws lambda update-function-code --function-name ${functionName}${method} --zip-file fileb://${jarPath} 1>${DEBUGFILE} 2>${DEBUGFILE}
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Unable to update Lamba" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Update successful."
|
||||
exit 0
|
||||
26
Tooling/VarSetup.sh
Normal file
26
Tooling/VarSetup.sh
Normal file
@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Meant to be source'd from other scripts that need these vars.
|
||||
|
||||
#constants
|
||||
APIID=datoh7woc9 #rest-api-id is tied to the apigateway while resource-id seems tied to the specific url extension
|
||||
ROOTRESOURCEID=6xrzhzidxh #gateway root should have a consistent resource id which will serve as parent for many apis
|
||||
LAMBDAROLE=arn:aws:iam::569815541706:role/LambdaBasic
|
||||
LANGUAGE=java11
|
||||
DEPLOYSTAGE=Development
|
||||
|
||||
DEBUGFILE=/dev/null
|
||||
|
||||
REL_SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
|
||||
echo -n "Please enter base function name: "
|
||||
read functionName
|
||||
echo -n "Please enter method(GET, POST, etc.): "
|
||||
read method
|
||||
|
||||
jarPath=$(find ${REL_SCRIPT_DIR}/.. -name "${functionName}.jar")
|
||||
if [[ "$jarPath" == "" ]]; then
|
||||
echo "Unable to find file ${functionName}.jar" >&2
|
||||
exit 1
|
||||
fi
|
||||
functionPath=${jarPath%/${functionName}.jar}
|
||||
3
Tooling/body_and_auth_mapping.json
Normal file
3
Tooling/body_and_auth_mapping.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"application/json": "#set($allParams = $input.params())\n{\"body\": $input.json('$'),\"params\" : {\n #foreach($type in $allParams.keySet())\n #set($params = $allParams.get($type))\n \"$type\" : {\n #foreach($paramName in $params.keySet())\n \"$paramName\" : \"$util.escapeJavaScript($params.get($paramName))\"\n #if($foreach.hasNext),#end\n #end\n }\n #if($foreach.hasNext),#end\n #end\n },\"context\" : {\"sub\" : \"$context.authorizer.claims.sub\",\"email\" : \"$context.authorizer.claims.email\"}}"
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user