Giter Club home page Giter Club logo

heard's Introduction

Heard - An enterprise React Native Social Messaging App

Built with AWS AppSync & AWS Amplify

Todo

  • Add subscriptions for real time updates / messages in feed
  • Add user profile section
  • Add "follower" tab

Getting Started

Cloning the project & creating the services

  1. Clone the project
git clone 
  1. Install dependencies
yarn
# or
npm install
  1. Create new AWS Mobile Project
awsmobile init
  1. Add Authentication service
awsmobile user-signin enable
  1. Push configuration to AWS Mobile Hub
awsmobile push

Configuring the AWS AppSync API

  1. Create & configure a new AppSync API
  • Visit the AWS AppSync console and create a new API.
  • In Settings, set the Auth mode to Amazon Cognito User Pool and choose the user pool created in the initial service creation.
  1. In index.js on line 11, change <YOURAPPSYNCENDPOINT> to the endpoint given to you when you created the AppSync API.

  2. Attach the following Schema:

input CreateFollowingInput {
	id: ID
	followerId: ID!
	followingId: ID!
}

input CreateMessageInput {
	messageId: ID
	authorId: ID!
	createdAt: String
	messageInfo: MessageInfoInput!
	author: UserInput
}

input CreateUserInput {
	userId: ID!
	username: String!
}

input DeleteFollowingInput {
	id: ID!
}

input DeleteMessageInput {
	authorId: ID!
	createdAt: String!
}

input DeleteUserInput {
	userId: ID!
}

type Following {
	id: ID
	followerId: ID!
	followingId: ID!
}

type FollowingConnection {
	items: [Following]
	nextToken: String
}

type ListUserConnection {
	items: [User]
	nextToken: String
}

type Mutation {
	createMessage(input: CreateMessageInput!): Message
	updateMessage(input: UpdateMessageInput!): Message
	deleteMessage(input: DeleteMessageInput!): Message
	createUser(input: CreateUserInput!): User
	updateUser(input: UpdateUserInput!): User
	deleteUser(input: DeleteUserInput!): User
	createFollowing(input: CreateFollowingInput!): Following
	updateFollowing(input: UpdateFollowingInput!): Following
	deleteFollowing(input: DeleteFollowingInput!): Following
}

type Query {
	getMessage(authorId: ID!, createdAt: String!): Message
	listMessages(first: Int, after: String): MessageConnection
	listFollowing: [Following]
	getUser(userId: ID!): User
	listUsers(first: Int, after: String): ListUserConnection
	queryMessagesByAuthorIdIndex(authorId: ID!, first: Int, after: String): MessageConnection
}

type Subscription {
	onCreateMessage(messageId: ID, authorId: ID, createdAt: String): Message
		@aws_subscribe(mutations: ["createMessage"])
	onUpdateMessage(messageId: ID, authorId: ID, createdAt: String): Message
		@aws_subscribe(mutations: ["updateMessage"])
	onDeleteMessage(messageId: ID, authorId: ID, createdAt: String): Message
		@aws_subscribe(mutations: ["deleteMessage"])
	onCreateUser(userId: ID, username: String): User
		@aws_subscribe(mutations: ["createUser"])
	onUpdateUser(userId: ID, username: String): User
		@aws_subscribe(mutations: ["updateUser"])
	onDeleteUser(userId: ID, username: String): User
		@aws_subscribe(mutations: ["deleteUser"])
	onCreateFollowing(id: ID, followerId: ID, followingId: ID): Following
		@aws_subscribe(mutations: ["createFollowing"])
	onUpdateFollowing(id: ID, followerId: ID, followingId: ID): Following
		@aws_subscribe(mutations: ["updateFollowing"])
	onDeleteFollowing(id: ID, followerId: ID, followingId: ID): Following
		@aws_subscribe(mutations: ["deleteFollowing"])
}

type Message {
	messageId: ID!
	authorId: ID!
	messageInfo: MessageInfo!
	author: User
	createdAt: String
}

type MessageConnection {
	items: [Message]
	nextToken: String
}

type MessageInfo {
	text: String!
}

input MessageInfoInput {
	text: String!
}

input UpdateFollowingInput {
	id: ID!
	followerId: ID
	followingId: ID
}

input UpdateMessageInput {
	messageId: ID
	authorId: ID!
	createdAt: String!
}

input UpdateUserInput {
	userId: ID!
	username: String
}

type User {
	userId: ID!
	username: String
	messages(limit: Int, nextToken: String): MessageConnection
	following(limit: Int, nextToken: String): UserFollowingConnection
	followers(limit: Int, nextToken: String): UserFollowersConnection
}

type UserConnection {
	items: [User]
	nextToken: String
}

type UserFollowersConnection {
	items: [User]
	nextToken: String
}

type UserFollowingConnection {
	items: [User]
	nextToken: String
}

input UserInput {
	userId: ID!
	username: String!
}
  1. Create the following DynamoDB Tables
  • HeardMessageTable
  • HeardFollowingTable
  • HeardUserTable
  1. Add the following indexes:
  • In HeardMessageTable, create an authorId-index with the authorId as the primary / partition key.
  • In HeardFollowingTable, create a followingId-index with the followingId as the primary / partition key.
  • In HeardFollowingTable, create a followerId-index with the followerId as the primary / partition key.

To create an index, click on the table you would like to create an index on, click on the indexes tab, then click Create Index .

  1. Create the following resolvers:

Message author: User: HeardUserTable

// request mapping template
{
    "version": "2017-02-28",
    "operation": "GetItem",
    "key": {
        "userId": $util.dynamodb.toDynamoDBJson($ctx.source.authorId),
    }
}

// response mapping template
$util.toJson($ctx.result)

ListUserConnection items: [User]: HeardUserTable

// request mapping template
{
    "version" : "2017-02-28",
    "operation" : "Scan",
}

// response mapping template
$util.toJson($ctx.result.items)

Query getUser(...): User: HeardUserTable

// request mapping template
{
  "version": "2017-02-28",
  "operation": "GetItem",
  "key": {
    "userId": $util.dynamodb.toDynamoDBJson($ctx.args.userId),
  },
}

// response mapping template
$util.toJson($context.result)

Query listUsers(...): ListUserConnection: HeardUserTable

// request mapping template
{
    "version" : "2017-02-28",
    "operation" : "Scan",
    "limit": $util.defaultIfNull(${ctx.args.limit}, 20),
    "nextToken": $util.toJson($util.defaultIfNullOrBlank($ctx.args.nextToken, null))
}

// response mapping template
$util.toJson($ctx.result.items)

Query listFollowing: [Following]: HeardFollowingTable

// request mapping template
{
    "version" : "2017-02-28",
    "operation" : "Query",
    "index" : "followerId-index",
    "query" : {
        "expression": "followerId = :id",
        "expressionValues" : {
            ":id" : {
                "S" : "${ctx.identity.sub}"
            }
        }
    }
}

// response mapping template
$util.toJson($ctx.result.items)

Query queryMessagesByAuthorIdIndex(...): MessageConnection: HeardMessageTable

// request mapping template
{
  "version": "2017-02-28",
  "operation": "Query",
  "query": {
    "expression": "#authorId = :authorId",
    "expressionNames": {
      "#authorId": "authorId",
    },
    "expressionValues": {
      ":authorId": $util.dynamodb.toDynamoDBJson($ctx.args.authorId),
    },
  },
  "index": "authorId-index",
  "limit": $util.defaultIfNull($ctx.args.first, 20),
  "nextToken": $util.toJson($util.defaultIfNullOrEmpty($ctx.args.after, null)),
  "scanIndexForward": true,
  "select": "ALL_ATTRIBUTES",
}

// response mapping template
$util.toJson($context.result)

Mutation createFollowing(...): Following: HeardFollowingTable

// request mapping template
{
  "version": "2017-02-28",
  "operation": "PutItem",
  "key": {
     ## If object "id" should come from GraphQL arguments, change to $util.dynamodb.toDynamoDBJson($ctx.args.id)
    "id": $util.dynamodb.toDynamoDBJson($util.autoId()),
  },
  "attributeValues": $util.dynamodb.toMapValuesJson($ctx.args.input),
  "condition": {
    "expression": "attribute_not_exists(#id)",
    "expressionNames": {
      "#id": "id",
    },
  },
}

// response mapping template
$util.toJson($context.result)

Mutation deleteFollowing(...): Following: HeardFollowingTable

// request mapping template
{
  "version": "2017-02-28",
  "operation": "DeleteItem",
  "key": {
    "id": $util.dynamodb.toDynamoDBJson($ctx.args.input.id),
  },
}

// response mapping template
$util.toJson($context.result)

Mutation createUser(...): User: HeardUserTable

// request mapping template
{
  "version": "2017-02-28",
  "operation": "PutItem",
  "key": {
    "userId": $util.dynamodb.toDynamoDBJson($ctx.args.input.userId),
  },
  "attributeValues": $util.dynamodb.toMapValuesJson($ctx.args.input),
  "condition": {
    "expression": "attribute_not_exists(#userId)",
    "expressionNames": {
      "#userId": "userId",
    },
  },
}

// response mapping template
$util.toJson($context.result)

Mutation createMessage(...): Message: HeardMessageTable

// request mapping template
#set($time = $util.time.nowISO8601())

#set($attribs = $util.dynamodb.toMapValues($ctx.args.input))
#set($attribs.createdAt = $util.dynamodb.toDynamoDB($time))
#set($attribs.messageId = $util.dynamodb.toDynamoDB($util.autoId()))

{
  "version": "2017-02-28",
  "operation": "PutItem",
  "key": {
    "authorId": $util.dynamodb.toDynamoDBJson($ctx.args.input.authorId),
    "createdAt": $util.dynamodb.toDynamoDBJson($time),
  },
  "attributeValues": $util.toJson($attribs),
  "condition": {
    "expression": "attribute_not_exists(#authorId) AND attribute_not_exists(#createdAt)",
    "expressionNames": {
      "#authorId": "authorId",
      "#createdAt": "createdAt",
    },
  },
}

// response mapping template
$util.toJson($context.result)

User messages(...): MessageConnection: HeardMessageTable

// request mapping template
{
    "version" : "2017-02-28",
    "operation" : "Query",
    "index" : "authorId-index",
    "query" : {
        "expression": "authorId = :id",
        "expressionValues" : {
            ":id" : {
                "S" : "${ctx.source.userId}"
            }
        }
    },
    "limit": $util.defaultIfNull(${ctx.args.first}, 20),
    "nextToken": $util.toJson($util.defaultIfNullOrBlank($ctx.args.after, null))
}

// response mapping template
$util.toJson($ctx.result)

User following(...): UserFollowingConnection: HeardFollowingTable

// request mapping template
{
    "version" : "2017-02-28",
    "operation" : "Query",
    "index" : "followerId-index",
    "query" : {
        "expression": "followerId = :id",
        "expressionValues" : {
            ":id" : {
                "S" : "${ctx.source.userId}"
            }
        }
    }
    ## ,
    ## "limit": $util.defaultIfNull(${ctx.args.first}, 20),
    ## "nextToken": $util.toJson($util.defaultIfNullOrBlank($ctx.args.after, null))
}

// response mapping template
## Pass back the result from DynamoDB. **
## $util.qr($util.error($ctx.result))
$util.toJson($ctx.result)

UserFollowingConnection items: [User]: HeardUserTable

// request mapping template
## UserFollowingConnection.items.request.vtl **
 
#set($ids = [])
#foreach($following in ${ctx.source.items})
    #set($map = {})
    $util.qr($map.put("userId", $util.dynamodb.toString($following.get("followerId"))))
    $util.qr($ids.add($map))
#end
 
{
    "version" : "2018-05-29",
    "operation" : "BatchGetItem",
    "tables" : {
        "HeardUserTable": {
           "keys": $util.toJson($ids),
           "consistentRead": true
       }
    }
}

// response mapping template
## Pass back the result from DynamoDB. **
#if( ! ${ctx.result.data} )
  $util.toJson([])
#else
  $util.toJson($ctx.result.data.HeardUserTable)
#end

## $util.toJson($ctx.result.data.HeardUserTable)

heard's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

heard's Issues

decorators plugin for React Native Version 0.56.0 +

Just read your great Medium post
https://medium.com/react-native-training/react-native-with-mobx-getting-started-ba7e18d8ff44

Instead of installing babel-plugin-transform-decorators-legacy, try installing @babel/plugin-proposal-decorators version 7.0.0-beta.47.

You’ll also need to set up your babel configuration in .babelrc a little differently:

{
  "presets": ["react-native"],
  "plugins": [
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ]
  ]
}

Can I use it as Chat App between users not in the feed?

I wanna use AWS Amplify/Cognito and AppSync for a chat app where users (Doctor or Patient ) can chat between them with a paid subscription model.

Doctor can create prescription/diagnosis or test for the patient during their chat.

My basic Idea is using Cognito and Amplify to make user registration.Then add doctors as admin so that that they can create prescription to send to the patients.

Also want to use Appsync,Dynamodb.

Could you give some guidelines.What parts I can use from "Heard" App.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.