kandi background
Explore Kits

ChatKit | Android library | User Interface library

 by   stfalcon-studio Java Version: v0.4.1 License: Apache-2.0

 by   stfalcon-studio Java Version: v0.4.1 License: Apache-2.0

Download this library from

kandi X-RAY | ChatKit Summary

ChatKit is a Java library typically used in Telecommunications, Media, Telecom, User Interface applications. ChatKit has no bugs, it has no vulnerabilities, it has build file available, it has a Permissive License and it has medium support. You can download it from GitHub.
ChatKit is a library designed to simplify the development of UI for such a trivial task as chat. It has flexible possibilities for styling, customizing and data management.
Support
Support
Quality
Quality
Security
Security
License
License
Reuse
Reuse

kandi-support Support

  • ChatKit has a medium active ecosystem.
  • It has 3413 star(s) with 779 fork(s). There are 109 watchers for this library.
  • It had no major release in the last 12 months.
  • There are 96 open issues and 196 have been closed. On average issues are closed in 113 days. There are 18 open pull requests and 0 closed requests.
  • It has a neutral sentiment in the developer community.
  • The latest version of ChatKit is v0.4.1
ChatKit Support
Best in #User Interface
Average in #User Interface
ChatKit Support
Best in #User Interface
Average in #User Interface

quality kandi Quality

  • ChatKit has 0 bugs and 0 code smells.
ChatKit Quality
Best in #User Interface
Average in #User Interface
ChatKit Quality
Best in #User Interface
Average in #User Interface

securitySecurity

  • ChatKit has no vulnerabilities reported, and its dependent libraries have no vulnerabilities reported.
  • ChatKit code analysis shows 0 unresolved vulnerabilities.
  • There are 0 security hotspots that need review.
ChatKit Security
Best in #User Interface
Average in #User Interface
ChatKit Security
Best in #User Interface
Average in #User Interface

license License

  • ChatKit is licensed under the Apache-2.0 License. This license is Permissive.
  • Permissive licenses have the least restrictions, and you can use them in most projects.
ChatKit License
Best in #User Interface
Average in #User Interface
ChatKit License
Best in #User Interface
Average in #User Interface

buildReuse

  • ChatKit releases are available to install and integrate.
  • Build file is available. You can build the component from source.
  • Installation instructions, examples and code snippets are available.
  • It has 6315 lines of code, 590 functions and 103 files.
  • It has medium code complexity. Code complexity directly impacts maintainability of the code.
ChatKit Reuse
Best in #User Interface
Average in #User Interface
ChatKit Reuse
Best in #User Interface
Average in #User Interface
Top functions reviewed by kandi - BETA

kandi has reviewed ChatKit and discovered the below as its top functions. This is intended to give you an instant insight into ChatKit implemented functionality, and help decide if they suit your requirements.

  • Parse list list style .
  • Initialize the MessageInput .
  • Called when the view is scrolled .
  • This method is used to retrieve a fragment .
  • Returns the view holder for the given view type .
  • Generate multiple messages
  • removes date headers that are present .
  • This method is called when the view holder is created .
  • region Path
  • Create a drawable for a specific color

ChatKit Key Features

Ready-to-use already styled solution for quick implementation;

Default and custom media messages;

Fully customizable layouts - setting styles out of the box (use your own colors, text appearances, drawables, selectors and sizes) or even create your own custom markup or/and holders for unique behaviour;

List of dialogs, including tete-a-tete and group chats, markers for unread messages and last user message view;

List of messages (incoming and outcoming) with history pagination and already calculated dates headers;

Different avatars with no specific realization of image loading - you can use any library you want;

Selection mode for interacting with messages;

Links highlighting

Easy dates formatting;

Your own models for dialogs and messages - there is no converting needed;

Ready to use message input view;

Custom animations (according to RecyclerView usage).

Download

copy iconCopydownload iconDownload
allprojects {
  repositories {
    ...
    maven { url 'https://jitpack.io' }
  }
}

AndroidX

copy iconCopydownload iconDownload
android.useAndroidX=true
android.enableJetifier=true

Proguard

copy iconCopydownload iconDownload
-keep class * extends com.stfalcon.chatkit.messages.MessageHolders$OutcomingTextMessageViewHolder {
     public <init>(android.view.View, java.lang.Object);
     public <init>(android.view.View);
 }
-keep class * extends com.stfalcon.chatkit.messages.MessageHolders$IncomingTextMessageViewHolder {
     public <init>(android.view.View, java.lang.Object);
     public <init>(android.view.View);
 }
-keep class * extends com.stfalcon.chatkit.messages.MessageHolders$IncomingImageMessageViewHolder {
     public <init>(android.view.View, java.lang.Object);
     public <init>(android.view.View);
 }
-keep class * extends com.stfalcon.chatkit.messages.MessageHolders$OutcomingImageMessageViewHolder {
     public <init>(android.view.View, java.lang.Object);
     public <init>(android.view.View);
 }

License

copy iconCopydownload iconDownload
Copyright (C) 2017 stfalcon.com

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://github.com/stfalcon-studio/ChatKit/blob/master/LICENSE

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.

Stream.io Chat API - Member state omitted from queryChannels response

copy iconCopydownload iconDownload
  public async getChannelUserIds(channelId: string): Promise<string[]> {
    try {
      const queryChannelsResponse = await this.client.queryChannels(
        { id: channelId },
        { last_updated_at: -1 },
        { message_limit: 0, limit: 1, state: true },
      )
      const channel = queryChannelsResponse[0]

      const userIds = Object.keys(channel.state.members)
      console.log('userIds:', userIds)

      return userIds
    } catch (err) {
      throw new InternalServerErrorException(
        `Error getting user ids for channel ('${channelId}').`,
        err,
      )
    }
  }
  public async getOfflineUserIds(userIds: string[]): Promise<string[]> {
    try {
      const queryUsersResponse = await this.client.queryUsers(
        { id: { $in: userIds } },
        { last_active: -1 },
        {},
      )

      console.log('queryUsersResponse:', queryUsersResponse)

      const offlineUserIds = queryUsersResponse.users
        .filter(u => !u.online)
        .map(u => u.user_id)

      return offlineUserIds
    } catch (err) {
      throw new InternalServerErrorException(
        `Error getting offline user ids from ('${JSON.stringify(
          userIds,
          null,
          2,
        )}').`,
        err,
      )
    }
  }
@Post('stream/messages')
  public async onReceive(
    @Req() req: Request,
    @Headers('x-signature') signature: string,
    @Body() body: any,
  ) {
    try {
      console.debug('webhooks-stream.messages.onReceive')
      this.chatService.verifyWebhook((req as any).rawBody, signature)

      console.log('DEBUG WEBHOOK BODY', JSON.stringify(body, null, 2))

      switch (body.type) {
        case 'message.new': {
          const offlineMemberIds = await this.chatService.getOfflineUserIds(
            body.members.map(member => member.user_id),
          )

      ...
-----------------------
  public async getChannelUserIds(channelId: string): Promise<string[]> {
    try {
      const queryChannelsResponse = await this.client.queryChannels(
        { id: channelId },
        { last_updated_at: -1 },
        { message_limit: 0, limit: 1, state: true },
      )
      const channel = queryChannelsResponse[0]

      const userIds = Object.keys(channel.state.members)
      console.log('userIds:', userIds)

      return userIds
    } catch (err) {
      throw new InternalServerErrorException(
        `Error getting user ids for channel ('${channelId}').`,
        err,
      )
    }
  }
  public async getOfflineUserIds(userIds: string[]): Promise<string[]> {
    try {
      const queryUsersResponse = await this.client.queryUsers(
        { id: { $in: userIds } },
        { last_active: -1 },
        {},
      )

      console.log('queryUsersResponse:', queryUsersResponse)

      const offlineUserIds = queryUsersResponse.users
        .filter(u => !u.online)
        .map(u => u.user_id)

      return offlineUserIds
    } catch (err) {
      throw new InternalServerErrorException(
        `Error getting offline user ids from ('${JSON.stringify(
          userIds,
          null,
          2,
        )}').`,
        err,
      )
    }
  }
@Post('stream/messages')
  public async onReceive(
    @Req() req: Request,
    @Headers('x-signature') signature: string,
    @Body() body: any,
  ) {
    try {
      console.debug('webhooks-stream.messages.onReceive')
      this.chatService.verifyWebhook((req as any).rawBody, signature)

      console.log('DEBUG WEBHOOK BODY', JSON.stringify(body, null, 2))

      switch (body.type) {
        case 'message.new': {
          const offlineMemberIds = await this.chatService.getOfflineUserIds(
            body.members.map(member => member.user_id),
          )

      ...
-----------------------
  public async getChannelUserIds(channelId: string): Promise<string[]> {
    try {
      const queryChannelsResponse = await this.client.queryChannels(
        { id: channelId },
        { last_updated_at: -1 },
        { message_limit: 0, limit: 1, state: true },
      )
      const channel = queryChannelsResponse[0]

      const userIds = Object.keys(channel.state.members)
      console.log('userIds:', userIds)

      return userIds
    } catch (err) {
      throw new InternalServerErrorException(
        `Error getting user ids for channel ('${channelId}').`,
        err,
      )
    }
  }
  public async getOfflineUserIds(userIds: string[]): Promise<string[]> {
    try {
      const queryUsersResponse = await this.client.queryUsers(
        { id: { $in: userIds } },
        { last_active: -1 },
        {},
      )

      console.log('queryUsersResponse:', queryUsersResponse)

      const offlineUserIds = queryUsersResponse.users
        .filter(u => !u.online)
        .map(u => u.user_id)

      return offlineUserIds
    } catch (err) {
      throw new InternalServerErrorException(
        `Error getting offline user ids from ('${JSON.stringify(
          userIds,
          null,
          2,
        )}').`,
        err,
      )
    }
  }
@Post('stream/messages')
  public async onReceive(
    @Req() req: Request,
    @Headers('x-signature') signature: string,
    @Body() body: any,
  ) {
    try {
      console.debug('webhooks-stream.messages.onReceive')
      this.chatService.verifyWebhook((req as any).rawBody, signature)

      console.log('DEBUG WEBHOOK BODY', JSON.stringify(body, null, 2))

      switch (body.type) {
        case 'message.new': {
          const offlineMemberIds = await this.chatService.getOfflineUserIds(
            body.members.map(member => member.user_id),
          )

      ...

Debugging deploying full-stack app to Heroku

copy iconCopydownload iconDownload
app.post('/authenticate', (req, res) => {
  const authData = chatkit.authenticate({ userId: req.query.user_id })
  res.status(authData.status).send(authData.body)
})

// if (process.env.NODE_ENV === 'production') { // This is your thang, I commented it out to reach a solution, but probably not necessary for you
  app.use(express.static('build')); // 'react-scripts build' places a /build directory at root, not /client/build

  app.get('*', (req, res) => {
    res.sendFile(path.resolve(__dirname, 'build', 'index.html')); // Removed client here also
  });
// }
"scripts": {
    "start": "node server.js",
    "build": "react-scripts build",
    "postinstall": "npm run build"
  },
-----------------------
app.post('/authenticate', (req, res) => {
  const authData = chatkit.authenticate({ userId: req.query.user_id })
  res.status(authData.status).send(authData.body)
})

// if (process.env.NODE_ENV === 'production') { // This is your thang, I commented it out to reach a solution, but probably not necessary for you
  app.use(express.static('build')); // 'react-scripts build' places a /build directory at root, not /client/build

  app.get('*', (req, res) => {
    res.sendFile(path.resolve(__dirname, 'build', 'index.html')); // Removed client here also
  });
// }
"scripts": {
    "start": "node server.js",
    "build": "react-scripts build",
    "postinstall": "npm run build"
  },

Stripe Firebase Cloud Functions - res.send() is not a function

copy iconCopydownload iconDownload
exports.stripeCreateOathResponseToken =
functions.https.onRequest((req, res) => {
    return cors(req, res, () => {
        // put your function code here
    });
});

How to send document or images in group using plain javascript pusher chatkit

copy iconCopydownload iconDownload
currentUser.sendMultipartMessage({
  roomId: myRoom.id,
  parts: [
    { type: "text/plain", content: "" },
    {
      type: "image/gif",
      url: "https://gfycat.com/failingforkedheterodontosaurus",
    },
    {
      file: document.querySelector("#attach").files[0],
      customData: { metadata: 42 },
    }
  ],
});

How to show badges using pusher data

copy iconCopydownload iconDownload
currentUser.subscribeToRoomMultipart({
  roomId: this.currentRoom,
  messageLimit: 100,
  hooks: {
    //Message is received
    onMessage: message => {
      this.lastMessage = message.id;
      //set cursor
        currentUser.setReadCursor({
        roomId: this.currentRoom,
        position: this.lastMessage
      })
      .then(() => {
        console.log(`Set cursor to message ${this.lastMessage}`)
      })
      .catch(err => {
        console.log(`Error setting cursor: ${err}`)
      })
    }
  },

}).then(room => {
  //log unread count
  console.log(`Unread count: ${room.unreadCount}`)
});

kotlin.UninitializedPropertyAccessException: lateinit property roomClickedInterface has not been initialized

copy iconCopydownload iconDownload
override fun onClick(p0: View?) {

    if(this::roomClickedInterface.isInitialized) {
        roomClickedInterface.roomSelected(list[adapterPosition])
    }
}
//lateinit var roomClickedInterface:RoomClickedInterface
class ChatRoomsListAdapter(val roomClickedInterface:RoomClickedInterface):
     RecyclerView.Adapter<ChatRoomsListAdapter.ViewHolder>() {

    //Implementation
}
private var roomClickedInterface: RoomClickedInterface? = null
override fun onClick(p0: View?) {
    roomClickedInterface?.roomSelected(list[adapterPosition])
}
-----------------------
override fun onClick(p0: View?) {

    if(this::roomClickedInterface.isInitialized) {
        roomClickedInterface.roomSelected(list[adapterPosition])
    }
}
//lateinit var roomClickedInterface:RoomClickedInterface
class ChatRoomsListAdapter(val roomClickedInterface:RoomClickedInterface):
     RecyclerView.Adapter<ChatRoomsListAdapter.ViewHolder>() {

    //Implementation
}
private var roomClickedInterface: RoomClickedInterface? = null
override fun onClick(p0: View?) {
    roomClickedInterface?.roomSelected(list[adapterPosition])
}
-----------------------
override fun onClick(p0: View?) {

    if(this::roomClickedInterface.isInitialized) {
        roomClickedInterface.roomSelected(list[adapterPosition])
    }
}
//lateinit var roomClickedInterface:RoomClickedInterface
class ChatRoomsListAdapter(val roomClickedInterface:RoomClickedInterface):
     RecyclerView.Adapter<ChatRoomsListAdapter.ViewHolder>() {

    //Implementation
}
private var roomClickedInterface: RoomClickedInterface? = null
override fun onClick(p0: View?) {
    roomClickedInterface?.roomSelected(list[adapterPosition])
}
-----------------------
override fun onClick(p0: View?) {

    if(this::roomClickedInterface.isInitialized) {
        roomClickedInterface.roomSelected(list[adapterPosition])
    }
}
//lateinit var roomClickedInterface:RoomClickedInterface
class ChatRoomsListAdapter(val roomClickedInterface:RoomClickedInterface):
     RecyclerView.Adapter<ChatRoomsListAdapter.ViewHolder>() {

    //Implementation
}
private var roomClickedInterface: RoomClickedInterface? = null
override fun onClick(p0: View?) {
    roomClickedInterface?.roomSelected(list[adapterPosition])
}
-----------------------
override fun onClick(p0: View?) {

    if(this::roomClickedInterface.isInitialized) {
        roomClickedInterface.roomSelected(list[adapterPosition])
    }
}
//lateinit var roomClickedInterface:RoomClickedInterface
class ChatRoomsListAdapter(val roomClickedInterface:RoomClickedInterface):
     RecyclerView.Adapter<ChatRoomsListAdapter.ViewHolder>() {

    //Implementation
}
private var roomClickedInterface: RoomClickedInterface? = null
override fun onClick(p0: View?) {
    roomClickedInterface?.roomSelected(list[adapterPosition])
}

React.js Duplicate key and Unreachable code BUGS

copy iconCopydownload iconDownload
return (
  <div>

  </div>
)
const myObject = {
  currentUsername: 'bob',
  currentUsername: 'alice',
}
<ChatScreen
  currentUsername="bob"
  currentUsername="alice"
/>
-----------------------
return (
  <div>

  </div>
)
const myObject = {
  currentUsername: 'bob',
  currentUsername: 'alice',
}
<ChatScreen
  currentUsername="bob"
  currentUsername="alice"
/>
-----------------------
return (
  <div>

  </div>
)
const myObject = {
  currentUsername: 'bob',
  currentUsername: 'alice',
}
<ChatScreen
  currentUsername="bob"
  currentUsername="alice"
/>
-----------------------
constructor() {
    super();
    this.state = {
      currentUsername: '', 
      currentUsername: 'WhatIsYournameScreen',
    }
    this.onUsernameSubmitted = this.onUsernameSubmitted.bind(this)
  }
import React, { Component } from 'react'
import Chatkit from '@pusher/chatkit-client'

class ChatScreen extends Component{
  constructor(props) {
    super(props)
    this.state = {
      currentUser: {}
    }
  }

  componentDidMount() {
    const chatManager = new Chatkit.ChatManager({
      instanceLocator: 'v1:us1:1308c34d-00c3-4257-b1c3-647cf56fd5fa',
      userId: this.props.currentUsername,
      tokenProvider: new Chatkit.TokenProvider({
        url: 'http://localhost:3000/authenticate',
      }),
    })

    chatManager
      .connect()
      .then(currentUser => {
        this.setState({ currentUser })
      })
      .catch(error => console.error('error', error))
  }

  render() {
    return (
      <div style={styles.container}>
        <div style={styles.chatContainer}>
          <aside style={styles.whosOnlineListContainer}>
            <h2>Who's online PLACEHOLDER</h2>
          </aside>
          <section style={styles.chatListContainer}>
            <h2>Chat PLACEHOLDER</h2>
          </section>
        </div>
      </div>
    );
  }
}

const styles = {
      container: {
        height: '100vh',
        display: 'flex',
        flexDirection: 'column',
      },
      chatContainer: {
        display: 'flex',
        flex: 1,
      },
      whosOnlineListContainer: {
        width: '300px',
        flex: 'none',
        padding: 20,
        backgroundColor: '#2c303b',
        color: 'white',
      },
      chatListContainer: {
        padding: 20,
        width: '85%',
        display: 'flex',
        flexDirection: 'column',
      },
    }

export default ChatScreen;
-----------------------
constructor() {
    super();
    this.state = {
      currentUsername: '', 
      currentUsername: 'WhatIsYournameScreen',
    }
    this.onUsernameSubmitted = this.onUsernameSubmitted.bind(this)
  }
import React, { Component } from 'react'
import Chatkit from '@pusher/chatkit-client'

class ChatScreen extends Component{
  constructor(props) {
    super(props)
    this.state = {
      currentUser: {}
    }
  }

  componentDidMount() {
    const chatManager = new Chatkit.ChatManager({
      instanceLocator: 'v1:us1:1308c34d-00c3-4257-b1c3-647cf56fd5fa',
      userId: this.props.currentUsername,
      tokenProvider: new Chatkit.TokenProvider({
        url: 'http://localhost:3000/authenticate',
      }),
    })

    chatManager
      .connect()
      .then(currentUser => {
        this.setState({ currentUser })
      })
      .catch(error => console.error('error', error))
  }

  render() {
    return (
      <div style={styles.container}>
        <div style={styles.chatContainer}>
          <aside style={styles.whosOnlineListContainer}>
            <h2>Who's online PLACEHOLDER</h2>
          </aside>
          <section style={styles.chatListContainer}>
            <h2>Chat PLACEHOLDER</h2>
          </section>
        </div>
      </div>
    );
  }
}

const styles = {
      container: {
        height: '100vh',
        display: 'flex',
        flexDirection: 'column',
      },
      chatContainer: {
        display: 'flex',
        flex: 1,
      },
      whosOnlineListContainer: {
        width: '300px',
        flex: 'none',
        padding: 20,
        backgroundColor: '#2c303b',
        color: 'white',
      },
      chatListContainer: {
        padding: 20,
        width: '85%',
        display: 'flex',
        flexDirection: 'column',
      },
    }

export default ChatScreen;
-----------------------
import React, { Component } from 'react'
import Chatkit from '@pusher/chatkit-client'

class ChatScreen extends Component{
  constructor(props) {
    super(props)
    this.state = {
      currentUser: {}
    }
  }

  componentDidMount() {
    const chatManager = new Chatkit.ChatManager({
      instanceLocator: 'v1:us1:1308c34d-00c3-4257-b1c3-647cf56fd5fa',
      userId: this.props.currentUsername,
      tokenProvider: new Chatkit.TokenProvider({
        url: 'http://localhost:3000/authenticate',
      }),
    })

    chatManager
      .connect()
      .then(currentUser => {
        this.setState({ currentUser })
      })
      .catch(error => console.error('error', error))
  }

  render() {
    const styles = {
      container: {
        height: '100vh',
        display: 'flex',
        flexDirection: 'column',
      },
      chatContainer: {
        display: 'flex',
        flex: 1,
      },
      whosOnlineListContainer: {
        width: '300px',
        flex: 'none',
        padding: 20,
        backgroundColor: '#2c303b',
        color: 'white',
      },
      chatListContainer: {
        padding: 20,
        width: '85%',
        display: 'flex',
        flexDirection: 'column',
      },
    }
    return (
      <div style={styles.container}>
        <div style={styles.chatContainer}>
          <aside style={styles.whosOnlineListContainer}>
            <h2>Who's online PLACEHOLDER</h2>
          </aside>
          <section style={styles.chatListContainer}>
            <h2>Chat PLACEHOLDER</h2>
          </section>
        </div>
      </div>
    );
  }
}




export default ChatScreen;
import React, { Component } from 'react'
import UsernameForm from './components/UsernameForm'
import ChatScreen from './components/ChatScreen'

class App extends Component {
  constructor() {
    super();
    this.state = {
      currentUsername: '',
      currentScreen: 'WhatIsYournameScreen',
    }
    this.onUsernameSubmitted = this.onUsernameSubmitted.bind(this)
  }

  onUsernameSubmitted(username) {
    fetch('http://localhost:3000/users', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ username }),
    })
      .then(response => {
        this.setState({
          currentUsername: username,
          currentScreen: 'ChatScreen'
        })
      })
      .catch(error => console.error('error', error))
  }

  render() {
    if (this.state.currentScreen === 'WhatIsYourUsernameScreen') {
      return <UsernameForm onSubmit={this.onUsernameSubmitted} />
    }
    if (this.state.currentScreen === 'ChatScreen') {
      return <ChatScreen currentUsername={this.state.currentUsername} /> 
    }
    return (
      <div>
        <h1>Hoş geldin</h1>
        <UsernameForm onSubmit={this.onUsernameSubmitted} />
      </div>
    );
  }
}


export default App;
-----------------------
import React, { Component } from 'react'
import Chatkit from '@pusher/chatkit-client'

class ChatScreen extends Component{
  constructor(props) {
    super(props)
    this.state = {
      currentUser: {}
    }
  }

  componentDidMount() {
    const chatManager = new Chatkit.ChatManager({
      instanceLocator: 'v1:us1:1308c34d-00c3-4257-b1c3-647cf56fd5fa',
      userId: this.props.currentUsername,
      tokenProvider: new Chatkit.TokenProvider({
        url: 'http://localhost:3000/authenticate',
      }),
    })

    chatManager
      .connect()
      .then(currentUser => {
        this.setState({ currentUser })
      })
      .catch(error => console.error('error', error))
  }

  render() {
    const styles = {
      container: {
        height: '100vh',
        display: 'flex',
        flexDirection: 'column',
      },
      chatContainer: {
        display: 'flex',
        flex: 1,
      },
      whosOnlineListContainer: {
        width: '300px',
        flex: 'none',
        padding: 20,
        backgroundColor: '#2c303b',
        color: 'white',
      },
      chatListContainer: {
        padding: 20,
        width: '85%',
        display: 'flex',
        flexDirection: 'column',
      },
    }
    return (
      <div style={styles.container}>
        <div style={styles.chatContainer}>
          <aside style={styles.whosOnlineListContainer}>
            <h2>Who's online PLACEHOLDER</h2>
          </aside>
          <section style={styles.chatListContainer}>
            <h2>Chat PLACEHOLDER</h2>
          </section>
        </div>
      </div>
    );
  }
}




export default ChatScreen;
import React, { Component } from 'react'
import UsernameForm from './components/UsernameForm'
import ChatScreen from './components/ChatScreen'

class App extends Component {
  constructor() {
    super();
    this.state = {
      currentUsername: '',
      currentScreen: 'WhatIsYournameScreen',
    }
    this.onUsernameSubmitted = this.onUsernameSubmitted.bind(this)
  }

  onUsernameSubmitted(username) {
    fetch('http://localhost:3000/users', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ username }),
    })
      .then(response => {
        this.setState({
          currentUsername: username,
          currentScreen: 'ChatScreen'
        })
      })
      .catch(error => console.error('error', error))
  }

  render() {
    if (this.state.currentScreen === 'WhatIsYourUsernameScreen') {
      return <UsernameForm onSubmit={this.onUsernameSubmitted} />
    }
    if (this.state.currentScreen === 'ChatScreen') {
      return <ChatScreen currentUsername={this.state.currentUsername} /> 
    }
    return (
      <div>
        <h1>Hoş geldin</h1>
        <UsernameForm onSubmit={this.onUsernameSubmitted} />
      </div>
    );
  }
}


export default App;

Community Discussions

Trending Discussions on ChatKit
  • Stream.io Chat API - Member state omitted from queryChannels response
  • Debugging deploying full-stack app to Heroku
  • Stripe Firebase Cloud Functions - res.send() is not a function
  • How to send document or images in group using plain javascript pusher chatkit
  • How to show badges using pusher data
  • Pusher Chatkit Android get status readout of specified room
  • kotlin.UninitializedPropertyAccessException: lateinit property roomClickedInterface has not been initialized
  • React.js Duplicate key and Unreachable code BUGS
Trending Discussions on ChatKit

QUESTION

Stream.io Chat API - Member state omitted from queryChannels response

Asked 2020-Apr-07 at 12:44

When I do the following:

      const queryChannelsResponse = await this.client.queryChannels(
        { id: channelId },
        { last_updated_at: -1 },
        { state: true },

This does not include the members. How am I able to get the member information?

I am writing a webhook and I want it to send a push notification (I am currently sending these myself via expo) to all offline users.

I am migrating from pusher chatkit which is now being discontinued. They had a new_message_users_offline hook for this purpose.

In the message.new webhook payload in the documentation the members are present but they are not present in the request body:

{
    "type": "message.new",
    "cid": "messaging:394f36fd-d512-4f2b-a785-ab8dfe82af49",
    "message": {
        "id": "f73ee1a8-f6fd-450b-bc64-0840b4df8fd9-2b4908ad-e267-4c48-8f41-8c26c8f769ce",
        "text": "Ffddf",
        "html": "<p>Ffddf</p>\n",
        "type": "regular",
        "user": {
            "id": "f73ee1a8-f6fd-450b-bc64-0840b4df8fd9",
            "role": "user",
            "created_at": "2020-04-06T14:06:37.979584Z",
            "updated_at": "2020-04-06T19:45:39.556842Z",
            "last_active": "2020-04-06T19:45:39.54939Z",
            "banned": false,
            "online": true,
            "name": "Mark Everett",
            "image": "https://8dc-user-files-dev.s3.eu-west-1.amazonaws.com/MEMBER_PROFILE_IMAGE-f73ee1a8-f6fd-450b-bc64-0840b4df8fd9.png?v=6"
        },
        "attachments": [],
        "latest_reactions": [],
        "own_reactions": [],
        "reaction_counts": null,
        "reaction_scores": {},
        "reply_count": 0,
        "created_at": "2020-04-06T19:51:14.114803Z",
        "updated_at": "2020-04-06T19:51:14.114803Z",
        "mentioned_users": []
    },
    "user": {
        "id": "f73ee1a8-f6fd-450b-bc64-0840b4df8fd9",
        "role": "user",
        "created_at": "2020-04-06T14:06:37.979584Z",
        "updated_at": "2020-04-06T19:45:39.556842Z",
        "last_active": "2020-04-06T19:45:39.54939Z",
        "banned": false,
        "online": true,
        "channel_unread_count": 0,
        "channel_last_read_at": "1970-01-01T00:00:00Z",
        "total_unread_count": 0,
        "unread_channels": 0,
        "unread_count": 0,
        "image": "https://8dc-user-files-dev.s3.eu-west-1.amazonaws.com/MEMBER_PROFILE_IMAGE-f73ee1a8-f6fd-450b-bc64-0840b4df8fd9.png?v=6",
        "name": "Mark Everett"
    },
    "watcher_count": 1,
    "created_at": "2020-04-06T19:51:14.121213459Z",
    "channel_type": "messaging",
    "channel_id": "394f36fd-d512-4f2b-a785-ab8dfe82af49"
}

My plan is do do something like this:

  public async getOfflineUserIds(channelId: string): Promise<string[]> {
    try {
      // Get the channel
      const queryChannelsResponse = await this.client.queryChannels(
        { id: channelId },
        { last_updated_at: -1 },
        { message_limit: 0, limit: 1, state: true},
      )
      const channel = queryChannelsResponse[0]

      console.log('channel: ', channel)

      // Get the channels members
      const userIds: string[] = []
      // tslint:disable-next-line: forin
      for (const index in channel.state.members) {
        userIds.push(channel.state.members[index].user_id)
      }
      console.log('userIds:', userIds)

      const queryUsersResponse = await this.client.queryUsers(
        { id: { $in: userIds } },
        { last_active: -1 },
        {},
      )

      console.log('queryUsersResponse:', queryUsersResponse)

      // Work out who is offline/online
      const offlineUserIds = queryUsersResponse.users
        .filter(u => !u.online)
        .map(u => u.id)

      return offlineUserIds
    } catch (err) {
      throw new InternalServerErrorException(
        'Error getting offline users for channel.',
        err,
      )
    }
  }

ANSWER

Answered 2020-Apr-07 at 12:44

This is now resolved.

I did not add the members to the channel with channel.addMembers. I create and add members on the server as this works perfectly for my use case.

If it helps anyone I ended up with these two methods:

  public async getChannelUserIds(channelId: string): Promise<string[]> {
    try {
      const queryChannelsResponse = await this.client.queryChannels(
        { id: channelId },
        { last_updated_at: -1 },
        { message_limit: 0, limit: 1, state: true },
      )
      const channel = queryChannelsResponse[0]

      const userIds = Object.keys(channel.state.members)
      console.log('userIds:', userIds)

      return userIds
    } catch (err) {
      throw new InternalServerErrorException(
        `Error getting user ids for channel ('${channelId}').`,
        err,
      )
    }
  }
  public async getOfflineUserIds(userIds: string[]): Promise<string[]> {
    try {
      const queryUsersResponse = await this.client.queryUsers(
        { id: { $in: userIds } },
        { last_active: -1 },
        {},
      )

      console.log('queryUsersResponse:', queryUsersResponse)

      const offlineUserIds = queryUsersResponse.users
        .filter(u => !u.online)
        .map(u => u.user_id)

      return offlineUserIds
    } catch (err) {
      throw new InternalServerErrorException(
        `Error getting offline user ids from ('${JSON.stringify(
          userIds,
          null,
          2,
        )}').`,
        err,
      )
    }
  }

And then in my webhook I:

@Post('stream/messages')
  public async onReceive(
    @Req() req: Request,
    @Headers('x-signature') signature: string,
    @Body() body: any,
  ) {
    try {
      console.debug('webhooks-stream.messages.onReceive')
      this.chatService.verifyWebhook((req as any).rawBody, signature)

      console.log('DEBUG WEBHOOK BODY', JSON.stringify(body, null, 2))

      switch (body.type) {
        case 'message.new': {
          const offlineMemberIds = await this.chatService.getOfflineUserIds(
            body.members.map(member => member.user_id),
          )

      ...

Source https://stackoverflow.com/questions/61067984

Community Discussions, Code Snippets contain sources that include Stack Exchange Network

Vulnerabilities

No vulnerabilities reported

Install ChatKit

Add jitpack to the root build.gradle file of your project at the end of repositories.
Add the dependency

Support

For any new features, suggestions and bugs create an issue on GitHub. If you have any questions check and ask questions on community page Stack Overflow .

DOWNLOAD this Library from

Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from
over 430 million Knowledge Items
Find more libraries
Reuse Solution Kits and Libraries Curated by Popular Use Cases

Save this library and start creating your kit

Share this Page

share link
Compare User Interface Libraries with Highest Quality
Compare User Interface Libraries with Highest Security
Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from
over 430 million Knowledge Items
Find more libraries
Reuse Solution Kits and Libraries Curated by Popular Use Cases

Save this library and start creating your kit

  • © 2022 Open Weaver Inc.