Explore all Chat open source software, libraries, packages, source code, cloud functions and APIs.

Popular New Releases in Chat

taro

chore(release): publish 3.4.7

python-telegram-bot

v13.11

tinker

litemall

v1.8.0

vant-weapp

v1.10.2

Popular Libraries in Chat

uni-app

by dcloudio doticonjavascriptdoticon

star image 36431 doticonApache-2.0

uni-app 是使用 Vue 语法开发小程序、H5、App的统一框架

taro

by NervJS doticontypescriptdoticon

star image 30875 doticonMIT

开放式跨端跨框架解决方案,支持使用 React/Vue/Nerv 等框架来开发微信/京东/百度/支付宝/字节跳动/ QQ 小程序/H5/React Native 等应用。 https://taro.zone/

ItChat

by littlecodersh doticonpythondoticon

star image 21699 doticonNOASSERTION

A complete and graceful API for Wechat. 微信个人号接口、微信机器人及命令行微信,三十行即可自定义个人号机器人。

python-telegram-bot

by python-telegram-bot doticonpythondoticon

star image 18256 doticonNOASSERTION

We have made you a wrapper you can't refuse

tinker

by Tencent doticonjavadoticon

star image 16260 doticonNOASSERTION

Tinker is a hot-fix solution library for Android, it supports dex, library and resources update without reinstall apk.

litemall

by linlinjava doticonjavadoticon

star image 16176 doticonMIT

又一个小商城。litemall = Spring Boot后端 + Vue管理员前端 + 微信小程序用户前端 + Vue用户移动端

mars

by Tencent doticonc++doticon

star image 16100 doticonNOASSERTION

Mars is a cross-platform network component developed by WeChat.

vant-weapp

by youzan doticonjavascriptdoticon

star image 15795 doticonMIT

轻量、可靠的小程序 UI 组件库

zulip

by zulip doticonpythondoticon

star image 15620 doticonApache-2.0

Zulip server and web app—powerful open source team chat

Trending New libraries in Chat

data-science-interviews

by alexeygrigorev doticonhtmldoticon

star image 5065 doticonCC-BY-4.0

Data science interview questions and answers

venom

by orkestral doticonjavascriptdoticon

star image 3775 doticonApache-2.0

Venom is the most complete javascript library for Whatsapp, 100% Open Source.

fosscord

by fosscord doticonjavascriptdoticon

star image 3576 doticonAGPL-3.0

Fosscord is a free open source selfhostable discord compatible communication platform

CrewLink

by ottomated doticontypescriptdoticon

star image 3159 doticonGPL-3.0

Free, open, Among Us Proximity Chat

script-commands

by raycast doticonshelldoticon

star image 2351 doticonMIT

Script Commands let you tailor Raycast to your needs. Think of them as little productivity boosts throughout your day.

pycord

by Pycord-Development doticonpythondoticon

star image 1944 doticonMIT

Pycord, a maintained fork of discord.py, is a python wrapper for the Discord API

clubhouse-py

by stypr doticonpythondoticon

star image 1669 doticonMIT

Clubhouse API written in Python. Standalone client included. For reference and education purposes only.

nonebot2

by nonebot doticonpythondoticon

star image 1525 doticonMIT

跨平台 Python 异步机器人框架 / Asynchronous multi-platform robot framework written in Python

dolby_beta

by nining377 doticoncdoticon

star image 1517 doticonMIT

杜比大喇叭的β版迎来了重大的革新,合并了UnblockMusic Pro的所有功能且更加强大,同时UnblockMusicPro_Xposed项目将会停止维护,让我们欢送这位老朋友!

Top Authors in Chat

1

getweapp

86 Libraries

star icon1233

2

wechaty

26 Libraries

star icon14368

3

RocketChat

21 Libraries

star icon3329

4

slackapi

20 Libraries

star icon1218

5

GetStream

19 Libraries

star icon1947

6

IBM

16 Libraries

star icon795

7

RasaHQ

14 Libraries

star icon15203

8

wechat-miniprogram

14 Libraries

star icon3162

9

TwilioDevEd

14 Libraries

star icon213

10

microsoft

14 Libraries

star icon1580

1

86 Libraries

star icon1233

2

26 Libraries

star icon14368

3

21 Libraries

star icon3329

4

20 Libraries

star icon1218

5

19 Libraries

star icon1947

6

16 Libraries

star icon795

7

14 Libraries

star icon15203

8

14 Libraries

star icon3162

9

14 Libraries

star icon213

10

14 Libraries

star icon1580

Trending Kits in Chat

Most Python Discord API libraries offer various features, making it easier to develop Discord bots and interact with the Discord API. Most Python Discord API libraries offer an effortless way of creating and managing bots on the Discord Platform. These libraries often offer functionality for handling events like a user joining a server, a reaction added to a message, or a message received.  


These libraries offer effortless ways to handle commands from the Discord server users. It can handle audio and voice functionalities, like streaming video, joining voice channels, and more. These support Discord’s new slash commands that offer an easy-to-use interface for users to interact with bots. It has a built-in caching mechanism for reducing the number of API requests to Discord and improving its performance. It offers methods for easily making requests to the Discord API and handling responses. It supports Discord webhooks by letting bots send messages and interact with Discord outside a server.  


Here is the list of the top 8 Python Discord API libraries that are handpicked to help developers: 

discord.py: 

  • Is an easy-to-use, asynchronous-ready, modern, and feature-rich API wrapper for Discord written in Python.  
  • Offers a simple and intuitive API to build Discord bots, making it accessible for developers of all skill sets.  
  • Has robust support for audio and voice, like streaming audio, joining voice channels, and many more.  

modmail: 

  • Is a Python library to build a moderation system within Discord servers. 
  • Allows users to contact server administration and moderators privately without having to share their messages publicly in a channel.  
  • Tracks user data like their conversation and messages history, making it easier for moderators to handle ongoing issues. 

nextcord: 

  • Is a Python library to build Discord bots that are forked from the original discord.py.  
  • Offers similar functionality as discord.py with certain improvements and changes.  
  • Has support for Discord’s new slash commands that offers an easy-to-use for users to interact with bots. 

hikari: 

  • Is a Python library to build Discord bots that aim to offer a modern and efficient API compared to other Python Discord libraries. 
  • Is designed with modern Python features like type hints and async/await. 
  • Is optimized for performance and uses asyncio for handling requests and events. 

interactions.py: 

  • Is a Python library that is a highly extensible, complete feature, and easy-to-use bot framework for Discord.  
  • Our HTTP client implements preemptive rate limit avoidance, so your bot is guaranteed never to hit HTTP 429.  
  • Each HTTP request and Gateway event made is cached if needed, so you never have to save information yourself. 

disnake: 

  • Is a fast, efficient, and modern Python library to build Discord bots, a fork of the discord.py library with many improvements.  
  • Is optimized for performance and uses asyncio to handle requests and events, making it one of the fastest Discord libraries.  
  • Discord’s components are supported in disnake, allowing more engaging and interactive bot experiences. 

jishaku: 

  • Is a debugging and testing extension for Discord.py, a popular Python library for creating Discord bots. 
  • Offers various utilities for debugging and testing Discord.py applications, like an interactive shell for running code snippets and functionality and commands for inspecting the current state of the server and bot.  
  • Advanced error handling and reports with detailed information about the cause of errors and how to fix them. 

Raid-Toolbox: 

  • A Python library is a big toolkit of raiding, token management, and spamming tools for Discord.  
  • Includes custom themes or skins, token checker, message spammer, and mass mentioner. 
  • Also includes DM spammer, Group DM spammer, image spammer, embed spammer, and Ascii spammer. 

Here are some of the famous Nodejs WhatsApp API Libraries. These Libraries are used for Creating interactive bots, Creating chatbots, Sending automated messages, and Integrating with other applications.


Node.js WhatsApp API Libraries are libraries that allow developers to create applications and services that interact with the WhatsApp messaging service. These libraries provide access to the WhatsApp API, allowing developers to create custom tools and applications that communicate with WhatsApp users. These libraries can be used to build bots, create custom chat experiences, and more.


Let us look at these libraries in detail below.

whatsapp-web.js

  • Auto-detection of incoming messages, allowing developers to respond quickly.
  • Built-in media upload and download support.
  • Built-in webhooks for automated responses.

Chat-API

  • Allows developers to build applications that integrate with multiple messaging platforms.
  • Provides support for multi-user chat rooms.
  • Allows developers to receive notifications whenever messages are sent or received.

sulla

  • Offers a wide range of analytics and reporting capabilities.
  • Integrates with other third-party services, such as Slack.
  • Powerful set of APIs for automating the WhatsApp messaging experience.

whats2api

  • Full control over incoming messages.
  • Event-driven notifications.
  • Flexible API calls and built-in security features.

whatsapi

  • Highly secure and provides end-to-end encryptions for all messages sent and received.
  • Provides a comprehensive set of features for managing contacts, groups, and conversations.
  • Allows developers to access and control the WhatsApp API directly from their applications.

wasapbot

  • Easy-to-use platform that allows you to quickly build a WhatsApp bot without the need to write any code.
  • Provides a user-friendly interface with a drag-and-drop editor to create sophisticated chatbots.
  • Handle complex conversations and can work with multiple users at the same time.

whatbot

  • Allows users to customize their conversations using a variety of built-in templates.
  • Provides an intuitive interface to set up automated messages and bot responses.
  • Ability to process incoming messages, and send and receive images and videos etc.

Django Calendar Libraries include Automating customer service, marketing, Creating chatbots, customer feedback, and Automating payments.  


Python WhatsApp API libraries are libraries of code written in the Python programming language that can develop applications that interact with the WhatsApp messaging platform. These libraries typically enable developers to create tools, bots, and other programs to send and receive messages, process messages and integrate with other services and APIs. 


Let us look at these libraries in detail. 

yowsup

  • Supports both the WhatsApp web and mobile platforms.
  • Allows developers to send and receive messages, images, videos, and audio files.
  • Supports group chats and broadcast messages.

whatsapp-framework

  • Offers a powerful text-parsing feature that allows developers to parse incoming messages. 
  • Supports both synchronous and asynchronous messaging.
  • Easy-to-use design helps developers quickly integrate its features into their applications.

PyWhatKit

  • Built-in scheduler allows you to schedule messages to be sent at a later date and time.   
  • Simple, intuitive, and user-friendly API. 
  • Possible to read incoming messages and respond to them.

PyWhatsapp

  • Offers a built-in event loop, which allows users to process incoming messages and react to them in real time.
  • Highly flexible and can be used to create powerful custom WhatsApp bots.
  • Supports media sending, which is unavailable in most other Python WhatsApp API libraries. 

whatsapp-cli

  • Command-line interface (CLI) tool allows users to interact directly with the WhatsApp API from their terminal.  
  • Many advanced features include group chats, file sharing, broadcast messages, and more.  
  • Built using the WhatsApp Web API, it is always up-to-date with the latest WhatsApp features. 

whatsapp-api-client-python

  • An automated setup process that makes it easy to get up and run quickly with the WhatsApp API.   
  • Supports both Python 2 and Python 3. 
  • Built-in error handling.

WhatsApp-Chat-Analyzer-API

  • Used to generate visualizations of the conversations, such as word clouds, heatmaps, and network graphs.
  • Provides a range of features for analyzing conversations, such as sentiment analysis, keyword extraction, and topic modeling.
  • Open source and is available for free.

whatsapp-wrapper

  • Provides a wrapper for the official WhatsApp API.
  • Built-in webhook system.
  • Provides robust API endpoints for creating, editing, and deleting conversations.

pywassap

  • Offers a complete suite of APIs to interact with WhatsApp services.
  • Highly customizable, allowing users to adjust the API to their specific needs.
  • Offers a secure and reliable connection with WhatsApp’s servers.

Chat-API

  • Automated message scheduling.
  • File and media messaging.
  • Easy integration with other apps and services.

FAQ  

What is WhatsApp Cloud API Python?  

WhatsApp API doesn’t directly interact with a “Cloud API” as other services do. It is typically hosted on the business’s servers. It allows them to send and receive messages through WhatsApp.   

  

What is the WhatsApp Business API?  

WhatsApp provides a Business API. It allows businesses API to provide a way for businesses to send messages to users. It helps receive messages from users and manage various aspects of business accounts.  


WhatsApp Business API supports various programming languages, including Python. It allows developers to integrate WhatsApp messaging capabilities into their applications.   

  

Is there a Python wrapper for WhatsApp?  

WhatsApp is restrictive about third-party applications. It helps in interacting with their service to maintain user privacy and security. However, there have been community-driven projects and third-party libraries. It provides Python wrappers or APIs to interact with WhatsApp.  


These might have limitations and may not be officially endorsed. However, it is crucial to be cautious when using such tools. It helps ensure compliance with WhatsApp’s terms of service.  

  

What are the different types of WhatsApp messages?  

WhatsApp supports various WhatsApp message types. It facilitates different forms of communication. Here are some common types of messages you can send and receive on WhatsApp:  

  • Text Messages  
  • Images and Videos  
  • Location Sharing  
  • Voice Messages  
  • Documents  
  • Stickers and Emojis  
  • Contacts  
  • Status Updates  
  • Reply and Quoted Messages  
  • GIFs  
  • Group Messages 

GPTs are about to be everything everywhere, all at once.

This means businesses will build private/public GPTs for specific functions, from drafting and scrutinizing legal compliance documents to creating tailored sales agreements for clientele.

Trending Discussions on Chat

How can I match if the current route matches a pattern in React Router Dom v6?

Redis NodeJs server error,client is closed

Google Play app rejected due to: Prominent disclosure Non compliant design for policy: Accessibility API

JetpackCompose Navigation Nested Graphs cause "ViewModelStore should be set before setGraph call" exception

slack chat.postMessage API endpoint is not allowing the authorization header

React/Socket.io not displaying latest message passed down as prop

Avoid rerendering every component in list while updating only one in React

Google Play App Rejection - Not a core feature - Use of All files access

How to add count values in venn diagram for more than 6 sets?

What do the values for gitlab's predefiner variable CI_PIPELINE_SOURCE mean?

QUESTION

How can I match if the current route matches a pattern in React Router Dom v6?

Asked 2022-Apr-07 at 19:55

I've got:

1export const ACCOUNT_PORTAL_PATHS = [
2      'home/*',
3      'my-care/*',
4      'chats/*',
5      'profile/*',
6      'programs/*',
7      'completion/*',
8    ]
9

If the current path is any of those, I want to know. I managed to get the current path with:

1export const ACCOUNT_PORTAL_PATHS = [
2      'home/*',
3      'my-care/*',
4      'chats/*',
5      'profile/*',
6      'programs/*',
7      'completion/*',
8    ]
9const { search: searchParams, pathname } = useLocation();
10

and that yields, in this example:

1export const ACCOUNT_PORTAL_PATHS = [
2      'home/*',
3      'my-care/*',
4      'chats/*',
5      'profile/*',
6      'programs/*',
7      'completion/*',
8    ]
9const { search: searchParams, pathname } = useLocation();
10pathname: "/my-care/1234"
11

What's the best way to match?

Thanks in advance!

ANSWER

Answered 2022-Apr-07 at 19:55

If you just want to know if you are on a matching path, you can use the matchPath function and test that some account path prefix is a match to the current pathname.

Example:

1export const ACCOUNT_PORTAL_PATHS = [
2      'home/*',
3      'my-care/*',
4      'chats/*',
5      'profile/*',
6      'programs/*',
7      'completion/*',
8    ]
9const { search: searchParams, pathname } = useLocation();
10pathname: "/my-care/1234"
11import { matchPath } from "react-router-dom";
12
13...
14
15const { pathname } = useLocation();
16const isMatch = ACCOUNT_PORTAL_PATHS.some((path) =>
17  matchPath(path, pathname)
18);
19

Edit epic-shtern-gyuolz

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

QUESTION

Redis NodeJs server error,client is closed

Asked 2022-Feb-11 at 05:16

I am developing an application where chats has to cached and monitored, currently it is an local application where i have installed redis and redis-cli. The problem i'm facing is (node:5368) UnhandledPromiseRejectionWarning: Error: The client is closed Attaching code snippet below

1//redis setup
2const redis = require('redis');
3const client = redis.createClient()//kept blank so that default options are available
4  
5
6//runs when client connects
7io.on("connect", function (socket) {
8
9  //this is client side socket
10  //console.log("a new user connected...");
11
12  socket.on("join", function ({ name, room }, callback) {
13    //console.log(name, room);
14    const { msg, user } = addUser({ id: socket.id, name, room });
15   // console.log(user);
16    if (msg) return callback(msg); //accessible in frontend
17
18    //emit to all users
19    socket.emit("message", {
20      user: "Admin",
21      text: `Welcome to the room ${user.name}`,
22    });
23    //emit to all users except current one
24  
25    socket.broadcast
26      .to(user.room)
27      .emit("message", { user: "Admin", text: `${user.name} has joined` });
28
29    socket.join(user.room); //pass the room that user wants to join
30
31    //get all users in the room
32    io.to(user.room).emit("roomData", {
33      room: user.room,
34      users: getUsersInRoom(user.room),
35    });
36
37    callback();
38  }); //end of join
39
40  //user generated messages
41  socket.on("sendMessage",  async(message, callback)=>{
42    const user = getUser(socket.id);
43
44    //this is where we can store the messages in redis
45    await client.set("messages",message);
46
47    io.to(user.room).emit("message", { user: user.name, text: message });
48    console.log(client.get('messages'));
49    callback();
50  }); //end of sendMessage
51
52  //when user disconnects
53  socket.on("disconnect", function () {
54    const user = removeUser(socket.id);
55    if (user) {
56     
57      console.log(client)
58
59      io.to(user.room).emit("message", {
60        user: "Admin",
61        text: `${user.name} has left `,
62      });
63    }
64  }); //end of disconnect
65
66

I am getting above error when user sends a message to the room or when socket.on("sendMessage") is called.

Where am I going wrong?

Thank you in advance.

ANSWER

Answered 2021-Dec-01 at 20:16

You should await client.connect() before using the client

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

QUESTION

Google Play app rejected due to: Prominent disclosure Non compliant design for policy: Accessibility API

Asked 2022-Jan-28 at 06:22

Our application is getting rejected from the play store for policy violation regarding

Prominent disclosure Non compliant design

for policy: Accessibility API

enter image description here

Initially we were using 3rd party library cobrowse, and they were using

android.permission.BIND_ACCESSIBILITY_SERVICE

and our app got rejected, after that, we had removed the library itself and now no accessibility permission is being asked in our manifest, and to comply with prominent disclosure we had taken the following steps:

  1. Added a Terms and conditions screen for all users.
  2. Added UI for prominent disclosure when requesting all permissions.

enter image description hereenter image description here

Note: Even tho we are not using the accessibility API, we kept its content as our rejection reason was still accessibility API even after removing service and library.

Target SDK: 31

We tried updating content and adding prominent disclosure UI still, the app is not getting accepted.

It's been 5 weeks and still no update from google over playstore, and they do not reply to emails, chats.

ANSWER

Answered 2021-Dec-22 at 11:00

Okay after having a discussion with 3rd party lib, they updated lib to ask for accessibility permission and we added proper consent and permission disclosure screens in the app, and it worked !!

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

QUESTION

JetpackCompose Navigation Nested Graphs cause "ViewModelStore should be set before setGraph call" exception

Asked 2022-Jan-21 at 07:35

I am trying to apply Jetpack Compose navigation into my application.

My Screens: Login/Register screens and Bottom navbar screens(call, chat, settings).

I already found out that the best way to do this is using nested graphs.

But I keep getting ViewModelStore should be set before setGraph call exception. However, I don't think this is the right exception.

My navigation is already in the latest version. Probably my nested graph logic is not right.

Requirement: I want to be able to navigate from the Login or Register screen to any BottomBar Screen & reverse

1@Composable
2fun SetupNavGraph(
3    navController: NavHostController,
4    userViewModel: UserViewModel
5) {
6    NavHost(
7        navController = navController,
8        startDestination = BOTTOM_BAR_GRAPH_ROUTE,
9        route = ROOT_GRAPH_ROUTE
10    ) {
11        loginNavGraph(navController = navController, userViewModel)
12        bottomBarNavGraph(navController = navController, userViewModel)
13    }
14}
15

NavGraph.kt

1@Composable
2fun SetupNavGraph(
3    navController: NavHostController,
4    userViewModel: UserViewModel
5) {
6    NavHost(
7        navController = navController,
8        startDestination = BOTTOM_BAR_GRAPH_ROUTE,
9        route = ROOT_GRAPH_ROUTE
10    ) {
11        loginNavGraph(navController = navController, userViewModel)
12        bottomBarNavGraph(navController = navController, userViewModel)
13    }
14}
15fun NavGraphBuilder.loginNavGraph(
16    navController: NavHostController,
17    userViewModel: UserViewModel
18) {
19    navigation(
20        startDestination = Screen.LoginScreen.route,
21        route = LOGIN_GRAPH_ROUTE
22    ) {
23        composable(
24            route = Screen.LoginScreen.route,
25            content = {
26                LoginScreen(
27                    navController = navController,
28                    loginViewModel = userViewModel
29                )
30            })
31        composable(
32            route = Screen.RegisterScreen.route,
33            content = {
34                RegisterScreen(
35                    navController = navController,
36                    loginViewModel = userViewModel
37                )
38            })
39    }
40}
41

LoginNavGraph.kt

1@Composable
2fun SetupNavGraph(
3    navController: NavHostController,
4    userViewModel: UserViewModel
5) {
6    NavHost(
7        navController = navController,
8        startDestination = BOTTOM_BAR_GRAPH_ROUTE,
9        route = ROOT_GRAPH_ROUTE
10    ) {
11        loginNavGraph(navController = navController, userViewModel)
12        bottomBarNavGraph(navController = navController, userViewModel)
13    }
14}
15fun NavGraphBuilder.loginNavGraph(
16    navController: NavHostController,
17    userViewModel: UserViewModel
18) {
19    navigation(
20        startDestination = Screen.LoginScreen.route,
21        route = LOGIN_GRAPH_ROUTE
22    ) {
23        composable(
24            route = Screen.LoginScreen.route,
25            content = {
26                LoginScreen(
27                    navController = navController,
28                    loginViewModel = userViewModel
29                )
30            })
31        composable(
32            route = Screen.RegisterScreen.route,
33            content = {
34                RegisterScreen(
35                    navController = navController,
36                    loginViewModel = userViewModel
37                )
38            })
39    }
40}
41fun NavGraphBuilder.bottomBarNavGraph(
42    navController: NavHostController,
43    userViewModel: UserViewModel
44) {
45    navigation(
46        startDestination = Screen.AppScaffold.route,
47        route = BOTTOM_BAR_GRAPH_ROUTE
48    ) {
49        composable(
50            route = Screen.AppScaffold.route,
51            content = {
52                AppScaffold(
53                    navController = navController,
54                    userViewModel = userViewModel
55                )
56            })
57    }
58}
59

BottomBarNavGraph.kt

1@Composable
2fun SetupNavGraph(
3    navController: NavHostController,
4    userViewModel: UserViewModel
5) {
6    NavHost(
7        navController = navController,
8        startDestination = BOTTOM_BAR_GRAPH_ROUTE,
9        route = ROOT_GRAPH_ROUTE
10    ) {
11        loginNavGraph(navController = navController, userViewModel)
12        bottomBarNavGraph(navController = navController, userViewModel)
13    }
14}
15fun NavGraphBuilder.loginNavGraph(
16    navController: NavHostController,
17    userViewModel: UserViewModel
18) {
19    navigation(
20        startDestination = Screen.LoginScreen.route,
21        route = LOGIN_GRAPH_ROUTE
22    ) {
23        composable(
24            route = Screen.LoginScreen.route,
25            content = {
26                LoginScreen(
27                    navController = navController,
28                    loginViewModel = userViewModel
29                )
30            })
31        composable(
32            route = Screen.RegisterScreen.route,
33            content = {
34                RegisterScreen(
35                    navController = navController,
36                    loginViewModel = userViewModel
37                )
38            })
39    }
40}
41fun NavGraphBuilder.bottomBarNavGraph(
42    navController: NavHostController,
43    userViewModel: UserViewModel
44) {
45    navigation(
46        startDestination = Screen.AppScaffold.route,
47        route = BOTTOM_BAR_GRAPH_ROUTE
48    ) {
49        composable(
50            route = Screen.AppScaffold.route,
51            content = {
52                AppScaffold(
53                    navController = navController,
54                    userViewModel = userViewModel
55                )
56            })
57    }
58}
59@Composable
60fun AppScaffold(
61    navController: NavHostController,
62    userViewModel: UserViewModel
63) {
64    val scaffoldState = rememberScaffoldState()
65
66    Scaffold(
67
68        bottomBar = {
69            BottomBar(mainNavController = navController)
70        },
71        scaffoldState = scaffoldState,
72
73        ) {
74
75        NavHost(
76            navController = navController,
77            startDestination = NavigationScreen.EmergencyCallScreen.route
78        ) {
79            composable(NavigationScreen.EmergencyCallScreen.route) {
80                EmergencyCallScreen(
81                    navController = navController,
82                    loginViewModel = userViewModel
83                )
84            }
85            composable(NavigationScreen.ChatScreen.route) { ChatScreen() }
86            composable(NavigationScreen.SettingsScreen.route) {
87                SettingsScreen(
88                    navController = navController,
89                    loginViewModel = userViewModel
90                )
91            }
92        }
93    }
94}
95

AppScaffold.kt

1@Composable
2fun SetupNavGraph(
3    navController: NavHostController,
4    userViewModel: UserViewModel
5) {
6    NavHost(
7        navController = navController,
8        startDestination = BOTTOM_BAR_GRAPH_ROUTE,
9        route = ROOT_GRAPH_ROUTE
10    ) {
11        loginNavGraph(navController = navController, userViewModel)
12        bottomBarNavGraph(navController = navController, userViewModel)
13    }
14}
15fun NavGraphBuilder.loginNavGraph(
16    navController: NavHostController,
17    userViewModel: UserViewModel
18) {
19    navigation(
20        startDestination = Screen.LoginScreen.route,
21        route = LOGIN_GRAPH_ROUTE
22    ) {
23        composable(
24            route = Screen.LoginScreen.route,
25            content = {
26                LoginScreen(
27                    navController = navController,
28                    loginViewModel = userViewModel
29                )
30            })
31        composable(
32            route = Screen.RegisterScreen.route,
33            content = {
34                RegisterScreen(
35                    navController = navController,
36                    loginViewModel = userViewModel
37                )
38            })
39    }
40}
41fun NavGraphBuilder.bottomBarNavGraph(
42    navController: NavHostController,
43    userViewModel: UserViewModel
44) {
45    navigation(
46        startDestination = Screen.AppScaffold.route,
47        route = BOTTOM_BAR_GRAPH_ROUTE
48    ) {
49        composable(
50            route = Screen.AppScaffold.route,
51            content = {
52                AppScaffold(
53                    navController = navController,
54                    userViewModel = userViewModel
55                )
56            })
57    }
58}
59@Composable
60fun AppScaffold(
61    navController: NavHostController,
62    userViewModel: UserViewModel
63) {
64    val scaffoldState = rememberScaffoldState()
65
66    Scaffold(
67
68        bottomBar = {
69            BottomBar(mainNavController = navController)
70        },
71        scaffoldState = scaffoldState,
72
73        ) {
74
75        NavHost(
76            navController = navController,
77            startDestination = NavigationScreen.EmergencyCallScreen.route
78        ) {
79            composable(NavigationScreen.EmergencyCallScreen.route) {
80                EmergencyCallScreen(
81                    navController = navController,
82                    loginViewModel = userViewModel
83                )
84            }
85            composable(NavigationScreen.ChatScreen.route) { ChatScreen() }
86            composable(NavigationScreen.SettingsScreen.route) {
87                SettingsScreen(
88                    navController = navController,
89                    loginViewModel = userViewModel
90                )
91            }
92        }
93    }
94}
95@Composable
96fun BottomBar(mainNavController: NavHostController) {
97
98    val items = listOf(
99        NavigationScreen.EmergencyCallScreen,
100        NavigationScreen.ChatScreen,
101        NavigationScreen.SettingsScreen,
102    )
103
104    BottomNavigation(
105        elevation = 5.dp,
106    ) {
107        val navBackStackEntry by mainNavController.currentBackStackEntryAsState()
108        val currentRoute = navBackStackEntry?.destination?.route
109        items.map {
110            BottomNavigationItem(
111                icon = {
112                    Icon(
113                        painter = painterResource(id = it.icon),
114                        contentDescription = it.title
115                    )
116                },
117                label = {
118                    Text(
119                        text = it.title
120                    )
121                },
122                selected = currentRoute == it.route,
123                selectedContentColor = Color.White,
124                unselectedContentColor = Color.White.copy(alpha = 0.4f),
125                onClick = {
126                    mainNavController.navigate(it.route) {
127                        mainNavController.graph.startDestinationRoute?.let { route ->
128                            popUpTo(route) {
129                                saveState = true
130                            }
131                        }
132                        restoreState = true
133                        launchSingleTop = true
134                    }
135                },
136
137                )
138        }
139
140    }
141}
142

BottomBar.kt

1@Composable
2fun SetupNavGraph(
3    navController: NavHostController,
4    userViewModel: UserViewModel
5) {
6    NavHost(
7        navController = navController,
8        startDestination = BOTTOM_BAR_GRAPH_ROUTE,
9        route = ROOT_GRAPH_ROUTE
10    ) {
11        loginNavGraph(navController = navController, userViewModel)
12        bottomBarNavGraph(navController = navController, userViewModel)
13    }
14}
15fun NavGraphBuilder.loginNavGraph(
16    navController: NavHostController,
17    userViewModel: UserViewModel
18) {
19    navigation(
20        startDestination = Screen.LoginScreen.route,
21        route = LOGIN_GRAPH_ROUTE
22    ) {
23        composable(
24            route = Screen.LoginScreen.route,
25            content = {
26                LoginScreen(
27                    navController = navController,
28                    loginViewModel = userViewModel
29                )
30            })
31        composable(
32            route = Screen.RegisterScreen.route,
33            content = {
34                RegisterScreen(
35                    navController = navController,
36                    loginViewModel = userViewModel
37                )
38            })
39    }
40}
41fun NavGraphBuilder.bottomBarNavGraph(
42    navController: NavHostController,
43    userViewModel: UserViewModel
44) {
45    navigation(
46        startDestination = Screen.AppScaffold.route,
47        route = BOTTOM_BAR_GRAPH_ROUTE
48    ) {
49        composable(
50            route = Screen.AppScaffold.route,
51            content = {
52                AppScaffold(
53                    navController = navController,
54                    userViewModel = userViewModel
55                )
56            })
57    }
58}
59@Composable
60fun AppScaffold(
61    navController: NavHostController,
62    userViewModel: UserViewModel
63) {
64    val scaffoldState = rememberScaffoldState()
65
66    Scaffold(
67
68        bottomBar = {
69            BottomBar(mainNavController = navController)
70        },
71        scaffoldState = scaffoldState,
72
73        ) {
74
75        NavHost(
76            navController = navController,
77            startDestination = NavigationScreen.EmergencyCallScreen.route
78        ) {
79            composable(NavigationScreen.EmergencyCallScreen.route) {
80                EmergencyCallScreen(
81                    navController = navController,
82                    loginViewModel = userViewModel
83                )
84            }
85            composable(NavigationScreen.ChatScreen.route) { ChatScreen() }
86            composable(NavigationScreen.SettingsScreen.route) {
87                SettingsScreen(
88                    navController = navController,
89                    loginViewModel = userViewModel
90                )
91            }
92        }
93    }
94}
95@Composable
96fun BottomBar(mainNavController: NavHostController) {
97
98    val items = listOf(
99        NavigationScreen.EmergencyCallScreen,
100        NavigationScreen.ChatScreen,
101        NavigationScreen.SettingsScreen,
102    )
103
104    BottomNavigation(
105        elevation = 5.dp,
106    ) {
107        val navBackStackEntry by mainNavController.currentBackStackEntryAsState()
108        val currentRoute = navBackStackEntry?.destination?.route
109        items.map {
110            BottomNavigationItem(
111                icon = {
112                    Icon(
113                        painter = painterResource(id = it.icon),
114                        contentDescription = it.title
115                    )
116                },
117                label = {
118                    Text(
119                        text = it.title
120                    )
121                },
122                selected = currentRoute == it.route,
123                selectedContentColor = Color.White,
124                unselectedContentColor = Color.White.copy(alpha = 0.4f),
125                onClick = {
126                    mainNavController.navigate(it.route) {
127                        mainNavController.graph.startDestinationRoute?.let { route ->
128                            popUpTo(route) {
129                                saveState = true
130                            }
131                        }
132                        restoreState = true
133                        launchSingleTop = true
134                    }
135                },
136
137                )
138        }
139
140    }
141}
142const val ROOT_GRAPH_ROUTE = "root"
143const val LOGIN_GRAPH_ROUTE = "login_register"
144const val BOTTOM_BAR_GRAPH_ROUTE = "bottom_bar"
145
146sealed class Screen(val route: String) {
147    object LoginScreen : Screen("login_screen")
148    object RegisterScreen : Screen("register_screen")
149    object AppScaffold : Screen("app_scaffold")
150
151}
152

Screen.kt

1@Composable
2fun SetupNavGraph(
3    navController: NavHostController,
4    userViewModel: UserViewModel
5) {
6    NavHost(
7        navController = navController,
8        startDestination = BOTTOM_BAR_GRAPH_ROUTE,
9        route = ROOT_GRAPH_ROUTE
10    ) {
11        loginNavGraph(navController = navController, userViewModel)
12        bottomBarNavGraph(navController = navController, userViewModel)
13    }
14}
15fun NavGraphBuilder.loginNavGraph(
16    navController: NavHostController,
17    userViewModel: UserViewModel
18) {
19    navigation(
20        startDestination = Screen.LoginScreen.route,
21        route = LOGIN_GRAPH_ROUTE
22    ) {
23        composable(
24            route = Screen.LoginScreen.route,
25            content = {
26                LoginScreen(
27                    navController = navController,
28                    loginViewModel = userViewModel
29                )
30            })
31        composable(
32            route = Screen.RegisterScreen.route,
33            content = {
34                RegisterScreen(
35                    navController = navController,
36                    loginViewModel = userViewModel
37                )
38            })
39    }
40}
41fun NavGraphBuilder.bottomBarNavGraph(
42    navController: NavHostController,
43    userViewModel: UserViewModel
44) {
45    navigation(
46        startDestination = Screen.AppScaffold.route,
47        route = BOTTOM_BAR_GRAPH_ROUTE
48    ) {
49        composable(
50            route = Screen.AppScaffold.route,
51            content = {
52                AppScaffold(
53                    navController = navController,
54                    userViewModel = userViewModel
55                )
56            })
57    }
58}
59@Composable
60fun AppScaffold(
61    navController: NavHostController,
62    userViewModel: UserViewModel
63) {
64    val scaffoldState = rememberScaffoldState()
65
66    Scaffold(
67
68        bottomBar = {
69            BottomBar(mainNavController = navController)
70        },
71        scaffoldState = scaffoldState,
72
73        ) {
74
75        NavHost(
76            navController = navController,
77            startDestination = NavigationScreen.EmergencyCallScreen.route
78        ) {
79            composable(NavigationScreen.EmergencyCallScreen.route) {
80                EmergencyCallScreen(
81                    navController = navController,
82                    loginViewModel = userViewModel
83                )
84            }
85            composable(NavigationScreen.ChatScreen.route) { ChatScreen() }
86            composable(NavigationScreen.SettingsScreen.route) {
87                SettingsScreen(
88                    navController = navController,
89                    loginViewModel = userViewModel
90                )
91            }
92        }
93    }
94}
95@Composable
96fun BottomBar(mainNavController: NavHostController) {
97
98    val items = listOf(
99        NavigationScreen.EmergencyCallScreen,
100        NavigationScreen.ChatScreen,
101        NavigationScreen.SettingsScreen,
102    )
103
104    BottomNavigation(
105        elevation = 5.dp,
106    ) {
107        val navBackStackEntry by mainNavController.currentBackStackEntryAsState()
108        val currentRoute = navBackStackEntry?.destination?.route
109        items.map {
110            BottomNavigationItem(
111                icon = {
112                    Icon(
113                        painter = painterResource(id = it.icon),
114                        contentDescription = it.title
115                    )
116                },
117                label = {
118                    Text(
119                        text = it.title
120                    )
121                },
122                selected = currentRoute == it.route,
123                selectedContentColor = Color.White,
124                unselectedContentColor = Color.White.copy(alpha = 0.4f),
125                onClick = {
126                    mainNavController.navigate(it.route) {
127                        mainNavController.graph.startDestinationRoute?.let { route ->
128                            popUpTo(route) {
129                                saveState = true
130                            }
131                        }
132                        restoreState = true
133                        launchSingleTop = true
134                    }
135                },
136
137                )
138        }
139
140    }
141}
142const val ROOT_GRAPH_ROUTE = "root"
143const val LOGIN_GRAPH_ROUTE = "login_register"
144const val BOTTOM_BAR_GRAPH_ROUTE = "bottom_bar"
145
146sealed class Screen(val route: String) {
147    object LoginScreen : Screen("login_screen")
148    object RegisterScreen : Screen("register_screen")
149    object AppScaffold : Screen("app_scaffold")
150
151}
152sealed class NavigationScreen(val route: String, val title: String, @DrawableRes val icon: Int) {
153    object EmergencyCallScreen : NavigationScreen(
154        route = "emergency_call_screen",
155        title = "Emergency Call",
156        icon = R.drawable.ic_phone
157    )
158
159    object ChatScreen :
160        NavigationScreen(
161            route = "chat_screen",
162            title = "Chat",
163            icon = R.drawable.ic_chat)
164
165    object SettingsScreen : NavigationScreen(
166        route = "settings_screen",
167        title = "Settings",
168        icon = R.drawable.ic_settings
169    )
170}
171

NavigationScreen.kt

ANSWER

Answered 2021-Nov-13 at 16:37

Nesting of NavHost is not allowed. It results in ViewModelStore should be set before setGraph call Exception. Generally, the bottom nav is outside of the NavHost, which is what the docs show. The recommended approach is a single NavHost, where you hide and show your bottom nav based on what destination you are on.

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

QUESTION

slack chat.postMessage API endpoint is not allowing the authorization header

Asked 2022-Jan-17 at 23:28

I have this code running in the browser

1<html>
2
3    <script type="module">
4        console.log("working");
5
6        var url = "https://slack.com/api/chat.postMessage";
7        var auth_token = "xoxb-2B"; //Your Bot's auth token
8        var body = {channel: "ses", text: "testing app"}
9
10        async function postData(url = '', data = {}) {
11            // Default options are marked with *
12            const response = await fetch(url, {
13                method: 'POST', // *GET, POST, PUT, DELETE, etc.
14                headers: {
15                    "Authorization": "Bearer " + auth_token,
16                    "Content-Type" : "application/json"
17                },
18                body: JSON.stringify(data) // body data type must match "Content-Type" header
19            });
20            return response.json(); // parses JSON response into native JavaScript objects
21        }
22
23        postData('https://slack.com/api/chat.postMessage', body)
24        .then(data => {
25            console.log(data); // JSON data parsed by `data.json()` call
26        });
27    </script>
28</html>
29

I'm getting

Access to fetch at 'https://slack.com/api/chat.postMessage' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.

I don't understand, I need to specify the bearer token somehow, even in the docs it says to put it in the Authorization header, why aren't they allowing it?

ANSWER

Answered 2022-Jan-17 at 23:28

I don't understand, I need to specify the bearer token somehow, even in the docs it says to put it in the Authorization header, why aren't they allowing it?

This is a different problem, is not related to the Bearer token at all. From the error you're getting, it means, the origin you're using to fetch the Slack API, is not trusted (http://127.0.0.1:5500), there is nothing you can do from the browser since this is a policy that comes from the server which defines the authorized origins. (Learn more about CORS here) Since I don't think this is supported by Slack, you will need to fetch the Slack API from the server.

One way to solve this, is by exposing a backend API, for example:

Post a message to Slack                                                                                 Run in Fusebit
1<html>
2
3    <script type="module">
4        console.log("working");
5
6        var url = "https://slack.com/api/chat.postMessage";
7        var auth_token = "xoxb-2B"; //Your Bot's auth token
8        var body = {channel: "ses", text: "testing app"}
9
10        async function postData(url = '', data = {}) {
11            // Default options are marked with *
12            const response = await fetch(url, {
13                method: 'POST', // *GET, POST, PUT, DELETE, etc.
14                headers: {
15                    "Authorization": "Bearer " + auth_token,
16                    "Content-Type" : "application/json"
17                },
18                body: JSON.stringify(data) // body data type must match "Content-Type" header
19            });
20            return response.json(); // parses JSON response into native JavaScript objects
21        }
22
23        postData('https://slack.com/api/chat.postMessage', body)
24        .then(data => {
25            console.log(data); // JSON data parsed by `data.json()` call
26        });
27    </script>
28</html>
29router.post('/api/tenant/:tenantId/test', async (ctx) => {
30  // Create a Slack client pre-configured with credentials necessary to communicate with your tenant's Slack workspace.
31  // For the Slack SDK documentation, see https://slack.dev/node-slack-sdk/web-api.
32  const slackClient = await integration.tenant.getSdkByTenant(ctx, connectorName, ctx.params.tenantId);
33
34  // Get the Slack user ID associated with your tenant
35  const slackUserId = slackClient.fusebit.credentials.authed_user.id;
36
37  // Send a Direct Message to the Slack user
38  const result = await slackClient.chat.postMessage({
39    text: 'Hello world!',
40    channel: slackUserId,
41  });
42
43  console.log('message response', result.message);
44  ctx.body = { message: `Successfully sent a message to Slack user ${slackUserId}!` };
45});
46
47

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

QUESTION

React/Socket.io not displaying latest message passed down as prop

Asked 2022-Jan-13 at 17:37

I am working on a chat application using React and socket.io. Back end is express/node. The relevant components are: Room.js --> Chat.js --> Messages.js --> Message.js

messageData received from the server is stored in state in Room.js. It is then passed down through Chat.js to Messages.js, where it is mapped onto a series of Message.js components.

When messages are received, they ARE appearing, but only after I start typing in the form again, triggering messageChangeHandler(). Any ideas why the Messages won't re-render when a new message is received and added to state in Room.js? I have confirmed that the state and props are updating everywhere they should be--they just aren't appearing/re-rendering until messageChangeHandler() triggers its own re-render.

Here are the components.

Room.js

1export default function Room(props) {
2    const [messagesData, setMessagesData] = useState([])
3
4    useEffect(() => {
5        console.log('the use effect ')
6        socket.on('broadcast', data => {
7            console.log(messagesData)
8            let previousData = messagesData
9            previousData.push(data)
10            // buildMessages(previousData)
11            setMessagesData(previousData)
12        })
13    }, [socket])
14
15
16    console.log('this is messagesData in queue.js', messagesData)
17
18    return(
19        // queue counter will go up here
20        // <QueueDisplay />
21
22        // chat goes here
23        <Chat 
24            profile={props.profile} 
25            messagesData={messagesData}
26        />
27
28    )
29}
30

Chat.js

1export default function Room(props) {
2    const [messagesData, setMessagesData] = useState([])
3
4    useEffect(() => {
5        console.log('the use effect ')
6        socket.on('broadcast', data => {
7            console.log(messagesData)
8            let previousData = messagesData
9            previousData.push(data)
10            // buildMessages(previousData)
11            setMessagesData(previousData)
12        })
13    }, [socket])
14
15
16    console.log('this is messagesData in queue.js', messagesData)
17
18    return(
19        // queue counter will go up here
20        // <QueueDisplay />
21
22        // chat goes here
23        <Chat 
24            profile={props.profile} 
25            messagesData={messagesData}
26        />
27
28    )
29}
30export default function Chat(props) {
31    // state
32    const [newPayload, setNewPayload] = useState({
33        message: '',
34        sender: props.profile.name
35    })
36    // const [messagesData, setMessagesData] = useState([])
37    const [updateToggle, setUpdateToggle] = useState(true)
38
39
40    const messageChangeHandler = (e) => {
41        setNewPayload({... newPayload, [e.target.name]: e.target.value})
42    }
43
44    const messageSend = (e) => {
45        e.preventDefault()
46        if (newPayload.message) {
47            socket.emit('chat message', newPayload)
48            setNewPayload({
49                message: '',
50                sender: props.profile.name  
51            })
52        }
53    }
54    
55    return(
56        <div id='chatbox'>
57            <div id='messages'>
58                <Messages messagesData={props.messagesData} />
59            </div>
60            <form onSubmit={messageSend}>
61                <input 
62                    type="text" 
63                    name="message" 
64                    id="message" 
65                    placeholder="Start a new message" 
66                    onChange={messageChangeHandler} 
67                    value={newPayload.message}
68                    autoComplete='off'
69                />
70                <input type="submit" value="Send" />
71            </form>
72        </div>
73    )
74}
75

Messages.js

1export default function Room(props) {
2    const [messagesData, setMessagesData] = useState([])
3
4    useEffect(() => {
5        console.log('the use effect ')
6        socket.on('broadcast', data => {
7            console.log(messagesData)
8            let previousData = messagesData
9            previousData.push(data)
10            // buildMessages(previousData)
11            setMessagesData(previousData)
12        })
13    }, [socket])
14
15
16    console.log('this is messagesData in queue.js', messagesData)
17
18    return(
19        // queue counter will go up here
20        // <QueueDisplay />
21
22        // chat goes here
23        <Chat 
24            profile={props.profile} 
25            messagesData={messagesData}
26        />
27
28    )
29}
30export default function Chat(props) {
31    // state
32    const [newPayload, setNewPayload] = useState({
33        message: '',
34        sender: props.profile.name
35    })
36    // const [messagesData, setMessagesData] = useState([])
37    const [updateToggle, setUpdateToggle] = useState(true)
38
39
40    const messageChangeHandler = (e) => {
41        setNewPayload({... newPayload, [e.target.name]: e.target.value})
42    }
43
44    const messageSend = (e) => {
45        e.preventDefault()
46        if (newPayload.message) {
47            socket.emit('chat message', newPayload)
48            setNewPayload({
49                message: '',
50                sender: props.profile.name  
51            })
52        }
53    }
54    
55    return(
56        <div id='chatbox'>
57            <div id='messages'>
58                <Messages messagesData={props.messagesData} />
59            </div>
60            <form onSubmit={messageSend}>
61                <input 
62                    type="text" 
63                    name="message" 
64                    id="message" 
65                    placeholder="Start a new message" 
66                    onChange={messageChangeHandler} 
67                    value={newPayload.message}
68                    autoComplete='off'
69                />
70                <input type="submit" value="Send" />
71            </form>
72        </div>
73    )
74}
75export default function Messages(props) {
76    return(
77        <>
78        {props.messagesData.map((data, i) => {
79            return <Message key={i} sender={data.sender} message={data.message} />
80        })}
81        </>
82    )
83}
84

Message.js

1export default function Room(props) {
2    const [messagesData, setMessagesData] = useState([])
3
4    useEffect(() => {
5        console.log('the use effect ')
6        socket.on('broadcast', data => {
7            console.log(messagesData)
8            let previousData = messagesData
9            previousData.push(data)
10            // buildMessages(previousData)
11            setMessagesData(previousData)
12        })
13    }, [socket])
14
15
16    console.log('this is messagesData in queue.js', messagesData)
17
18    return(
19        // queue counter will go up here
20        // <QueueDisplay />
21
22        // chat goes here
23        <Chat 
24            profile={props.profile} 
25            messagesData={messagesData}
26        />
27
28    )
29}
30export default function Chat(props) {
31    // state
32    const [newPayload, setNewPayload] = useState({
33        message: '',
34        sender: props.profile.name
35    })
36    // const [messagesData, setMessagesData] = useState([])
37    const [updateToggle, setUpdateToggle] = useState(true)
38
39
40    const messageChangeHandler = (e) => {
41        setNewPayload({... newPayload, [e.target.name]: e.target.value})
42    }
43
44    const messageSend = (e) => {
45        e.preventDefault()
46        if (newPayload.message) {
47            socket.emit('chat message', newPayload)
48            setNewPayload({
49                message: '',
50                sender: props.profile.name  
51            })
52        }
53    }
54    
55    return(
56        <div id='chatbox'>
57            <div id='messages'>
58                <Messages messagesData={props.messagesData} />
59            </div>
60            <form onSubmit={messageSend}>
61                <input 
62                    type="text" 
63                    name="message" 
64                    id="message" 
65                    placeholder="Start a new message" 
66                    onChange={messageChangeHandler} 
67                    value={newPayload.message}
68                    autoComplete='off'
69                />
70                <input type="submit" value="Send" />
71            </form>
72        </div>
73    )
74}
75export default function Messages(props) {
76    return(
77        <>
78        {props.messagesData.map((data, i) => {
79            return <Message key={i} sender={data.sender} message={data.message} />
80        })}
81        </>
82    )
83}
84export default function Message(props) {
85    return(
86        <div key={props.key}>
87            <p>{props.sender}</p>
88            <p>{props.message}</p>
89        </div>
90    )
91}
92

Thank you in advance for any help!

ANSWER

Answered 2022-Jan-11 at 19:44

Changing the useEffect in room to contain the following fixed the issue:

1export default function Room(props) {
2    const [messagesData, setMessagesData] = useState([])
3
4    useEffect(() => {
5        console.log('the use effect ')
6        socket.on('broadcast', data => {
7            console.log(messagesData)
8            let previousData = messagesData
9            previousData.push(data)
10            // buildMessages(previousData)
11            setMessagesData(previousData)
12        })
13    }, [socket])
14
15
16    console.log('this is messagesData in queue.js', messagesData)
17
18    return(
19        // queue counter will go up here
20        // <QueueDisplay />
21
22        // chat goes here
23        <Chat 
24            profile={props.profile} 
25            messagesData={messagesData}
26        />
27
28    )
29}
30export default function Chat(props) {
31    // state
32    const [newPayload, setNewPayload] = useState({
33        message: '',
34        sender: props.profile.name
35    })
36    // const [messagesData, setMessagesData] = useState([])
37    const [updateToggle, setUpdateToggle] = useState(true)
38
39
40    const messageChangeHandler = (e) => {
41        setNewPayload({... newPayload, [e.target.name]: e.target.value})
42    }
43
44    const messageSend = (e) => {
45        e.preventDefault()
46        if (newPayload.message) {
47            socket.emit('chat message', newPayload)
48            setNewPayload({
49                message: '',
50                sender: props.profile.name  
51            })
52        }
53    }
54    
55    return(
56        <div id='chatbox'>
57            <div id='messages'>
58                <Messages messagesData={props.messagesData} />
59            </div>
60            <form onSubmit={messageSend}>
61                <input 
62                    type="text" 
63                    name="message" 
64                    id="message" 
65                    placeholder="Start a new message" 
66                    onChange={messageChangeHandler} 
67                    value={newPayload.message}
68                    autoComplete='off'
69                />
70                <input type="submit" value="Send" />
71            </form>
72        </div>
73    )
74}
75export default function Messages(props) {
76    return(
77        <>
78        {props.messagesData.map((data, i) => {
79            return <Message key={i} sender={data.sender} message={data.message} />
80        })}
81        </>
82    )
83}
84export default function Message(props) {
85    return(
86        <div key={props.key}>
87            <p>{props.sender}</p>
88            <p>{props.message}</p>
89        </div>
90    )
91}
92    useEffect(() => {
93        console.log('the use effect ')
94        socket.on('broadcast', data => {
95            console.log(messagesData)
96            // let previousData = messagesData
97            // previousData.push(data)
98            // setMessagesData(previousData)
99            setMessagesData(prev => prev.concat([data]))
100        })
101    }, [socket])```
102

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

QUESTION

Avoid rerendering every component in list while updating only one in React

Asked 2021-Dec-17 at 07:39

I have a simple chat app using Firebase v9, with these components from parent to child in this hierarchical order: ChatSection, Chat, ChatLine, EditMessage.

I have a custom hook named useChatService holding the list of messages in state, the hook is called in ChatSection, the hook returns the messages and I pass them from ChatSection in a prop to Chat, then I loop through messages and create a ChatLine component for every message.

I can click the Edit button in front of each message, it shows the EditMessage component so I can edit the text, then when I press "Enter", the function updateMessage gets executed and updates the message in the db, but then every single ChatLine gets rerendered again, which is a problem as the list gets bigger.

EDIT 2: I've completed the code to make a working example with Firebase v9 so you can visualize the rerenders I'm talking about after every (add, edit or delete) of a message. I'm using ReactDevTools Profiler to track rerenders.

ChatSection.js:

1import useChatService from "../hooks/useChatService";
2import { useEffect } from "react";
3import Chat from "./Chat";
4import NoChat from "./NoChat";
5import ChatInput from "./ChatInput";
6
7const ChatSection = () => {
8  let unsubscribe;
9  const { getChatAndUnsub, messages } = useChatService();
10
11  useEffect(() => {
12    const getChat = async () => {
13      unsubscribe = await getChatAndUnsub();
14    };
15
16    getChat();
17
18    return () => {
19      unsubscribe?.();
20    };
21  }, []);
22
23  return (
24    <div>
25      {messages.length ? <Chat messages={messages} /> : <NoChat />}
26      <p>ADD A MESSAGE</p>
27      <ChatInput />
28    </div>
29  );
30};
31
32export default ChatSection;
33

Chat.js:

1import useChatService from "../hooks/useChatService";
2import { useEffect } from "react";
3import Chat from "./Chat";
4import NoChat from "./NoChat";
5import ChatInput from "./ChatInput";
6
7const ChatSection = () => {
8  let unsubscribe;
9  const { getChatAndUnsub, messages } = useChatService();
10
11  useEffect(() => {
12    const getChat = async () => {
13      unsubscribe = await getChatAndUnsub();
14    };
15
16    getChat();
17
18    return () => {
19      unsubscribe?.();
20    };
21  }, []);
22
23  return (
24    <div>
25      {messages.length ? <Chat messages={messages} /> : <NoChat />}
26      <p>ADD A MESSAGE</p>
27      <ChatInput />
28    </div>
29  );
30};
31
32export default ChatSection;
33import { useState } from "react";
34import ChatLine from "./ChatLine";
35import useChatService from "../hooks/useChatService";
36
37const Chat = ({ messages }) => {
38  const [editValue, setEditValue] = useState("");
39  const [editingId, setEditingId] = useState(null);
40
41  const { updateMessage, deleteMessage } = useChatService();
42
43  return (
44    <div>
45      <p>MESSAGES :</p>
46      {messages.map((line) => (
47        <ChatLine
48          key={line.id}
49          line={line}
50          editValue={line.id === editingId ? editValue : ""}
51          setEditValue={setEditValue}
52          editingId={line.id === editingId ? editingId : null}
53          setEditingId={setEditingId}
54          updateMessage={updateMessage}
55          deleteMessage={deleteMessage}
56        />
57      ))}
58    </div>
59  );
60};
61
62export default Chat;
63

ChatInput:

1import useChatService from "../hooks/useChatService";
2import { useEffect } from "react";
3import Chat from "./Chat";
4import NoChat from "./NoChat";
5import ChatInput from "./ChatInput";
6
7const ChatSection = () => {
8  let unsubscribe;
9  const { getChatAndUnsub, messages } = useChatService();
10
11  useEffect(() => {
12    const getChat = async () => {
13      unsubscribe = await getChatAndUnsub();
14    };
15
16    getChat();
17
18    return () => {
19      unsubscribe?.();
20    };
21  }, []);
22
23  return (
24    <div>
25      {messages.length ? <Chat messages={messages} /> : <NoChat />}
26      <p>ADD A MESSAGE</p>
27      <ChatInput />
28    </div>
29  );
30};
31
32export default ChatSection;
33import { useState } from "react";
34import ChatLine from "./ChatLine";
35import useChatService from "../hooks/useChatService";
36
37const Chat = ({ messages }) => {
38  const [editValue, setEditValue] = useState("");
39  const [editingId, setEditingId] = useState(null);
40
41  const { updateMessage, deleteMessage } = useChatService();
42
43  return (
44    <div>
45      <p>MESSAGES :</p>
46      {messages.map((line) => (
47        <ChatLine
48          key={line.id}
49          line={line}
50          editValue={line.id === editingId ? editValue : ""}
51          setEditValue={setEditValue}
52          editingId={line.id === editingId ? editingId : null}
53          setEditingId={setEditingId}
54          updateMessage={updateMessage}
55          deleteMessage={deleteMessage}
56        />
57      ))}
58    </div>
59  );
60};
61
62export default Chat;
63import { useState } from "react";
64import useChatService from "../hooks/useChatService";
65
66const ChatInput = () => {
67  const [inputValue, setInputValue] = useState("");
68  const { addMessage } = useChatService();
69
70  return (
71    <textarea
72      onKeyPress={(e) => {
73        if (e.key === "Enter") {
74          e.preventDefault();
75          addMessage(inputValue);
76          setInputValue("");
77        }
78      }}
79      placeholder="new message..."
80      onChange={(e) => {
81        setInputValue(e.target.value);
82      }}
83      value={inputValue}
84      autoFocus
85    />
86  );
87};
88
89export default ChatInput;
90

ChatLine.js:

1import useChatService from "../hooks/useChatService";
2import { useEffect } from "react";
3import Chat from "./Chat";
4import NoChat from "./NoChat";
5import ChatInput from "./ChatInput";
6
7const ChatSection = () => {
8  let unsubscribe;
9  const { getChatAndUnsub, messages } = useChatService();
10
11  useEffect(() => {
12    const getChat = async () => {
13      unsubscribe = await getChatAndUnsub();
14    };
15
16    getChat();
17
18    return () => {
19      unsubscribe?.();
20    };
21  }, []);
22
23  return (
24    <div>
25      {messages.length ? <Chat messages={messages} /> : <NoChat />}
26      <p>ADD A MESSAGE</p>
27      <ChatInput />
28    </div>
29  );
30};
31
32export default ChatSection;
33import { useState } from "react";
34import ChatLine from "./ChatLine";
35import useChatService from "../hooks/useChatService";
36
37const Chat = ({ messages }) => {
38  const [editValue, setEditValue] = useState("");
39  const [editingId, setEditingId] = useState(null);
40
41  const { updateMessage, deleteMessage } = useChatService();
42
43  return (
44    <div>
45      <p>MESSAGES :</p>
46      {messages.map((line) => (
47        <ChatLine
48          key={line.id}
49          line={line}
50          editValue={line.id === editingId ? editValue : ""}
51          setEditValue={setEditValue}
52          editingId={line.id === editingId ? editingId : null}
53          setEditingId={setEditingId}
54          updateMessage={updateMessage}
55          deleteMessage={deleteMessage}
56        />
57      ))}
58    </div>
59  );
60};
61
62export default Chat;
63import { useState } from "react";
64import useChatService from "../hooks/useChatService";
65
66const ChatInput = () => {
67  const [inputValue, setInputValue] = useState("");
68  const { addMessage } = useChatService();
69
70  return (
71    <textarea
72      onKeyPress={(e) => {
73        if (e.key === "Enter") {
74          e.preventDefault();
75          addMessage(inputValue);
76          setInputValue("");
77        }
78      }}
79      placeholder="new message..."
80      onChange={(e) => {
81        setInputValue(e.target.value);
82      }}
83      value={inputValue}
84      autoFocus
85    />
86  );
87};
88
89export default ChatInput;
90import EditMessage from "./EditMessage";
91import { memo } from "react";
92
93const ChatLine = ({
94  line,
95  editValue,
96  setEditValue,
97  editingId,
98  setEditingId,
99  updateMessage,
100  deleteMessage,
101}) => {
102  return (
103    <div>
104      {editingId !== line.id ? (
105        <>
106          <span style={{ marginRight: "20px" }}>{line.id}: </span>
107          <span style={{ marginRight: "20px" }}>[{line.displayName}]</span>
108          <span style={{ marginRight: "20px" }}>{line.message}</span>
109          <button
110            onClick={() => {
111              setEditingId(line.id);
112              setEditValue(line.message);
113            }}
114          >
115            EDIT
116          </button>
117          <button
118            onClick={() => {
119              deleteMessage(line.id);
120            }}
121          >
122            DELETE
123          </button>
124        </>
125      ) : (
126        <EditMessage
127          editValue={editValue}
128          setEditValue={setEditValue}
129          setEditingId={setEditingId}
130          editingId={editingId}
131          updateMessage={updateMessage}
132        />
133      )}
134    </div>
135  );
136};
137
138export default memo(ChatLine);
139

EditMessage.js:

1import useChatService from "../hooks/useChatService";
2import { useEffect } from "react";
3import Chat from "./Chat";
4import NoChat from "./NoChat";
5import ChatInput from "./ChatInput";
6
7const ChatSection = () => {
8  let unsubscribe;
9  const { getChatAndUnsub, messages } = useChatService();
10
11  useEffect(() => {
12    const getChat = async () => {
13      unsubscribe = await getChatAndUnsub();
14    };
15
16    getChat();
17
18    return () => {
19      unsubscribe?.();
20    };
21  }, []);
22
23  return (
24    <div>
25      {messages.length ? <Chat messages={messages} /> : <NoChat />}
26      <p>ADD A MESSAGE</p>
27      <ChatInput />
28    </div>
29  );
30};
31
32export default ChatSection;
33import { useState } from "react";
34import ChatLine from "./ChatLine";
35import useChatService from "../hooks/useChatService";
36
37const Chat = ({ messages }) => {
38  const [editValue, setEditValue] = useState("");
39  const [editingId, setEditingId] = useState(null);
40
41  const { updateMessage, deleteMessage } = useChatService();
42
43  return (
44    <div>
45      <p>MESSAGES :</p>
46      {messages.map((line) => (
47        <ChatLine
48          key={line.id}
49          line={line}
50          editValue={line.id === editingId ? editValue : ""}
51          setEditValue={setEditValue}
52          editingId={line.id === editingId ? editingId : null}
53          setEditingId={setEditingId}
54          updateMessage={updateMessage}
55          deleteMessage={deleteMessage}
56        />
57      ))}
58    </div>
59  );
60};
61
62export default Chat;
63import { useState } from "react";
64import useChatService from "../hooks/useChatService";
65
66const ChatInput = () => {
67  const [inputValue, setInputValue] = useState("");
68  const { addMessage } = useChatService();
69
70  return (
71    <textarea
72      onKeyPress={(e) => {
73        if (e.key === "Enter") {
74          e.preventDefault();
75          addMessage(inputValue);
76          setInputValue("");
77        }
78      }}
79      placeholder="new message..."
80      onChange={(e) => {
81        setInputValue(e.target.value);
82      }}
83      value={inputValue}
84      autoFocus
85    />
86  );
87};
88
89export default ChatInput;
90import EditMessage from "./EditMessage";
91import { memo } from "react";
92
93const ChatLine = ({
94  line,
95  editValue,
96  setEditValue,
97  editingId,
98  setEditingId,
99  updateMessage,
100  deleteMessage,
101}) => {
102  return (
103    <div>
104      {editingId !== line.id ? (
105        <>
106          <span style={{ marginRight: "20px" }}>{line.id}: </span>
107          <span style={{ marginRight: "20px" }}>[{line.displayName}]</span>
108          <span style={{ marginRight: "20px" }}>{line.message}</span>
109          <button
110            onClick={() => {
111              setEditingId(line.id);
112              setEditValue(line.message);
113            }}
114          >
115            EDIT
116          </button>
117          <button
118            onClick={() => {
119              deleteMessage(line.id);
120            }}
121          >
122            DELETE
123          </button>
124        </>
125      ) : (
126        <EditMessage
127          editValue={editValue}
128          setEditValue={setEditValue}
129          setEditingId={setEditingId}
130          editingId={editingId}
131          updateMessage={updateMessage}
132        />
133      )}
134    </div>
135  );
136};
137
138export default memo(ChatLine);
139import { memo } from "react";
140
141const EditMessage = ({
142  editValue,
143  setEditValue,
144  editingId,
145  setEditingId,
146  updateMessage,
147}) => {
148  return (
149    <div>
150      <textarea
151        onKeyPress={(e) => {
152          if (e.key === "Enter") {
153            // prevent textarea default behaviour (line break on Enter)
154            e.preventDefault();
155            // updating message in DB
156            updateMessage(editValue, setEditValue, editingId, setEditingId);
157          }
158        }}
159        onChange={(e) => setEditValue(e.target.value)}
160        value={editValue}
161        autoFocus
162      />
163      <button
164        onClick={() => {
165          setEditingId(null);
166          setEditValue(null);
167        }}
168      >
169        CANCEL
170      </button>
171    </div>
172  );
173};
174
175export default memo(EditMessage);
176

useChatService.js:

1import useChatService from "../hooks/useChatService";
2import { useEffect } from "react";
3import Chat from "./Chat";
4import NoChat from "./NoChat";
5import ChatInput from "./ChatInput";
6
7const ChatSection = () => {
8  let unsubscribe;
9  const { getChatAndUnsub, messages } = useChatService();
10
11  useEffect(() => {
12    const getChat = async () => {
13      unsubscribe = await getChatAndUnsub();
14    };
15
16    getChat();
17
18    return () => {
19      unsubscribe?.();
20    };
21  }, []);
22
23  return (
24    <div>
25      {messages.length ? <Chat messages={messages} /> : <NoChat />}
26      <p>ADD A MESSAGE</p>
27      <ChatInput />
28    </div>
29  );
30};
31
32export default ChatSection;
33import { useState } from "react";
34import ChatLine from "./ChatLine";
35import useChatService from "../hooks/useChatService";
36
37const Chat = ({ messages }) => {
38  const [editValue, setEditValue] = useState("");
39  const [editingId, setEditingId] = useState(null);
40
41  const { updateMessage, deleteMessage } = useChatService();
42
43  return (
44    <div>
45      <p>MESSAGES :</p>
46      {messages.map((line) => (
47        <ChatLine
48          key={line.id}
49          line={line}
50          editValue={line.id === editingId ? editValue : ""}
51          setEditValue={setEditValue}
52          editingId={line.id === editingId ? editingId : null}
53          setEditingId={setEditingId}
54          updateMessage={updateMessage}
55          deleteMessage={deleteMessage}
56        />
57      ))}
58    </div>
59  );
60};
61
62export default Chat;
63import { useState } from "react";
64import useChatService from "../hooks/useChatService";
65
66const ChatInput = () => {
67  const [inputValue, setInputValue] = useState("");
68  const { addMessage } = useChatService();
69
70  return (
71    <textarea
72      onKeyPress={(e) => {
73        if (e.key === "Enter") {
74          e.preventDefault();
75          addMessage(inputValue);
76          setInputValue("");
77        }
78      }}
79      placeholder="new message..."
80      onChange={(e) => {
81        setInputValue(e.target.value);
82      }}
83      value={inputValue}
84      autoFocus
85    />
86  );
87};
88
89export default ChatInput;
90import EditMessage from "./EditMessage";
91import { memo } from "react";
92
93const ChatLine = ({
94  line,
95  editValue,
96  setEditValue,
97  editingId,
98  setEditingId,
99  updateMessage,
100  deleteMessage,
101}) => {
102  return (
103    <div>
104      {editingId !== line.id ? (
105        <>
106          <span style={{ marginRight: "20px" }}>{line.id}: </span>
107          <span style={{ marginRight: "20px" }}>[{line.displayName}]</span>
108          <span style={{ marginRight: "20px" }}>{line.message}</span>
109          <button
110            onClick={() => {
111              setEditingId(line.id);
112              setEditValue(line.message);
113            }}
114          >
115            EDIT
116          </button>
117          <button
118            onClick={() => {
119              deleteMessage(line.id);
120            }}
121          >
122            DELETE
123          </button>
124        </>
125      ) : (
126        <EditMessage
127          editValue={editValue}
128          setEditValue={setEditValue}
129          setEditingId={setEditingId}
130          editingId={editingId}
131          updateMessage={updateMessage}
132        />
133      )}
134    </div>
135  );
136};
137
138export default memo(ChatLine);
139import { memo } from "react";
140
141const EditMessage = ({
142  editValue,
143  setEditValue,
144  editingId,
145  setEditingId,
146  updateMessage,
147}) => {
148  return (
149    <div>
150      <textarea
151        onKeyPress={(e) => {
152          if (e.key === "Enter") {
153            // prevent textarea default behaviour (line break on Enter)
154            e.preventDefault();
155            // updating message in DB
156            updateMessage(editValue, setEditValue, editingId, setEditingId);
157          }
158        }}
159        onChange={(e) => setEditValue(e.target.value)}
160        value={editValue}
161        autoFocus
162      />
163      <button
164        onClick={() => {
165          setEditingId(null);
166          setEditValue(null);
167        }}
168      >
169        CANCEL
170      </button>
171    </div>
172  );
173};
174
175export default memo(EditMessage);
176import { useCallback, useState } from "react";
177import {
178  collection,
179  onSnapshot,
180  orderBy,
181  query,
182  serverTimestamp,
183  updateDoc,
184  doc,
185  addDoc,
186  deleteDoc,
187} from "firebase/firestore";
188import { db } from "../firebase/firebase-config";
189
190const useChatService = () => {
191  const [messages, setMessages] = useState([]);
192
193  /**
194   * Get Messages
195   *
196   * @returns {Promise<Unsubscribe>}
197   */
198  const getChatAndUnsub = async () => {
199    const q = query(collection(db, "messages"), orderBy("createdAt"));
200
201    const unsubscribe = onSnapshot(q, (snapshot) => {
202      const data = snapshot.docs.map((doc, index) => {
203        const entry = doc.data();
204
205        return {
206          id: doc.id,
207          message: entry.message,
208          createdAt: entry.createdAt,
209          updatedAt: entry.updatedAt,
210          uid: entry.uid,
211          displayName: entry.displayName,
212          photoURL: entry.photoURL,
213        };
214      });
215
216      setMessages(data);
217    });
218
219    return unsubscribe;
220  };
221
222  /**
223   * Memoized using useCallback
224   */
225  const updateMessage = useCallback(
226    async (editValue, setEditValue, editingId, setEditingId) => {
227      const message = editValue;
228      const id = editingId;
229
230      // resetting state as soon as we press Enter
231      setEditValue("");
232      setEditingId(null);
233
234      try {
235        await updateDoc(doc(db, "messages", id), {
236          message,
237          updatedAt: serverTimestamp(),
238        });
239      } catch (err) {
240        console.log(err);
241      }
242    },
243    []
244  );
245
246  const addMessage = async (inputValue) => {
247    if (!inputValue) {
248      return;
249    }
250    const message = inputValue;
251
252    const messageData = {
253      // hardcoded photoURL, uid, and displayName for demo purposes
254      photoURL:
255        "https://lh3.googleusercontent.com/a/AATXAJwNw_ECd4OhqV0bwAb7l4UqtPYeSrRMpVB7ayxY=s96-c",
256      uid: keyGen(),
257      message,
258      displayName: "John Doe",
259      createdAt: serverTimestamp(),
260      updatedAt: null,
261    };
262
263    try {
264      await addDoc(collection(db, "messages"), messageData);
265    } catch (e) {
266      console.log(e);
267    }
268  };
269
270  /**
271   * Memoized using useCallback
272   */
273  const deleteMessage = useCallback(async (idToDelete) => {
274    if (!idToDelete) {
275      return;
276    }
277    try {
278      await deleteDoc(doc(db, "messages", idToDelete));
279    } catch (err) {
280      console.log(err);
281    }
282  }, []);
283
284  const keyGen = () => {
285    const s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
286    return Array(20)
287      .join()
288      .split(",")
289      .map(function () {
290        return s.charAt(Math.floor(Math.random() * s.length));
291      })
292      .join("");
293  };
294
295  return {
296    messages,
297    getChatAndUnsub,
298    updateMessage,
299    addMessage,
300    deleteMessage,
301  };
302};
303
304export default useChatService;
305

When a message gets updated using updateMessage method, I only need the affected ChatLine to rerender (same for add & delete), not every single ChatLine in the list, while keeping the messages state passed from ChatSection to Chat, I understand that ChatSection & Chat should rerender, but not every ChatLine in the list. (Also ChatLine is memoized)

EDIT 1: I guess the problem is with setMessages(data) in useChatService.js, but I thought React will only rerender the edited line because I already provided the key={line.id} when looping through messages in Chat component, but I have no idea how to fix this.

ANSWER

Answered 2021-Dec-13 at 23:35

This is what I think, You are passing Messages in ChatSection and that means that when Messages get updated ChatSection will rerender and all its children will rerender too.

So here is my idea remove Messages from ChatSection and only add it in Chat.

You already using useChatService in Chat so adding Messages there should be better.

Try this and gets back too us if it working.

If still not as you like it to be there is also other way we could fix it.

But you have to create a working example for us so we could have a look and make small changes.

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

QUESTION

Google Play App Rejection - Not a core feature - Use of All files access

Asked 2021-Nov-26 at 12:40

I have an application on play store to whom the targetSdkVersion is update to 30 from 29, which is getting rejected again and again by Google Play after an update.

Previously, there was a permission of MANAGE_EXTERNAL_STORAGE in one of the SDK Manifest.

After removing MANAGE_EXTERNAL_STORAGE permission and storage permission (WRITE_EXTERNAL_STORAGE) completely from my app, uploading the app on store, app update gets rejected again.

This is the email received from Google Play for the rejection reason.

Note: I am saving all my media files in app-specific internal storage.

Also, I have the permission of READ_EXTERNAL_STORAGE in my SDK as we have chat feature in our app to get images and videos of device to sent it.

According to Use of All files access (MANAGE_EXTERNAL_STORAGE) permission READ_EXTERNAL_STORAGE permission has not impact.

Attached reference.

Update

I also removed READ_EXTERNAL_STORAGE permission from the app, but still got the rejection with same reason from Google Play.

Is the issue with Storage Policy, or something else?

ANSWER

Answered 2021-Nov-25 at 13:10

I had the same error for a month but finally, Google Play Store accepted my uploads.

Briefly, what I did was to create new builds for each track, and -interestingly- it worked!

(Before my countless update trials, our latest version on Production was 2.23.5 (build 1), our active tracks were Internal Testing Track and Production, and I was trying to upload my updates to Internal Testing Track.)

Below are the steps that I've applied:

  1. Created a new build 2.24.1 (build 1) with all necessary changes. (e.g. upgrading targetSdkVersion to 30, removing MANAGE_EXTERNAL_STORAGE permission, etc.)
  2. Activated our inactive tracks (Open, Closed Alpha, and Beta Testing Tracks), uploaded the same build 2.24.1 (build 1) to these tracks, and then paused those tracks. (I've paused them as I won't use them actively, you may not want to pause it)
  3. Created another build 2.24.1 (build 2) which was completely the same as build 1. I've just updated its build number.
  4. Uploaded 2.24.1 (build 2) to the Internal Testing Track.
  5. Created another build 2.24.1 (build 3) which was completely the same as build 3. I've just updated its build number.
  6. Uploaded 2.24.1 (build 3) to the Production Track.
  7. Went to "Publishing Overview" page, activated Managed Publishing in order to manually publish my uploads to Production and other tracks as they got accepted.
  8. Sent these uploads to review at once and voila, Google accepts your uploads!

Sarcasm on.

Hereby, I would like to congratulate Google Play Support as they've shared all these details within their documentation, within their rejection e-mails, and within their super fast response to the appeal.

Sarcasm off.

I've found this solution referencing from this answer https://stackoverflow.com/a/69933431/2833718. I couldn't find any help from Google's official docs. They've always rejected my uploads with the same e-mail which is impossible to decode for a human being. They've never returned to my appeal.

This migration and support process was completely a failure.

Thank you Google Play Support, you are everything but support to developers.

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

QUESTION

How to add count values in venn diagram for more than 6 sets?

Asked 2021-Nov-04 at 00:43

I used following code to generate the sets for more than 5 groups:

1library(venneuler)
2
3H=list('ASD'=c("SCN3A", "TSC2", "RASSF8", "XDH", "CNTN5", "CHD7", "DPYD", "BUB1", "DPP4", "AMPD1", "ARID4A", "QSER1", "OCA2", "GPR141", "DNAH9", "LOXHD1", "SETX", "GSTP1", "SLC6A15", "ASTN1", "CACNA1D", "WFS1", "KCNC1", "TPRA1", "NBAS", "LAMB1", "TSNARE1", "GABRB3", "PAG1", "SOS1", "LHFPL4", "KMT2C", "GATM", "NPTX2", "ANK3", "SH3TC2", "CLPP", "TP53BP1", "EBF4", "ANO1", "DNAJC10", "TTC25", "NDUFB7", "PCSK1", "ROBO3", "MYO9A", "RPS23", "ZNF292", "CRBN", "HIVEP2", "CYP1B1", "KCNE2", "NRP2", "ADSL", "XIRP2", "SMARCA4", "HDAC2", "JAK2", "ATP9B", "ESR1", "MDN1", "CTNNA2", "CNTNAP2", "SPTB", "ACY1", "CEP290", "WNT2", "IQGAP3", "CACNG3", "CACNA1H", "FOXN1", "SPAST", "ADCY1", "IGF2", "RNF4", "CTTNBP2", "TMF1", "CPT1A", "TENM3", "RABGGTA", "MBD3", "CCDC18", "SMG1", "SYNE1", "PITX3", "HMGA2", "PDE6C", "CTU2", "PNPLA7", "PIEZO1", "MAP2", "MCF2L", "PRF1", "VWA8", "LRP2", "RYR3", "IPO9", "DIXDC1", "CNTNAP5", "ELP4", "LRRN1", "TRIO", "SACS", "ASIC2", "KIF1B", "AXIN2", "SORL1", "DLG2", "VPS13C", "F2RL1", "NRP1", "LAMA1", "LARP1", "SDK1", "LAMC2", "LSG1", "EP300", "DGCR6L", "TSHB", "APC", "TENM4", "IGSF21"),
4             'Epilepsy'=c("ADCY1", "ADSL", "ANK3", "APC", "ASIC2", "ASTN1", "ATP9B", "AXIN2", "BUB1", "CACNA1D", "CACNA1H", "CACNG3", "CEP290", "CLPP", "CNTN5", "CNTNAP2", "CNTNAP5", "CTNNA2", "CTU2", "DGCR6L", "DLG2", "DNAJC10", "ELP4", "EP300", "GABRB3", "HDAC2", "HMGA2", "IGSF21", "IPO9", "IQGAP3", "JAK2", "KCNC1", "KCNE2", "KIF1B", "LAMB1", "LAMC2", "LARP1", "LHFPL4", "MCF2L", "MYO9A", "NDUFB7", "NRP2", "RABGGTA", "RYR3", "SACS", "SCN3A", "SETX", "SMARCA4", "SMG1", "SORL1", "SPAST", "SPTB", "TMF1", "TP53BP1", "TPRA1", "TRIO", "TSC2", "TSHB", "VPS13C", "WFS1", "XDH", "ZNF292", "ABCA1", "ABCG5", "ACP2", "ADCY6", "ADGRA3", "ADGRV1", "AGA", "AGRN", "ALG3", "ANK2", "ANKRD44", "AP5Z1", "ARAP1", "ARHGEF11", "ASCC3", "ASPM", "ATRN", "AURKB", "BRINP2", "BRSK2", "CAPN15", "CAPN2", "CC2D2A", "CD36", "CDX1", "CHAT", "CHM", "CHTF18", "CLCN2", "CLCN7", "CLEC12A", "COG5", "COG6", "COL12A1", "COL17A1", "COL28A1", "COL6A2", "COQ3", "CYBB", "DBNL", "DBR1", "DEAF1", "DGKQ", "DHX29", "DMXL1", "DMXL2", "DNAH12", "DOCK7", "DOLK", "DSG4", "DZIP1", "EFHC1", "EPHA7", "EPHB1", "EPHB3", "ESYT1", "EXOC7", "F13A1", "F5", "FAH", "FARP1", "FASN", "FAT1", "FERMT1", "FGFR3", "FLNB", "FLRT1", "FMNL1", "FN1", "FOLR1", "FZD4", "GAA", "GAK", "GALC", "GANAB", "GLB1", "GM2A", "GNA14", "GOSR2", "GPC1", "GSS", "GTPBP4", "HEATR1", "HGS", "HIPK2", "HSPA13", "HTR2B", "INO80E", "KALRN", "KCNH2", "KCNJ16", "KIAA0586", "KRIT1", "LAMB2", "LMAN1", "LTBP3", "MASTL", "MED17", "METTL25", "MGAT5B", "MPL", "MRPL24", "MRPS27", "MSX2", "MUS81", "NALCN", "NEB", "NFE2L1", "NMBR", "NOL11", "NUCB1", "OBSL1", "OGDHL", "OGFOD2", "PARP1", "PCCB", "PDGFRA", "PDYN", "PFAS", "PFKFB3", "PLEC", "PLOD2", "PNKD", "PNPO", "POLD1", "POLE", "POLL", "PPAT", "PRDX3", "PSEN2", "PTCH1", "PTK2B", "RAB5A", "RAD54B", "RELB", "RHOT2", "RIMS2", "RTN4IP1", "SAE1", "SCAPER", "SCN1B", "SCN5A", "SEC23IP", "SERPINE2", "SGCB", "SIGLEC1", "SLC18A3", "SLC26A4", "SLC2A1", "SLC4A1", "SLC4A3", "SLITRK6", "SPG11", "STARD13", "STT3A", "SYF2", "SYNJ1", "SZT2", "TECPR2", "TES", "TMEM67", "TNK2", "TNS1", "TNS3", "TRAP1", "TRAPPC11", "TRAPPC8", "TRIP10", "TRPM2", "TRPM3", "TRPV1", "TUBGCP6", "TYW1", "UNC13B", "USP45", "VCP", "WDR62", "WWOX", "YAP1", "ZBTB48", "ZFHX4", "ZW10"),
5             'Intellectual'=c("YAP1", "TSC2", "FMNL1", "MADD", "KRIT1", "TNK2", "NUP155", "COG6", "TRAPPC8", "IPO9", "CCT8", "ZFYVE16", "FAT1", "SLC37A1", "KAT6B", "WWOX", "PTK2B", "CNTNAP5", "HEATR1", "TRAPPC11", "ARID4A", "ADGRV1", "GPC1", "AURKB", "TTC39B", "GSS", "GANAB", "RFWD3", "CUL9", "SAE1", "CACNG3", "SMC4", "ASIC2", "SYF2", "PFAS", "GAK", "METTL25", "OGDHL", "RAB5A", "VPS13C", "FGFR3", "KCNC1", "DDOST", "CTNND1", "ATRN", "UNC13B", "FASN", "MYO18A", "TMF1", "CRBN", "FLNB", "LARP1", "RCC2", "MASTL", "ADGRA3", "SCAPER", "SZT2", "LRP4", "SMG1", "SYNE1", "ADCY6", "RNGTT", "EP300", "ARAP1", "ANKRD44", "VPS39", "DGCR6L", "STT3A", "COG5", "NFE2L1", "SLC7A2", "ASCC3", "LMAN1", "OBSL1", "KIF20B", "PNPLA7"),
6             'Schizophrenia'=c("CRB1", "FBXW4", "CNTN5", "CHM", "DPYD", "BUB1", "DPP4", "ADGRV1", "GPC1", "DLD", "RBM19", "ITIH1", "ADCY7", "KCNC1", "ACBD5", "ELF1", "TSNARE1", "GABRB3", "TMEM182", "STT3A", "KMT2C", "ANK3", "SAMD4A", "NALCN", "PDLIM5", "LIMA1", "DYNC1I2", "TMEM26", "ANK2", "GRIN3A", "EPHB1", "BRINP2", "KALRN", "MICAL2", "TTLL6", "ZNF292", "SERPINB1", "SCAPER", "KCNS3", "VAMP1", "HDAC2", "DLG1", "CFAP58", "JAK2", "ESR1", "EFCAB14", "CNTNAP2", "PENK", "WWOX", "GLT8D1", "SFMBT2", "EEFSEC", "PDZD8", "GALC", "CACNG3", "SPG7", "ADCY1", "CLDN10", "TENM3", "OTOS", "CAPN2", "LRP4", "SYNE1", "HMGA2", "APOL4", "ARAP1", "DOPEY1", "EPN2", "MCF2L", "PLAA", "RYR3", "CNTNAP5", "POLE", "TRIO", "RAB11FIP5", "BNIP3L", "RUNX1", "AXIN2", "KIF1B", "DLG2", "MAP3K9", "CERCAM", "VPS13C", "MYO18B", "NRP1", "IRS1", "MANEA", "EP300", "DGCR6L", "TSHB", "AASDHPPT", "TRAPPC3", "APC", "TENM4"),
7             'ADHD'=c("TSC2", "CSMD2", "ANK3", "ASPM", "CNTN5", "TP53BP1", "CNTNAP2", "CHD7", "GLT8D1", "CNTNAP5", "SFMBT2", "MLH1", "FLII", "PTCH1", "SPRED1", "ARHGEF12", "CHMP7", "SVEP1", "CREB5", "MSH6", "TTLL8", "DLG2", "MICAL2", "DNAH3", "ADGRA3", "ACBD5", "SYNE1", "NUCB1", "NRP2", "TMEM182", "STT3A", "GNE", "PAX5", "TENM4"),
8             'Biopolar Disoder'=c("CSMD2", "ANK3", "NUMB", "CNTN5", "CTNNA2", "CNTNAP2", "NALCN", "RDH14", "WWOX", "GLT8D1", "SFMBT2", "SPRED1", "ADAMTS14", "TTC39B", "SVEP1", "COL28A1", "PDZD8", "GALC", "SORL1", "ITIH1", "CLSPN", "SLCO4A1", "VPS13C", "MYO18B", "TTLL6", "CRBN", "NFATC2", "SYNE1", "INTS7", "TMEM182", "STT3A", "WSCD1", "KCNS3", "PDGFRA"),
9             'circadian'=c("YTHDC2", "LRP1B", "SAMD4A", "VTA1", "NALCN", "F13A1", "SLC4A1", "TMEM26", "ADAMTS14", "COL28A1", "RNF19A", "BRINP2", "TRHR", "CCBE1", "CACNA2D3", "MYO18A", "SLC26A7", "FRAS1", "EP300", "GNE", "LMAN1", "NMBR", "TGFBI", "CHAT", "HIPK2", "SERPINE2", "RELB", "ARHGEF12", "SETX", "CACNA1D", "ADCY7", "NBAS", "GPR83", "LTBP3", "GABRB3", "HMBS", "PSMA4", "MADD", "SIX3", "EPHB1", "GAK", "SPRY4", "ABCA13", "SLC8A3", "HIVEP2", "FAH", "ADCY6", "MYLIP", "NFE2L1", "PRKAG1", "HDAC2", "TNS1", "GSS", "CACNA1H", "POLL", "CPT1A", "CAPN2", "PITX3", "NFE2L3", "PNPLA7", "AGA", "STX16", "TNK2", "PRF1", "RYR3", "DIXDC1", "PSEN2", "SREBF1", "POLE", "RAB11FIP5", "KIF1B", "RAB5A", "NGB", "ARHGEF11", "SIX6", "SDK1", "AATK", "CYP7A1", "CUL9"),
10             'dementia'=c("LMAN1", "PRDX3", "NPLOC4", "PSEN2", "ZFYVE16", "CHAT", "PENK", "LTBP1", "SNCAIP", "NOL11", "GANAB", "DLD", "SPG11", "IGSF21", "RNF19A", "ASIC2", "ASTN1", "SORL1", "SPRY4", "VCP", "TATDN1", "RAB5A", "VPS13C", "GM2A", "IRS1", "PSMB4", "NGB", "F2RL1", "RAB38", "SMOX", "PARP1", "ABCC9", "RPN2", "CAPN2", "GALNT7", "SMG1", "TBK1", "MASP2", "GNE", "GTPBP4", "CCT8", "CD63", "PSMA4", "TUBA4A", "CUL9")
11            )
12    
13Hmat <- lapply(seq_along(H), \(i) {
14Set <- names(H)[i]
15data.frame(Element = H[[i]], Set)
16    })
17Hmat <- do.call(rbind, Hmat)
18vd <- venneuler(Hmat)
19plot(vd)
20

and got the output as: Venn

How do I add the count (number) inside the each circle?

ANSWER

Answered 2021-Nov-04 at 00:43

Change vd's label manually will help.

1library(venneuler)
2
3H=list('ASD'=c("SCN3A", "TSC2", "RASSF8", "XDH", "CNTN5", "CHD7", "DPYD", "BUB1", "DPP4", "AMPD1", "ARID4A", "QSER1", "OCA2", "GPR141", "DNAH9", "LOXHD1", "SETX", "GSTP1", "SLC6A15", "ASTN1", "CACNA1D", "WFS1", "KCNC1", "TPRA1", "NBAS", "LAMB1", "TSNARE1", "GABRB3", "PAG1", "SOS1", "LHFPL4", "KMT2C", "GATM", "NPTX2", "ANK3", "SH3TC2", "CLPP", "TP53BP1", "EBF4", "ANO1", "DNAJC10", "TTC25", "NDUFB7", "PCSK1", "ROBO3", "MYO9A", "RPS23", "ZNF292", "CRBN", "HIVEP2", "CYP1B1", "KCNE2", "NRP2", "ADSL", "XIRP2", "SMARCA4", "HDAC2", "JAK2", "ATP9B", "ESR1", "MDN1", "CTNNA2", "CNTNAP2", "SPTB", "ACY1", "CEP290", "WNT2", "IQGAP3", "CACNG3", "CACNA1H", "FOXN1", "SPAST", "ADCY1", "IGF2", "RNF4", "CTTNBP2", "TMF1", "CPT1A", "TENM3", "RABGGTA", "MBD3", "CCDC18", "SMG1", "SYNE1", "PITX3", "HMGA2", "PDE6C", "CTU2", "PNPLA7", "PIEZO1", "MAP2", "MCF2L", "PRF1", "VWA8", "LRP2", "RYR3", "IPO9", "DIXDC1", "CNTNAP5", "ELP4", "LRRN1", "TRIO", "SACS", "ASIC2", "KIF1B", "AXIN2", "SORL1", "DLG2", "VPS13C", "F2RL1", "NRP1", "LAMA1", "LARP1", "SDK1", "LAMC2", "LSG1", "EP300", "DGCR6L", "TSHB", "APC", "TENM4", "IGSF21"),
4             'Epilepsy'=c("ADCY1", "ADSL", "ANK3", "APC", "ASIC2", "ASTN1", "ATP9B", "AXIN2", "BUB1", "CACNA1D", "CACNA1H", "CACNG3", "CEP290", "CLPP", "CNTN5", "CNTNAP2", "CNTNAP5", "CTNNA2", "CTU2", "DGCR6L", "DLG2", "DNAJC10", "ELP4", "EP300", "GABRB3", "HDAC2", "HMGA2", "IGSF21", "IPO9", "IQGAP3", "JAK2", "KCNC1", "KCNE2", "KIF1B", "LAMB1", "LAMC2", "LARP1", "LHFPL4", "MCF2L", "MYO9A", "NDUFB7", "NRP2", "RABGGTA", "RYR3", "SACS", "SCN3A", "SETX", "SMARCA4", "SMG1", "SORL1", "SPAST", "SPTB", "TMF1", "TP53BP1", "TPRA1", "TRIO", "TSC2", "TSHB", "VPS13C", "WFS1", "XDH", "ZNF292", "ABCA1", "ABCG5", "ACP2", "ADCY6", "ADGRA3", "ADGRV1", "AGA", "AGRN", "ALG3", "ANK2", "ANKRD44", "AP5Z1", "ARAP1", "ARHGEF11", "ASCC3", "ASPM", "ATRN", "AURKB", "BRINP2", "BRSK2", "CAPN15", "CAPN2", "CC2D2A", "CD36", "CDX1", "CHAT", "CHM", "CHTF18", "CLCN2", "CLCN7", "CLEC12A", "COG5", "COG6", "COL12A1", "COL17A1", "COL28A1", "COL6A2", "COQ3", "CYBB", "DBNL", "DBR1", "DEAF1", "DGKQ", "DHX29", "DMXL1", "DMXL2", "DNAH12", "DOCK7", "DOLK", "DSG4", "DZIP1", "EFHC1", "EPHA7", "EPHB1", "EPHB3", "ESYT1", "EXOC7", "F13A1", "F5", "FAH", "FARP1", "FASN", "FAT1", "FERMT1", "FGFR3", "FLNB", "FLRT1", "FMNL1", "FN1", "FOLR1", "FZD4", "GAA", "GAK", "GALC", "GANAB", "GLB1", "GM2A", "GNA14", "GOSR2", "GPC1", "GSS", "GTPBP4", "HEATR1", "HGS", "HIPK2", "HSPA13", "HTR2B", "INO80E", "KALRN", "KCNH2", "KCNJ16", "KIAA0586", "KRIT1", "LAMB2", "LMAN1", "LTBP3", "MASTL", "MED17", "METTL25", "MGAT5B", "MPL", "MRPL24", "MRPS27", "MSX2", "MUS81", "NALCN", "NEB", "NFE2L1", "NMBR", "NOL11", "NUCB1", "OBSL1", "OGDHL", "OGFOD2", "PARP1", "PCCB", "PDGFRA", "PDYN", "PFAS", "PFKFB3", "PLEC", "PLOD2", "PNKD", "PNPO", "POLD1", "POLE", "POLL", "PPAT", "PRDX3", "PSEN2", "PTCH1", "PTK2B", "RAB5A", "RAD54B", "RELB", "RHOT2", "RIMS2", "RTN4IP1", "SAE1", "SCAPER", "SCN1B", "SCN5A", "SEC23IP", "SERPINE2", "SGCB", "SIGLEC1", "SLC18A3", "SLC26A4", "SLC2A1", "SLC4A1", "SLC4A3", "SLITRK6", "SPG11", "STARD13", "STT3A", "SYF2", "SYNJ1", "SZT2", "TECPR2", "TES", "TMEM67", "TNK2", "TNS1", "TNS3", "TRAP1", "TRAPPC11", "TRAPPC8", "TRIP10", "TRPM2", "TRPM3", "TRPV1", "TUBGCP6", "TYW1", "UNC13B", "USP45", "VCP", "WDR62", "WWOX", "YAP1", "ZBTB48", "ZFHX4", "ZW10"),
5             'Intellectual'=c("YAP1", "TSC2", "FMNL1", "MADD", "KRIT1", "TNK2", "NUP155", "COG6", "TRAPPC8", "IPO9", "CCT8", "ZFYVE16", "FAT1", "SLC37A1", "KAT6B", "WWOX", "PTK2B", "CNTNAP5", "HEATR1", "TRAPPC11", "ARID4A", "ADGRV1", "GPC1", "AURKB", "TTC39B", "GSS", "GANAB", "RFWD3", "CUL9", "SAE1", "CACNG3", "SMC4", "ASIC2", "SYF2", "PFAS", "GAK", "METTL25", "OGDHL", "RAB5A", "VPS13C", "FGFR3", "KCNC1", "DDOST", "CTNND1", "ATRN", "UNC13B", "FASN", "MYO18A", "TMF1", "CRBN", "FLNB", "LARP1", "RCC2", "MASTL", "ADGRA3", "SCAPER", "SZT2", "LRP4", "SMG1", "SYNE1", "ADCY6", "RNGTT", "EP300", "ARAP1", "ANKRD44", "VPS39", "DGCR6L", "STT3A", "COG5", "NFE2L1", "SLC7A2", "ASCC3", "LMAN1", "OBSL1", "KIF20B", "PNPLA7"),
6             'Schizophrenia'=c("CRB1", "FBXW4", "CNTN5", "CHM", "DPYD", "BUB1", "DPP4", "ADGRV1", "GPC1", "DLD", "RBM19", "ITIH1", "ADCY7", "KCNC1", "ACBD5", "ELF1", "TSNARE1", "GABRB3", "TMEM182", "STT3A", "KMT2C", "ANK3", "SAMD4A", "NALCN", "PDLIM5", "LIMA1", "DYNC1I2", "TMEM26", "ANK2", "GRIN3A", "EPHB1", "BRINP2", "KALRN", "MICAL2", "TTLL6", "ZNF292", "SERPINB1", "SCAPER", "KCNS3", "VAMP1", "HDAC2", "DLG1", "CFAP58", "JAK2", "ESR1", "EFCAB14", "CNTNAP2", "PENK", "WWOX", "GLT8D1", "SFMBT2", "EEFSEC", "PDZD8", "GALC", "CACNG3", "SPG7", "ADCY1", "CLDN10", "TENM3", "OTOS", "CAPN2", "LRP4", "SYNE1", "HMGA2", "APOL4", "ARAP1", "DOPEY1", "EPN2", "MCF2L", "PLAA", "RYR3", "CNTNAP5", "POLE", "TRIO", "RAB11FIP5", "BNIP3L", "RUNX1", "AXIN2", "KIF1B", "DLG2", "MAP3K9", "CERCAM", "VPS13C", "MYO18B", "NRP1", "IRS1", "MANEA", "EP300", "DGCR6L", "TSHB", "AASDHPPT", "TRAPPC3", "APC", "TENM4"),
7             'ADHD'=c("TSC2", "CSMD2", "ANK3", "ASPM", "CNTN5", "TP53BP1", "CNTNAP2", "CHD7", "GLT8D1", "CNTNAP5", "SFMBT2", "MLH1", "FLII", "PTCH1", "SPRED1", "ARHGEF12", "CHMP7", "SVEP1", "CREB5", "MSH6", "TTLL8", "DLG2", "MICAL2", "DNAH3", "ADGRA3", "ACBD5", "SYNE1", "NUCB1", "NRP2", "TMEM182", "STT3A", "GNE", "PAX5", "TENM4"),
8             'Biopolar Disoder'=c("CSMD2", "ANK3", "NUMB", "CNTN5", "CTNNA2", "CNTNAP2", "NALCN", "RDH14", "WWOX", "GLT8D1", "SFMBT2", "SPRED1", "ADAMTS14", "TTC39B", "SVEP1", "COL28A1", "PDZD8", "GALC", "SORL1", "ITIH1", "CLSPN", "SLCO4A1", "VPS13C", "MYO18B", "TTLL6", "CRBN", "NFATC2", "SYNE1", "INTS7", "TMEM182", "STT3A", "WSCD1", "KCNS3", "PDGFRA"),
9             'circadian'=c("YTHDC2", "LRP1B", "SAMD4A", "VTA1", "NALCN", "F13A1", "SLC4A1", "TMEM26", "ADAMTS14", "COL28A1", "RNF19A", "BRINP2", "TRHR", "CCBE1", "CACNA2D3", "MYO18A", "SLC26A7", "FRAS1", "EP300", "GNE", "LMAN1", "NMBR", "TGFBI", "CHAT", "HIPK2", "SERPINE2", "RELB", "ARHGEF12", "SETX", "CACNA1D", "ADCY7", "NBAS", "GPR83", "LTBP3", "GABRB3", "HMBS", "PSMA4", "MADD", "SIX3", "EPHB1", "GAK", "SPRY4", "ABCA13", "SLC8A3", "HIVEP2", "FAH", "ADCY6", "MYLIP", "NFE2L1", "PRKAG1", "HDAC2", "TNS1", "GSS", "CACNA1H", "POLL", "CPT1A", "CAPN2", "PITX3", "NFE2L3", "PNPLA7", "AGA", "STX16", "TNK2", "PRF1", "RYR3", "DIXDC1", "PSEN2", "SREBF1", "POLE", "RAB11FIP5", "KIF1B", "RAB5A", "NGB", "ARHGEF11", "SIX6", "SDK1", "AATK", "CYP7A1", "CUL9"),
10             'dementia'=c("LMAN1", "PRDX3", "NPLOC4", "PSEN2", "ZFYVE16", "CHAT", "PENK", "LTBP1", "SNCAIP", "NOL11", "GANAB", "DLD", "SPG11", "IGSF21", "RNF19A", "ASIC2", "ASTN1", "SORL1", "SPRY4", "VCP", "TATDN1", "RAB5A", "VPS13C", "GM2A", "IRS1", "PSMB4", "NGB", "F2RL1", "RAB38", "SMOX", "PARP1", "ABCC9", "RPN2", "CAPN2", "GALNT7", "SMG1", "TBK1", "MASP2", "GNE", "GTPBP4", "CCT8", "CD63", "PSMA4", "TUBA4A", "CUL9")
11            )
12    
13Hmat <- lapply(seq_along(H), \(i) {
14Set <- names(H)[i]
15data.frame(Element = H[[i]], Set)
16    })
17Hmat <- do.call(rbind, Hmat)
18vd <- venneuler(Hmat)
19plot(vd)
20HH <- Hmat %>%
21  group_by(Set) %>%
22  summarise(n = n()) %>%
23  .[match(vd$labels, .$Set),] %>%
24  mutate(n = paste(Set, "\n", n))
25vd$labels <- HH$n
26plot(vd)
27

enter image description here

Using eulerr::euler function,

1library(venneuler)
2
3H=list('ASD'=c("SCN3A", "TSC2", "RASSF8", "XDH", "CNTN5", "CHD7", "DPYD", "BUB1", "DPP4", "AMPD1", "ARID4A", "QSER1", "OCA2", "GPR141", "DNAH9", "LOXHD1", "SETX", "GSTP1", "SLC6A15", "ASTN1", "CACNA1D", "WFS1", "KCNC1", "TPRA1", "NBAS", "LAMB1", "TSNARE1", "GABRB3", "PAG1", "SOS1", "LHFPL4", "KMT2C", "GATM", "NPTX2", "ANK3", "SH3TC2", "CLPP", "TP53BP1", "EBF4", "ANO1", "DNAJC10", "TTC25", "NDUFB7", "PCSK1", "ROBO3", "MYO9A", "RPS23", "ZNF292", "CRBN", "HIVEP2", "CYP1B1", "KCNE2", "NRP2", "ADSL", "XIRP2", "SMARCA4", "HDAC2", "JAK2", "ATP9B", "ESR1", "MDN1", "CTNNA2", "CNTNAP2", "SPTB", "ACY1", "CEP290", "WNT2", "IQGAP3", "CACNG3", "CACNA1H", "FOXN1", "SPAST", "ADCY1", "IGF2", "RNF4", "CTTNBP2", "TMF1", "CPT1A", "TENM3", "RABGGTA", "MBD3", "CCDC18", "SMG1", "SYNE1", "PITX3", "HMGA2", "PDE6C", "CTU2", "PNPLA7", "PIEZO1", "MAP2", "MCF2L", "PRF1", "VWA8", "LRP2", "RYR3", "IPO9", "DIXDC1", "CNTNAP5", "ELP4", "LRRN1", "TRIO", "SACS", "ASIC2", "KIF1B", "AXIN2", "SORL1", "DLG2", "VPS13C", "F2RL1", "NRP1", "LAMA1", "LARP1", "SDK1", "LAMC2", "LSG1", "EP300", "DGCR6L", "TSHB", "APC", "TENM4", "IGSF21"),
4             'Epilepsy'=c("ADCY1", "ADSL", "ANK3", "APC", "ASIC2", "ASTN1", "ATP9B", "AXIN2", "BUB1", "CACNA1D", "CACNA1H", "CACNG3", "CEP290", "CLPP", "CNTN5", "CNTNAP2", "CNTNAP5", "CTNNA2", "CTU2", "DGCR6L", "DLG2", "DNAJC10", "ELP4", "EP300", "GABRB3", "HDAC2", "HMGA2", "IGSF21", "IPO9", "IQGAP3", "JAK2", "KCNC1", "KCNE2", "KIF1B", "LAMB1", "LAMC2", "LARP1", "LHFPL4", "MCF2L", "MYO9A", "NDUFB7", "NRP2", "RABGGTA", "RYR3", "SACS", "SCN3A", "SETX", "SMARCA4", "SMG1", "SORL1", "SPAST", "SPTB", "TMF1", "TP53BP1", "TPRA1", "TRIO", "TSC2", "TSHB", "VPS13C", "WFS1", "XDH", "ZNF292", "ABCA1", "ABCG5", "ACP2", "ADCY6", "ADGRA3", "ADGRV1", "AGA", "AGRN", "ALG3", "ANK2", "ANKRD44", "AP5Z1", "ARAP1", "ARHGEF11", "ASCC3", "ASPM", "ATRN", "AURKB", "BRINP2", "BRSK2", "CAPN15", "CAPN2", "CC2D2A", "CD36", "CDX1", "CHAT", "CHM", "CHTF18", "CLCN2", "CLCN7", "CLEC12A", "COG5", "COG6", "COL12A1", "COL17A1", "COL28A1", "COL6A2", "COQ3", "CYBB", "DBNL", "DBR1", "DEAF1", "DGKQ", "DHX29", "DMXL1", "DMXL2", "DNAH12", "DOCK7", "DOLK", "DSG4", "DZIP1", "EFHC1", "EPHA7", "EPHB1", "EPHB3", "ESYT1", "EXOC7", "F13A1", "F5", "FAH", "FARP1", "FASN", "FAT1", "FERMT1", "FGFR3", "FLNB", "FLRT1", "FMNL1", "FN1", "FOLR1", "FZD4", "GAA", "GAK", "GALC", "GANAB", "GLB1", "GM2A", "GNA14", "GOSR2", "GPC1", "GSS", "GTPBP4", "HEATR1", "HGS", "HIPK2", "HSPA13", "HTR2B", "INO80E", "KALRN", "KCNH2", "KCNJ16", "KIAA0586", "KRIT1", "LAMB2", "LMAN1", "LTBP3", "MASTL", "MED17", "METTL25", "MGAT5B", "MPL", "MRPL24", "MRPS27", "MSX2", "MUS81", "NALCN", "NEB", "NFE2L1", "NMBR", "NOL11", "NUCB1", "OBSL1", "OGDHL", "OGFOD2", "PARP1", "PCCB", "PDGFRA", "PDYN", "PFAS", "PFKFB3", "PLEC", "PLOD2", "PNKD", "PNPO", "POLD1", "POLE", "POLL", "PPAT", "PRDX3", "PSEN2", "PTCH1", "PTK2B", "RAB5A", "RAD54B", "RELB", "RHOT2", "RIMS2", "RTN4IP1", "SAE1", "SCAPER", "SCN1B", "SCN5A", "SEC23IP", "SERPINE2", "SGCB", "SIGLEC1", "SLC18A3", "SLC26A4", "SLC2A1", "SLC4A1", "SLC4A3", "SLITRK6", "SPG11", "STARD13", "STT3A", "SYF2", "SYNJ1", "SZT2", "TECPR2", "TES", "TMEM67", "TNK2", "TNS1", "TNS3", "TRAP1", "TRAPPC11", "TRAPPC8", "TRIP10", "TRPM2", "TRPM3", "TRPV1", "TUBGCP6", "TYW1", "UNC13B", "USP45", "VCP", "WDR62", "WWOX", "YAP1", "ZBTB48", "ZFHX4", "ZW10"),
5             'Intellectual'=c("YAP1", "TSC2", "FMNL1", "MADD", "KRIT1", "TNK2", "NUP155", "COG6", "TRAPPC8", "IPO9", "CCT8", "ZFYVE16", "FAT1", "SLC37A1", "KAT6B", "WWOX", "PTK2B", "CNTNAP5", "HEATR1", "TRAPPC11", "ARID4A", "ADGRV1", "GPC1", "AURKB", "TTC39B", "GSS", "GANAB", "RFWD3", "CUL9", "SAE1", "CACNG3", "SMC4", "ASIC2", "SYF2", "PFAS", "GAK", "METTL25", "OGDHL", "RAB5A", "VPS13C", "FGFR3", "KCNC1", "DDOST", "CTNND1", "ATRN", "UNC13B", "FASN", "MYO18A", "TMF1", "CRBN", "FLNB", "LARP1", "RCC2", "MASTL", "ADGRA3", "SCAPER", "SZT2", "LRP4", "SMG1", "SYNE1", "ADCY6", "RNGTT", "EP300", "ARAP1", "ANKRD44", "VPS39", "DGCR6L", "STT3A", "COG5", "NFE2L1", "SLC7A2", "ASCC3", "LMAN1", "OBSL1", "KIF20B", "PNPLA7"),
6             'Schizophrenia'=c("CRB1", "FBXW4", "CNTN5", "CHM", "DPYD", "BUB1", "DPP4", "ADGRV1", "GPC1", "DLD", "RBM19", "ITIH1", "ADCY7", "KCNC1", "ACBD5", "ELF1", "TSNARE1", "GABRB3", "TMEM182", "STT3A", "KMT2C", "ANK3", "SAMD4A", "NALCN", "PDLIM5", "LIMA1", "DYNC1I2", "TMEM26", "ANK2", "GRIN3A", "EPHB1", "BRINP2", "KALRN", "MICAL2", "TTLL6", "ZNF292", "SERPINB1", "SCAPER", "KCNS3", "VAMP1", "HDAC2", "DLG1", "CFAP58", "JAK2", "ESR1", "EFCAB14", "CNTNAP2", "PENK", "WWOX", "GLT8D1", "SFMBT2", "EEFSEC", "PDZD8", "GALC", "CACNG3", "SPG7", "ADCY1", "CLDN10", "TENM3", "OTOS", "CAPN2", "LRP4", "SYNE1", "HMGA2", "APOL4", "ARAP1", "DOPEY1", "EPN2", "MCF2L", "PLAA", "RYR3", "CNTNAP5", "POLE", "TRIO", "RAB11FIP5", "BNIP3L", "RUNX1", "AXIN2", "KIF1B", "DLG2", "MAP3K9", "CERCAM", "VPS13C", "MYO18B", "NRP1", "IRS1", "MANEA", "EP300", "DGCR6L", "TSHB", "AASDHPPT", "TRAPPC3", "APC", "TENM4"),
7             'ADHD'=c("TSC2", "CSMD2", "ANK3", "ASPM", "CNTN5", "TP53BP1", "CNTNAP2", "CHD7", "GLT8D1", "CNTNAP5", "SFMBT2", "MLH1", "FLII", "PTCH1", "SPRED1", "ARHGEF12", "CHMP7", "SVEP1", "CREB5", "MSH6", "TTLL8", "DLG2", "MICAL2", "DNAH3", "ADGRA3", "ACBD5", "SYNE1", "NUCB1", "NRP2", "TMEM182", "STT3A", "GNE", "PAX5", "TENM4"),
8             'Biopolar Disoder'=c("CSMD2", "ANK3", "NUMB", "CNTN5", "CTNNA2", "CNTNAP2", "NALCN", "RDH14", "WWOX", "GLT8D1", "SFMBT2", "SPRED1", "ADAMTS14", "TTC39B", "SVEP1", "COL28A1", "PDZD8", "GALC", "SORL1", "ITIH1", "CLSPN", "SLCO4A1", "VPS13C", "MYO18B", "TTLL6", "CRBN", "NFATC2", "SYNE1", "INTS7", "TMEM182", "STT3A", "WSCD1", "KCNS3", "PDGFRA"),
9             'circadian'=c("YTHDC2", "LRP1B", "SAMD4A", "VTA1", "NALCN", "F13A1", "SLC4A1", "TMEM26", "ADAMTS14", "COL28A1", "RNF19A", "BRINP2", "TRHR", "CCBE1", "CACNA2D3", "MYO18A", "SLC26A7", "FRAS1", "EP300", "GNE", "LMAN1", "NMBR", "TGFBI", "CHAT", "HIPK2", "SERPINE2", "RELB", "ARHGEF12", "SETX", "CACNA1D", "ADCY7", "NBAS", "GPR83", "LTBP3", "GABRB3", "HMBS", "PSMA4", "MADD", "SIX3", "EPHB1", "GAK", "SPRY4", "ABCA13", "SLC8A3", "HIVEP2", "FAH", "ADCY6", "MYLIP", "NFE2L1", "PRKAG1", "HDAC2", "TNS1", "GSS", "CACNA1H", "POLL", "CPT1A", "CAPN2", "PITX3", "NFE2L3", "PNPLA7", "AGA", "STX16", "TNK2", "PRF1", "RYR3", "DIXDC1", "PSEN2", "SREBF1", "POLE", "RAB11FIP5", "KIF1B", "RAB5A", "NGB", "ARHGEF11", "SIX6", "SDK1", "AATK", "CYP7A1", "CUL9"),
10             'dementia'=c("LMAN1", "PRDX3", "NPLOC4", "PSEN2", "ZFYVE16", "CHAT", "PENK", "LTBP1", "SNCAIP", "NOL11", "GANAB", "DLD", "SPG11", "IGSF21", "RNF19A", "ASIC2", "ASTN1", "SORL1", "SPRY4", "VCP", "TATDN1", "RAB5A", "VPS13C", "GM2A", "IRS1", "PSMB4", "NGB", "F2RL1", "RAB38", "SMOX", "PARP1", "ABCC9", "RPN2", "CAPN2", "GALNT7", "SMG1", "TBK1", "MASP2", "GNE", "GTPBP4", "CCT8", "CD63", "PSMA4", "TUBA4A", "CUL9")
11            )
12    
13Hmat <- lapply(seq_along(H), \(i) {
14Set <- names(H)[i]
15data.frame(Element = H[[i]], Set)
16    })
17Hmat <- do.call(rbind, Hmat)
18vd <- venneuler(Hmat)
19plot(vd)
20HH <- Hmat %>%
21  group_by(Set) %>%
22  summarise(n = n()) %>%
23  .[match(vd$labels, .$Set),] %>%
24  mutate(n = paste(Set, "\n", n))
25vd$labels <- HH$n
26plot(vd)
27library(reshape2)
28library(eulerr)
29library(purrr)
30vennfun <- function(x) { 
31  x$id <- seq(1, nrow(x))  #add a column of numbers (required for melt)
32  xm <- melt(x, id.vars="id", na.rm=TRUE)  #melt table into two columns (value & variable)
33  xc <- dcast(xm, value~variable, fun.aggregate=length)  #remove NA's, list presence/absence of each value for each variable (1 or 0)
34  rownames(xc) <- xc$value  #value column = rownames (required for Venneuler)
35  xc$value <- NULL  #remove redundent value column
36  xc  #output the new dataframe
37}
38
39HHH<- as.data.frame(t(map_dfr(H, ~as_data_frame(t(.)))))
40HHHH <- vennfun(HHH)
41plot(eulerr::euler(HHHH), quantities = TRUE)
42

enter image description here

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

QUESTION

What do the values for gitlab's predefiner variable CI_PIPELINE_SOURCE mean?

Asked 2021-Oct-27 at 08:17

In the gitlab documentation you find a list of predefined variables HERE, where the variable CI_PIPELINE_SOURCE is explained to have the possible values "push, web, schedule, api, external, chat, webide, merge_request_event, external_pull_request_event, parent_pipeline, trigger, or pipeline."

However, it is not explained, what they mean.

  • push: When you push something to a branch?
  • web: When you trigger a pipeline from the web GUI?
  • schedule: When a pipeline is triggered by a schedule
  • api: When the pipeline is triggered by an API request
  • external: ???
  • chat: ???
  • webide: ???
  • merge_request_event: Seems to be triggered when a merge request is created. Does not trigger when a change is actually merged
  • external_pull_request_event: ???
  • parent_pipeline: ???
  • trigger: ???
  • pipeline: another pipeline?

If someone knows where the documentation for that is hiding, I appreciate if you can let me know where to find it.

In addition, how can I figure out when some changes are actually merged into a branch? How can I trigger a pipeline in that event?

ANSWER

Answered 2021-Oct-27 at 08:17

Regarding your first set of questions, i have to point you forward to the gitlab CI Documentation and the rules:if section. They have their a good explanation of the states and also some addtion https://docs.gitlab.com/ee/ci/jobs/job_control.html#common-if-clauses-for-rules - i am just screenshoting this, so people can relate to it in the future if the link gets outdated:

CI_PIPELINE_SOURCE

Regarding your additional question:

A merge is a push. We do not check on some branches for CI_PIPELINE_SOURCE but for the branch name and do checks simply against that like:

1    rules:
2        - if: '$CI_COMMIT_BRANCH == "master"'
3        - if: '$CI_COMMIT_BRANCH == "develop"'
4        - if: '$CI_COMMIT_BRANCH =~ /^release.*$/i'
5        - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
6

This works eg perfectly in our case for gitflow. But you can vary your rules and easily define them to your own needs - the rules documentation gives a lot of good examples see: https://docs.gitlab.com/ee/ci/jobs/job_control.html#common-if-clauses-for-rules

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

Community Discussions contain sources that include Stack Exchange Network

Tutorials and Learning Resources in Chat

Tutorials and Learning Resources are not available at this moment for Chat

Share this Page

share link

Get latest updates on Chat