From d875eefed0bb43ba0d058260f36db3d54160959b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Pardou?= Date: Sat, 30 Dec 2023 17:53:50 +0100 Subject: [PATCH] Migrate to functionnal components (#232) * Refactor Home component * Refactor Welcome * Refactor small components * Refactor Nav component * refactor Settings * Refactor Chat * Refactor New message notifications * Fix tests * Remove tooltip * Remove react-simple-dropdown * Change to last redux * Switch to redux hooks * Add github action --- .circleci/config.yml | 49 -- .github/workflows/lint-test.yml | 32 + client/.eslintrc.cjs | 18 +- client/jsconfig.json | 9 - client/package.json | 7 +- client/src/actions/app.js | 4 - client/src/actions/app.test.js | 1 - client/src/actions/encrypted_messages.js | 10 +- client/src/components/About/index.jsx | 810 +++++++++--------- client/src/components/Chat/Chat.jsx | 367 ++++---- client/src/components/Chat/Chat.test.jsx | 8 +- client/src/components/Connecting/index.jsx | 10 +- client/src/components/Home/ActivityList.jsx | 46 +- .../src/components/Home/ActivityList.test.jsx | 18 +- client/src/components/Home/Home.jsx | 453 ++++++---- client/src/components/Home/Home.test.jsx | 21 +- .../Home/WithNewMessageNotification.jsx | 182 ++-- .../Home/__snapshots__/index.test.jsx.snap | 89 +- client/src/components/Home/index.jsx | 16 +- client/src/components/Home/index.test.jsx | 96 ++- client/src/components/Message/index.jsx | 43 +- client/src/components/Nav/Nav.test.jsx | 55 +- .../Nav/__snapshots__/Nav.test.jsx.snap | 406 ++++++--- client/src/components/Nav/index.jsx | 271 +++--- .../src/components/RoomLink/RoomLink.test.jsx | 47 +- .../__snapshots__/RoomLink.test.jsx.snap | 6 +- client/src/components/RoomLink/index.jsx | 99 ++- client/src/components/RoomLocked/index.jsx | 10 +- .../src/components/Settings/Settings.test.jsx | 24 +- .../__snapshots__/Settings.test.jsx.snap | 2 + client/src/components/Settings/index.jsx | 335 ++++---- client/src/components/T/T.jsx | 36 +- .../src/components/Username/Username.test.jsx | 1 - client/src/components/Username/index.jsx | 17 +- client/src/components/Welcome/index.jsx | 64 +- client/src/main.tsx | 2 +- client/src/reducers/room.js | 2 +- client/src/reducers/user.js | 49 +- client/src/reducers/user.test.js | 11 +- client/src/store/index.js | 13 +- client/src/stylesheets/nav.sass | 17 +- client/tsconfig.json | 1 + client/yarn.lock | 368 +++++++- readme.md | 2 +- 44 files changed, 2301 insertions(+), 1826 deletions(-) delete mode 100644 .circleci/config.yml create mode 100644 .github/workflows/lint-test.yml delete mode 100644 client/jsconfig.json diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 317616ad..00000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,49 +0,0 @@ -# Javascript Node CircleCI 2.0 configuration file -# - -jobs: - test-job: - docker: - - image: "cimg/node:lts" - - working_directory: ~/repo - - steps: - - checkout - # Download and cache dependencies - - restore_cache: - keys: - - dependencies-{{ checksum "yarn.lock" }} - # fallback to using the latest cache if no exact match is found - - dependencies- - - - run: yarn setup - - - save_cache: - paths: - - node_modules - - client/node_modules - - server/node_modules - key: dependencies-{{ checksum "yarn.lock" }} - - - run: - command: yarn lint - - - run: - command: yarn test - environment: - TZ: UTC - VITE_COMMIT_SHA: some_sha - - - store_artifacts: # For coverage report - path: client/coverage - -orbs: # declare what orbs we are going to use - node: circleci/node@2.0.2 # the node orb provides common node-related configuration - -version: 2.1 - -workflows: - tests: - jobs: - - test-job diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml new file mode 100644 index 00000000..bdb12af4 --- /dev/null +++ b/.github/workflows/lint-test.yml @@ -0,0 +1,32 @@ +# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs + +name: Node.js CI + +on: + push: + pull_request: + workflow_dispatch: +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [16.x, 18.x] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + + steps: + - uses: actions/checkout@v3 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + - run: npm i yarn -g + - run: yarn setup + env: + TZ: UTC + VITE_COMMIT_SHA: some_sha + - run: yarn lint + - run: yarn test diff --git a/client/.eslintrc.cjs b/client/.eslintrc.cjs index 68156998..0da511b3 100644 --- a/client/.eslintrc.cjs +++ b/client/.eslintrc.cjs @@ -1,5 +1,11 @@ module.exports = { - extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react/recommended', + 'plugin:react/jsx-runtime', + 'plugin:react-hooks/recommended' + ], parser: '@typescript-eslint/parser', plugins: ['@typescript-eslint'], root: true, @@ -7,4 +13,14 @@ module.exports = { browser: true, node: true, }, + settings: { + react: { + pragma: 'React', // Pragma to use, default to "React" + version: 'detect', // React version. "detect" automatically picks the version you have installed. + }, + }, + rules: { + "react/prop-types": "off", + "@typescript-eslint/no-empty-function": "off" + } }; diff --git a/client/jsconfig.json b/client/jsconfig.json deleted file mode 100644 index 0ecf7b31..00000000 --- a/client/jsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": "src", - "paths": { - "@/*": ["src/*"] - } - } -} - diff --git a/client/package.json b/client/package.json index 26f2c7db..1a0485c5 100644 --- a/client/package.json +++ b/client/package.json @@ -13,9 +13,10 @@ ], "license": "MIT", "dependencies": { + "@react-hookz/web": "^20.0.2", + "@reduxjs/toolkit": "^1.9.1", "bootstrap": "^4.6.2", "classnames": "^2.3.2", - "clipboard": "^2.0.11", "jquery": "3", "moment": "^2.29.4", "nanoid": "^4.0.0", @@ -28,7 +29,7 @@ "react-redux": "^8.0.5", "react-router": "^6.4.4", "react-router-dom": "^6.4.4", - "react-simple-dropdown": "^3.2.3", + "react-tooltip": "^5.2.0", "redux": "^4.2.0", "redux-thunk": "^2.4.2", "sanitize-html": "^2.7.3", @@ -54,6 +55,8 @@ "eslint": "^8.29.0", "eslint-config-prettier": "^6.11.0", "eslint-plugin-prettier": "^3.1.3", + "eslint-plugin-react": "^7.31.11", + "eslint-plugin-react-hooks": "^4.6.0", "jest-environment-jsdom-sixteen": "^1.0.3", "jest-fetch-mock": "^3.0.3", "prettier": "^2.0.5", diff --git a/client/src/actions/app.js b/client/src/actions/app.js index 3aac0892..8a5ca15a 100644 --- a/client/src/actions/app.js +++ b/client/src/actions/app.js @@ -31,10 +31,6 @@ export const toggleSocketConnected = payload => async dispatch => { dispatch({ type: 'TOGGLE_SOCKET_CONNECTED', payload }); }; -export const createUser = payload => async dispatch => { - dispatch({ type: 'CREATE_USER', payload }); -}; - export const clearActivities = () => async dispatch => { dispatch({ type: 'CLEAR_ACTIVITIES' }); }; diff --git a/client/src/actions/app.test.js b/client/src/actions/app.test.js index 9ba2a359..30c9ad2c 100644 --- a/client/src/actions/app.test.js +++ b/client/src/actions/app.test.js @@ -40,7 +40,6 @@ describe('App actions', () => { [actions.showNotice('test'), 'SHOW_NOTICE'], [actions.toggleSoundEnabled('test'), 'TOGGLE_SOUND_ENABLED'], [actions.toggleSocketConnected('test'), 'TOGGLE_SOCKET_CONNECTED'], - [actions.createUser('test'), 'CREATE_USER'], [actions.setLanguage('test'), 'CHANGE_LANGUAGE'], ]; diff --git a/client/src/actions/encrypted_messages.js b/client/src/actions/encrypted_messages.js index 95000425..50f50ae7 100644 --- a/client/src/actions/encrypted_messages.js +++ b/client/src/actions/encrypted_messages.js @@ -1,10 +1,18 @@ import { getSocket } from '@/utils/socket'; import { prepare as prepareMessage, process as processMessage } from '@/utils/message'; +import { changeUsername } from '@/reducers/user'; export const sendEncryptedMessage = payload => async (dispatch, getState) => { const state = getState(); const msg = await prepareMessage(payload, state); - dispatch({ type: `SEND_ENCRYPTED_MESSAGE_${msg.original.type}`, payload: msg.original.payload }); + switch(msg.original.type){ + case "CHANGE_USERNAME": + dispatch(changeUsername(msg.original.payload)); + dispatch({ type: `SEND_ENCRYPTED_MESSAGE_${msg.original.type}`, payload: msg.original.payload }); + break; + default: + dispatch({ type: `SEND_ENCRYPTED_MESSAGE_${msg.original.type}`, payload: msg.original.payload }); + } getSocket().emit('ENCRYPTED_MESSAGE', msg.toSend); }; diff --git a/client/src/components/About/index.jsx b/client/src/components/About/index.jsx index 823ed746..5243551c 100644 --- a/client/src/components/About/index.jsx +++ b/client/src/components/About/index.jsx @@ -1,448 +1,434 @@ /* eslint-disable */ -import React, { Component } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; import { COMMIT_SHA } from '@/config/env'; import apiUrlGenerator from '@/api/generator'; import styles from './styles.module.scss'; -class About extends Component { - constructor(props) { - super(props); - this.state = { - roomId: props.roomId, - abuseReported: false, - }; - } +const About = ({ roomId: roomIdProp }) => { + const [roomId, setRoomId] = React.useState(roomIdProp); + const [abuseReported, setAbuseReported] = React.useState(false); - handleUpdateRoomId(evt) { - this.setState({ - roomId: evt.target.value, - }); - } + const handleUpdateRoomId = evt => { + setRoomId(evt.target.value); + }; - handleReportAbuse(evt) { + const handleReportAbuse = evt => { evt.preventDefault(); - fetch(`${apiUrlGenerator('abuse')}/${this.state.roomId}`, { + fetch(`${apiUrlGenerator('abuse')}/${roomId}`, { method: 'POST', }); - this.setState({ - abuseReported: true, - }); - } + setAbuseReported(true); + }; - render() { - return ( -
-
-
- Version -
-
- Software -
-
- Report Abuse -
-
- Acceptable Use Policy -
-
- Disclaimer -
-
- Terms of Service -
-
- Contact -
-
- Donate -
+ return ( +
+
+
+ Version +
+
+ Software +
+ + + + +
+ Contact +
+
+ Donate +
+
-
-

Version

-

- Commit SHA:{' '} - - {COMMIT_SHA} - -

-
+
+

Version

+

+ Commit SHA:{' '} + + {COMMIT_SHA} + +

+
-
-

Software

-

- This software uses the{' '} - - Web Cryptography API - {' '} - to encrypt data which is transferred using{' '} - - secure WebSockets - - . Messages are never stored on a server or sent over the wire in plain-text. -

-

- We believe in privacy and transparency.   - - View the source code and documentation on GitHub. - -

-
+
+

Software

+

+ This software uses the{' '} + + Web Cryptography API + {' '} + to encrypt data which is transferred using{' '} + + secure WebSockets + + . Messages are never stored on a server or sent over the wire in plain-text. +

+

+ We believe in privacy and transparency.   + + View the source code and documentation on GitHub. + +

+
-
-

Report Abuse

-

- We encourage you to report problematic content to us. Please keep in mind that to help ensure the safety, - confidentiality and security of your messages, we do not have the contents of messages available to us, - which limits our ability to verify the report and take action. -

-

- When needed, you can take a screenshot of the content and share it, along with any available contact info, - with appropriate law enforcement authorities. -

-

- To report any content, email us at abuse[at]darkwire.io or submit the room ID below to report anonymously. -

-
- {this.state.abuseReported &&
Thank you!
} -
-
- -
- -
+
+

Report Abuse

+

+ We encourage you to report problematic content to us. Please keep in mind that to help ensure the safety, + confidentiality and security of your messages, we do not have the contents of messages available to us, which + limits our ability to verify the report and take action. +

+

+ When needed, you can take a screenshot of the content and share it, along with any available contact info, + with appropriate law enforcement authorities. +

+

+ To report any content, email us at abuse[at]darkwire.io or submit the room ID below to report anonymously. +

+ + {abuseReported &&
Thank you!
} +
+
+ +
+
- -
-

If you feel you or anyone else is in immediate danger, please contact your local emergency services.

-

- If you receive content from someone who wishes to hurt themselves, and you're concerned for their safety, - please contact your local emergency services or a{' '} - suicide prevention hotline. -

-

- If you receive or encounter content indicating abuse or exploitation of a child, please contact the{' '} - National Center for Missing and Exploited Children (NCMEC). -

-
+
+ +
+

If you feel you or anyone else is in immediate danger, please contact your local emergency services.

+

+ If you receive content from someone who wishes to hurt themselves, and you're concerned for their safety, + please contact your local emergency services or a{' '} + suicide prevention hotline. +

+

+ If you receive or encounter content indicating abuse or exploitation of a child, please contact the{' '} + National Center for Missing and Exploited Children (NCMEC). +

+
-
-

Acceptable Use Policy

-

- This Acceptable Use Policy (this “Policy”) describes prohibited uses of the web services offered by Darkwire - and its affiliates (the “Services”) and the website located at https://darkwire.io (the “Darkwire Site”). - The examples described in this Policy are not exhaustive. We may modify this Policy at any time by posting a - revised version on the Darkwire Site. By using the Services or accessing the Darkwire Site, you agree to the - latest version of this Policy. If you violate the Policy or authorize or help others to do so, we may - suspend or terminate your use of the Services. -

- No Illegal, Harmful, or Offensive Use or Content -

- You may not use, or encourage, promote, facilitate or instruct others to use, the Services or Darkwire Site - for any illegal, harmful, fraudulent, infringing or offensive use, or to transmit, store, display, - distribute or otherwise make available content that is illegal, harmful, fraudulent, infringing or - offensive. Prohibited activities or content include: -

-
    -
  • - Illegal, Harmful or Fraudulent Activities. Any activities that are illegal, that violate - the rights of others, or that may be harmful to others, our operations or reputation, including - disseminating, promoting or facilitating child pornography, offering or disseminating fraudulent goods, - services, schemes, or promotions, make-money-fast schemes, ponzi and pyramid schemes, phishing, or - pharming. -
  • +
    +

    Acceptable Use Policy

    +

    + This Acceptable Use Policy (this “Policy”) describes prohibited uses of the web services offered by Darkwire + and its affiliates (the “Services”) and the website located at https://darkwire.io (the “Darkwire Site”). The + examples described in this Policy are not exhaustive. We may modify this Policy at any time by posting a + revised version on the Darkwire Site. By using the Services or accessing the Darkwire Site, you agree to the + latest version of this Policy. If you violate the Policy or authorize or help others to do so, we may suspend + or terminate your use of the Services. +

    + No Illegal, Harmful, or Offensive Use or Content +

    + You may not use, or encourage, promote, facilitate or instruct others to use, the Services or Darkwire Site + for any illegal, harmful, fraudulent, infringing or offensive use, or to transmit, store, display, distribute + or otherwise make available content that is illegal, harmful, fraudulent, infringing or offensive. Prohibited + activities or content include: +

    +
      +
    • + Illegal, Harmful or Fraudulent Activities. Any activities that are illegal, that violate + the rights of others, or that may be harmful to others, our operations or reputation, including + disseminating, promoting or facilitating child pornography, offering or disseminating fraudulent goods, + services, schemes, or promotions, make-money-fast schemes, ponzi and pyramid schemes, phishing, or pharming. +
    • -
    • - Infringing Content. Content that infringes or misappropriates the intellectual property - or proprietary rights of others. -
    • +
    • + Infringing Content. Content that infringes or misappropriates the intellectual property or + proprietary rights of others. +
    • -
    • - Offensive Content. Content that is defamatory, obscene, abusive, invasive of privacy, or - otherwise objectionable, including content that constitutes child pornography, relates to bestiality, or - depicts non-consensual sex acts. -
    • +
    • + Offensive Content. Content that is defamatory, obscene, abusive, invasive of privacy, or + otherwise objectionable, including content that constitutes child pornography, relates to bestiality, or + depicts non-consensual sex acts. +
    • -
    • - Harmful Content. Content or other computer technology that may damage, interfere with, - surreptitiously intercept, or expropriate any system, program, or data, including viruses, Trojan horses, - worms, time bombs, or cancelbots. -
    • -
    - No Security Violations -
    - You may not use the Services to violate the security or integrity of any network, computer or communications - system, software application, or network or computing device (each, a “System”). Prohibited activities - include: -
      -
    • - Unauthorized Access. Accessing or using any System without permission, including - attempting to probe, scan, or test the vulnerability of a System or to breach any security or - authentication measures used by a System. -
    • +
    • + Harmful Content. Content or other computer technology that may damage, interfere with, + surreptitiously intercept, or expropriate any system, program, or data, including viruses, Trojan horses, + worms, time bombs, or cancelbots. +
    • +
    + No Security Violations +
    + You may not use the Services to violate the security or integrity of any network, computer or communications + system, software application, or network or computing device (each, a “System”). Prohibited activities include: +
      +
    • + Unauthorized Access. Accessing or using any System without permission, including attempting + to probe, scan, or test the vulnerability of a System or to breach any security or authentication measures + used by a System. +
    • -
    • - Interception. Monitoring of data or traffic on a System without permission. -
    • +
    • + Interception. Monitoring of data or traffic on a System without permission. +
    • -
    • - Falsification of Origin. Forging TCP-IP packet headers, e-mail headers, or any part of a - message describing its origin or route. The legitimate use of aliases and anonymous remailers is not - prohibited by this provision. -
    • -
    - No Network Abuse -
    - You may not make network connections to any users, hosts, or networks unless you have permission to - communicate with them. Prohibited activities include: -
      -
    • - Monitoring or Crawling. Monitoring or crawling of a System that impairs or disrupts the - System being monitored or crawled. -
    • +
    • + Falsification of Origin. Forging TCP-IP packet headers, e-mail headers, or any part of a + message describing its origin or route. The legitimate use of aliases and anonymous remailers is not + prohibited by this provision. +
    • +
    + No Network Abuse +
    + You may not make network connections to any users, hosts, or networks unless you have permission to communicate + with them. Prohibited activities include: +
      +
    • + Monitoring or Crawling. Monitoring or crawling of a System that impairs or disrupts the + System being monitored or crawled. +
    • -
    • - Denial of Service (DoS). Inundating a target with communications requests so the target - either cannot respond to legitimate traffic or responds so slowly that it becomes ineffective. -
    • +
    • + Denial of Service (DoS). Inundating a target with communications requests so the target + either cannot respond to legitimate traffic or responds so slowly that it becomes ineffective. +
    • -
    • - Intentional Interference. Interfering with the proper functioning of any System, - including any deliberate attempt to overload a system by mail bombing, news bombing, broadcast attacks, or - flooding techniques. -
    • +
    • + Intentional Interference. Interfering with the proper functioning of any System, including + any deliberate attempt to overload a system by mail bombing, news bombing, broadcast attacks, or flooding + techniques. +
    • -
    • - Operation of Certain Network Services. Operating network services like open proxies, open - mail relays, or open recursive domain name servers. -
    • +
    • + Operation of Certain Network Services. Operating network services like open proxies, open + mail relays, or open recursive domain name servers. +
    • -
    • - Avoiding System Restrictions. Using manual or electronic means to avoid any use - limitations placed on a System, such as access and storage restrictions. -
    • -
    - No E-Mail or Other Message Abuse -
    - You will not distribute, publish, send, or facilitate the sending of unsolicited mass e-mail or other - messages, promotions, advertising, or solicitations (like “spam”), including commercial advertising and - informational announcements. You will not alter or obscure mail headers or assume a sender’s identity without - the sender’s explicit permission. You will not collect replies to messages sent from another internet service - provider if those messages violate this Policy or the acceptable use policy of that provider. - Our Monitoring and Enforcement -
    - We reserve the right, but do not assume the obligation, to investigate any violation of this Policy or misuse - of the Services or Darkwire Site. We may: -
      -
    • investigate violations of this Policy or misuse of the Services or Darkwire Site; or
    • -
    • - remove, disable access to, or modify any content or resource that violates this Policy or any other - agreement we have with you for use of the Services or the Darkwire Site. -
    • -
    • - We may report any activity that we suspect violates any law or regulation to appropriate law enforcement - officials, regulators, or other appropriate third parties. Our reporting may include disclosing - appropriate customer information. We also may cooperate with appropriate law enforcement agencies, - regulators, or other appropriate third parties to help with the investigation and prosecution of illegal - conduct by providing network and systems information related to alleged violations of this Policy. -
    • -
    - Reporting of Violations of this Policy -
    - If you become aware of any violation of this Policy, you will immediately notify us and provide us with - assistance, as requested, to stop or remedy the violation. To report any violation of this Policy, please - follow our abuse reporting process. -
    +
  • + Avoiding System Restrictions. Using manual or electronic means to avoid any use limitations + placed on a System, such as access and storage restrictions. +
  • +
+ No E-Mail or Other Message Abuse +
+ You will not distribute, publish, send, or facilitate the sending of unsolicited mass e-mail or other messages, + promotions, advertising, or solicitations (like “spam”), including commercial advertising and informational + announcements. You will not alter or obscure mail headers or assume a sender’s identity without the sender’s + explicit permission. You will not collect replies to messages sent from another internet service provider if + those messages violate this Policy or the acceptable use policy of that provider. + Our Monitoring and Enforcement +
+ We reserve the right, but do not assume the obligation, to investigate any violation of this Policy or misuse of + the Services or Darkwire Site. We may: +
    +
  • investigate violations of this Policy or misuse of the Services or Darkwire Site; or
  • +
  • + remove, disable access to, or modify any content or resource that violates this Policy or any other + agreement we have with you for use of the Services or the Darkwire Site. +
  • +
  • + We may report any activity that we suspect violates any law or regulation to appropriate law enforcement + officials, regulators, or other appropriate third parties. Our reporting may include disclosing appropriate + customer information. We also may cooperate with appropriate law enforcement agencies, regulators, or other + appropriate third parties to help with the investigation and prosecution of illegal conduct by providing + network and systems information related to alleged violations of this Policy. +
  • +
+ Reporting of Violations of this Policy +
+ If you become aware of any violation of this Policy, you will immediately notify us and provide us with + assistance, as requested, to stop or remedy the violation. To report any violation of this Policy, please follow + our abuse reporting process. +
-
-

Terms of Service ("Terms")

-

Last updated: December 11, 2017

-

- Please read these Terms of Service ("Terms", "Terms of Service") carefully before using the - https://darkwire.io website (the "Service") operated by Darkwire ("us", "we", or "our"). -

-

- Your access to and use of the Service is conditioned on your acceptance of and compliance with these Terms. - These Terms apply to all visitors, users and others who access or use the Service. -

-

- By accessing or using the Service you agree to be bound by these Terms. If you disagree with any part of the - terms then you may not access the Service. -

- Links To Other Web Sites -

- Our Service may contain links to third-party web sites or services that are not owned or controlled by - Darkwire. -

-

- Darkwire has no control over, and assumes no responsibility for, the content, privacy policies, or practices - of any third party web sites or services. You further acknowledge and agree that Darkwire shall not be - responsible or liable, directly or indirectly, for any damage or loss caused or alleged to be caused by or - in connection with use of or reliance on any such content, goods or services available on or through any - such web sites or services. -

-

- We strongly advise you to read the terms and conditions and privacy policies of any third-party web sites or - services that you visit. -

- Termination -

- We may terminate or suspend access to our Service immediately, without prior notice or liability, for any - reason whatsoever, including without limitation if you breach the Terms. -

-

- All provisions of the Terms which by their nature should survive termination shall survive termination, - including, without limitation, ownership provisions, warranty disclaimers, indemnity and limitations of - liability. -

- Governing Law -

- These Terms shall be governed and construed in accordance with the laws of New York, United States, without - regard to its conflict of law provisions. -

-

- Our failure to enforce any right or provision of these Terms will not be considered a waiver of those - rights. If any provision of these Terms is held to be invalid or unenforceable by a court, the remaining - provisions of these Terms will remain in effect. These Terms constitute the entire agreement between us - regarding our Service, and supersede and replace any prior agreements we might have between us regarding the - Service. -

-
+
+

Terms of Service ("Terms")

+

Last updated: December 11, 2017

+

+ Please read these Terms of Service ("Terms", "Terms of Service") carefully before using the + https://darkwire.io website (the "Service") operated by Darkwire ("us", "we", or "our"). +

+

+ Your access to and use of the Service is conditioned on your acceptance of and compliance with these Terms. + These Terms apply to all visitors, users and others who access or use the Service. +

+

+ By accessing or using the Service you agree to be bound by these Terms. If you disagree with any part of the + terms then you may not access the Service. +

+ Links To Other Web Sites +

+ Our Service may contain links to third-party web sites or services that are not owned or controlled by + Darkwire. +

+

+ Darkwire has no control over, and assumes no responsibility for, the content, privacy policies, or practices + of any third party web sites or services. You further acknowledge and agree that Darkwire shall not be + responsible or liable, directly or indirectly, for any damage or loss caused or alleged to be caused by or in + connection with use of or reliance on any such content, goods or services available on or through any such web + sites or services. +

+

+ We strongly advise you to read the terms and conditions and privacy policies of any third-party web sites or + services that you visit. +

+ Termination +

+ We may terminate or suspend access to our Service immediately, without prior notice or liability, for any + reason whatsoever, including without limitation if you breach the Terms. +

+

+ All provisions of the Terms which by their nature should survive termination shall survive termination, + including, without limitation, ownership provisions, warranty disclaimers, indemnity and limitations of + liability. +

+ Governing Law +

+ These Terms shall be governed and construed in accordance with the laws of New York, United States, without + regard to its conflict of law provisions. +

+

+ Our failure to enforce any right or provision of these Terms will not be considered a waiver of those rights. + If any provision of these Terms is held to be invalid or unenforceable by a court, the remaining provisions of + these Terms will remain in effect. These Terms constitute the entire agreement between us regarding our + Service, and supersede and replace any prior agreements we might have between us regarding the Service. +

+
-
-

Disclaimer

-

- WARNING: Darkwire does not mask IP addresses nor can verify the integrity of parties recieving messages. -  Proceed with caution and always confirm recipients beforre starting a chat session. -

-

- Please also note that ALL CHATROOMS are public.  Anyone can guess your room URL. If - you need a more-private room, use the lock feature or set the URL manually by entering a room ID after - "darkwire.io/". -

-
- No Warranties; Exclusion of Liability; Indemnification -

- - OUR WEBSITE IS OPERATED BY Darkwire ON AN "AS IS," "AS AVAILABLE" BASIS, WITHOUT REPRESENTATIONS OR - WARRANTIES OF ANY KIND. TO THE FULLEST EXTENT PERMITTED BY LAW, Darkwire SPECIFICALLY DISCLAIMS ALL - WARRANTIES AND CONDITIONS OF ANY KIND, INCLUDING ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NONINFRINGEMENT FOR OUR WEBSITE AND ANY CONTRACTS AND SERVICES - YOU PURCHASE THROUGH IT. Darkwire SHALL NOT HAVE ANY LIABILITY OR RESPONSIBILITY FOR ANY ERRORS OR - OMISSIONS IN THE CONTENT OF OUR WEBSITE, FOR CONTRACTS OR SERVICES SOLD THROUGH OUR WEBSITE, FOR YOUR - ACTION OR INACTION IN CONNECTION WITH OUR WEBSITE OR FOR ANY DAMAGE TO YOUR COMPUTER OR DATA OR ANY OTHER - DAMAGE YOU MAY INCUR IN CONNECTION WITH OUR WEBSITE. YOUR USE OF OUR WEBSITE AND ANY CONTRACTS OR SERVICES - ARE AT YOUR OWN RISK. IN NO EVENT SHALL EITHER Darkwire OR THEIR AGENTS BE LIABLE FOR ANY DIRECT, - INDIRECT, PUNITIVE, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN ANY WAY CONNECTED - WITH THE USE OF OUR WEBSITE, CONTRACTS AND SERVICES PURCHASED THROUGH OUR WEBSITE, THE DELAY OR INABILITY - TO USE OUR WEBSITE OR OTHERWISE ARISING IN CONNECTION WITH OUR WEBSITE, CONTRACTS OR RELATED SERVICES, - WHETHER BASED ON CONTRACT, TORT, STRICT LIABILITY OR OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF ANY - SUCH DAMAGES. IN NO EVENT SHALL Darkwire’s LIABILITY FOR ANY DAMAGE CLAIM EXCEED THE AMOUNT PAID BY YOU TO - Darkwire FOR THE TRANSACTION GIVING RISE TO SUCH DAMAGE CLAIM. - -

-

- - SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE - ABOVE EXCLUSION MAY NOT APPLY TO YOU. - -

-

- - WITHOUT LIMITING THE FOREGOING, Darkwire DO NOT REPRESENT OR WARRANT THAT THE INFORMATION ON THE WEBITE IS - ACCURATE, COMPLETE, RELIABLE, USEFUL, TIMELY OR CURRENT OR THAT OUR WEBSITE WILL OPERATE WITHOUT - INTERRUPTION OR ERROR. - -

-

- - YOU AGREE THAT ALL TIMES, YOU WILL LOOK TO ATTORNEYS FROM WHOM YOU PURCHASE SERVICES FOR ANY CLAIMS OF ANY - NATURE, INCLUDING LOSS, DAMAGE, OR WARRANTY. Darkwire AND THEIR RESPECTIVE AFFILIATES MAKE NO - REPRESENTATION OR GUARANTEES ABOUT ANY CONTRACTS AND SERVICES OFFERED THROUGH OUR WEBSITE. - -

-

- - Darkwire MAKES NO REPRESENTATION THAT CONTENT PROVIDED ON OUR WEBSITE, CONTRACTS, OR RELATED SERVICES ARE - APPLICABLE OR APPROPRIATE FOR USE IN ALL JURISDICTIONS. - -

- Indemnification -

- You agree to defend, indemnify and hold Darkwire harmless from and against any and all claims, damages, - costs and expenses, including attorneys' fees, arising from or related to your use of our Website or any - Contracts or Services you purchase through it. -

- Changes -

- We reserve the right, at our sole discretion, to modify or replace these Terms at any time. If a revision is - material we will try to provide at least 30 days notice prior to any new terms taking effect. What - constitutes a material change will be determined at our sole discretion. -

-

- By continuing to access or use our Service after those revisions become effective, you agree to be bound by - the revised terms. If you do not agree to the new terms, please stop using the Service. -

- Contact Us -

If you have any questions about these Terms, please contact us at hello[at]darkwire.io.

-
+
+

Disclaimer

+

+ WARNING: Darkwire does not mask IP addresses nor can verify the integrity of parties recieving messages. +  Proceed with caution and always confirm recipients beforre starting a chat session. +

+

+ Please also note that ALL CHATROOMS are public.  Anyone can guess your room URL. If you + need a more-private room, use the lock feature or set the URL manually by entering a room ID after + "darkwire.io/". +

+
+ No Warranties; Exclusion of Liability; Indemnification +

+ + OUR WEBSITE IS OPERATED BY Darkwire ON AN "AS IS," "AS AVAILABLE" BASIS, WITHOUT REPRESENTATIONS OR + WARRANTIES OF ANY KIND. TO THE FULLEST EXTENT PERMITTED BY LAW, Darkwire SPECIFICALLY DISCLAIMS ALL + WARRANTIES AND CONDITIONS OF ANY KIND, INCLUDING ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NONINFRINGEMENT FOR OUR WEBSITE AND ANY CONTRACTS AND SERVICES + YOU PURCHASE THROUGH IT. Darkwire SHALL NOT HAVE ANY LIABILITY OR RESPONSIBILITY FOR ANY ERRORS OR OMISSIONS + IN THE CONTENT OF OUR WEBSITE, FOR CONTRACTS OR SERVICES SOLD THROUGH OUR WEBSITE, FOR YOUR ACTION OR + INACTION IN CONNECTION WITH OUR WEBSITE OR FOR ANY DAMAGE TO YOUR COMPUTER OR DATA OR ANY OTHER DAMAGE YOU + MAY INCUR IN CONNECTION WITH OUR WEBSITE. YOUR USE OF OUR WEBSITE AND ANY CONTRACTS OR SERVICES ARE AT YOUR + OWN RISK. IN NO EVENT SHALL EITHER Darkwire OR THEIR AGENTS BE LIABLE FOR ANY DIRECT, INDIRECT, PUNITIVE, + INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN ANY WAY CONNECTED WITH THE USE OF OUR + WEBSITE, CONTRACTS AND SERVICES PURCHASED THROUGH OUR WEBSITE, THE DELAY OR INABILITY TO USE OUR WEBSITE OR + OTHERWISE ARISING IN CONNECTION WITH OUR WEBSITE, CONTRACTS OR RELATED SERVICES, WHETHER BASED ON CONTRACT, + TORT, STRICT LIABILITY OR OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF ANY SUCH DAMAGES. IN NO EVENT + SHALL Darkwire’s LIABILITY FOR ANY DAMAGE CLAIM EXCEED THE AMOUNT PAID BY YOU TO Darkwire FOR THE + TRANSACTION GIVING RISE TO SUCH DAMAGE CLAIM. + +

+

+ + SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE + ABOVE EXCLUSION MAY NOT APPLY TO YOU. + +

+

+ + WITHOUT LIMITING THE FOREGOING, Darkwire DO NOT REPRESENT OR WARRANT THAT THE INFORMATION ON THE WEBITE IS + ACCURATE, COMPLETE, RELIABLE, USEFUL, TIMELY OR CURRENT OR THAT OUR WEBSITE WILL OPERATE WITHOUT + INTERRUPTION OR ERROR. + +

+

+ + YOU AGREE THAT ALL TIMES, YOU WILL LOOK TO ATTORNEYS FROM WHOM YOU PURCHASE SERVICES FOR ANY CLAIMS OF ANY + NATURE, INCLUDING LOSS, DAMAGE, OR WARRANTY. Darkwire AND THEIR RESPECTIVE AFFILIATES MAKE NO REPRESENTATION + OR GUARANTEES ABOUT ANY CONTRACTS AND SERVICES OFFERED THROUGH OUR WEBSITE. + +

+

+ + Darkwire MAKES NO REPRESENTATION THAT CONTENT PROVIDED ON OUR WEBSITE, CONTRACTS, OR RELATED SERVICES ARE + APPLICABLE OR APPROPRIATE FOR USE IN ALL JURISDICTIONS. + +

+ Indemnification +

+ You agree to defend, indemnify and hold Darkwire harmless from and against any and all claims, damages, costs + and expenses, including attorneys' fees, arising from or related to your use of our Website or any Contracts + or Services you purchase through it. +

+ Changes +

+ We reserve the right, at our sole discretion, to modify or replace these Terms at any time. If a revision is + material we will try to provide at least 30 days notice prior to any new terms taking effect. What constitutes + a material change will be determined at our sole discretion. +

+

+ By continuing to access or use our Service after those revisions become effective, you agree to be bound by + the revised terms. If you do not agree to the new terms, please stop using the Service. +

+ Contact Us +

If you have any questions about these Terms, please contact us at hello[at]darkwire.io.

+
-
-

Contact

-

Questions/comments? Email us at hello[at]darkwire.io

-

- Found a bug or want a new feature?{' '} - - Open a ticket on Github - - . -

-
+
+

Contact

+

Questions/comments? Email us at hello[at]darkwire.io

+

+ Found a bug or want a new feature?{' '} + + Open a ticket on Github + + . +

+
- -
- ); - } -} + +
+ ); +}; About.propTypes = { roomId: PropTypes.string.isRequired, diff --git a/client/src/components/Chat/Chat.jsx b/client/src/components/Chat/Chat.jsx index 92e0b27d..ad7f15d4 100644 --- a/client/src/components/Chat/Chat.jsx +++ b/client/src/components/Chat/Chat.jsx @@ -1,171 +1,134 @@ -import React, { Component } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; import sanitizeHtml from 'sanitize-html'; import { CornerDownRight } from 'react-feather'; -import { getSelectedText, hasTouchSupport } from '@/utils/dom'; +import { hasTouchSupport } from '@/utils/dom'; import FileTransfer from '@/components/FileTransfer'; -export class Chat extends Component { - constructor(props) { - super(props); - this.state = { - message: '', - touchSupport: hasTouchSupport, - shiftKeyDown: false, - }; +export const Chat = ({ sendEncryptedMessage, showNotice, userId, username, clearActivities, translations }) => { + const [message, setMessage] = React.useState(''); + const [shiftKeyDown, setShiftKeyDown] = React.useState(false); + const textInputRef = React.useRef(); + + const touchSupport = hasTouchSupport; + + const canSend = message.trim().length; + + const commands = [ + { + command: 'nick', + description: 'Changes nickname.', + parameters: ['{username}'], + usage: '/nick {username}', + scope: 'global', + action: params => { + // eslint-disable-line + let newUsername = params.join(' ') || ''; // eslint-disable-line + + // Remove things that aren't digits or chars + newUsername = newUsername.replace(/[^A-Za-z0-9]/g, '-'); + + const errors = []; + + if (!newUsername.trim().length) { + errors.push('Username cannot be blank'); + } + + if (newUsername.toString().length > 16) { + errors.push('Username cannot be greater than 16 characters'); + } - this.commands = [ - { - command: 'nick', - description: 'Changes nickname.', - parameters: ['{username}'], - usage: '/nick {username}', - scope: 'global', - action: params => { - // eslint-disable-line - let newUsername = params.join(' ') || ''; // eslint-disable-line - - // Remove things that aren't digits or chars - newUsername = newUsername.replace(/[^A-Za-z0-9]/g, '-'); - - const errors = []; - - if (!newUsername.trim().length) { - errors.push('Username cannot be blank'); - } - - if (newUsername.toString().length > 16) { - errors.push('Username cannot be greater than 16 characters'); - } - - if (!newUsername.match(/^[A-Z]/i)) { - errors.push('Username must start with a letter'); - } - - if (errors.length) { - return this.props.showNotice({ - message: `${errors.join(', ')}`, - level: 'error', - }); - } - - this.props.sendEncryptedMessage({ - type: 'CHANGE_USERNAME', - payload: { - id: this.props.userId, - newUsername, - currentUsername: this.props.username, - }, + if (!newUsername.match(/^[A-Z]/i)) { + errors.push('Username must start with a letter'); + } + + if (errors.length) { + return showNotice({ + message: `${errors.join(', ')}`, + level: 'error', }); - }, + } + + sendEncryptedMessage({ + type: 'CHANGE_USERNAME', + payload: { + id: userId, + newUsername, + currentUsername: username, + }, + }); }, - { - command: 'help', - description: 'Shows a list of commands.', - paramaters: [], - usage: '/help', - scope: 'local', - action: params => { - // eslint-disable-line - const validCommands = this.commands.map(command => `/${command.command}`); - this.props.showNotice({ - message: `Valid commands: ${validCommands.sort().join(', ')}`, - level: 'info', - }); - }, + }, + { + command: 'help', + description: 'Shows a list of commands.', + parameters: [], + usage: '/help', + scope: 'local', + action: () => { + const validCommands = commands.map(command => `/${command.command}`); + showNotice({ + message: `Valid commands: ${validCommands.sort().join(', ')}`, + level: 'info', + }); }, - { - command: 'me', - description: 'Invoke virtual action', - paramaters: ['{action}'], - usage: '/me {action}', - scope: 'global', - action: params => { - // eslint-disable-line - const actionMessage = params.join(' '); - if (!actionMessage.trim().length) { - return false; - } - - this.props.sendEncryptedMessage({ - type: 'USER_ACTION', - payload: { - action: actionMessage, - }, - }); - }, + }, + { + command: 'me', + description: 'Invoke virtual action', + parameters: ['{action}'], + usage: '/me {action}', + scope: 'global', + action: params => { + const actionMessage = params.join(' '); + if (!actionMessage.trim().length) { + return false; + } + + sendEncryptedMessage({ + type: 'USER_ACTION', + payload: { + action: actionMessage, + }, + }); }, - { - command: 'clear', - description: 'Clears the chat screen', - paramaters: [], - usage: '/clear', - scope: 'local', - action: (params = null) => { - // eslint-disable-line - this.props.clearActivities(); - }, + }, + { + command: 'clear', + description: 'Clears the chat screen', + parameters: [], + usage: '/clear', + scope: 'local', + action: () => { + clearActivities(); }, - ]; - } - - componentDidMount() { - if (!hasTouchSupport) { - // Disable for now due to vary issues: - // Paste not working, shift+enter line breaks - // autosize(this.textInput); - this.textInput.addEventListener('autosize:resized', () => { - this.props.scrollToBottom(); - }); - } - } - - componentWillReceiveProps(nextProps) { - if (nextProps.focusChat) { - if (!getSelectedText()) { - // Don't focus for now, evaluate UX benfits - // this.textInput.focus() - } - } - } + }, + ]; - componentDidUpdate(nextProps, nextState) { - if (!nextState.message.trim().length) { - // autosize.update(this.textInput) - } - } - - handleKeyUp(e) { + const handleKeyUp = e => { if (e.key === 'Shift') { - this.setState({ - shiftKeyDown: false, - }); + setShiftKeyDown(false); } - } + }; - handleKeyPress(e) { + const handleKeyPress = e => { if (e.key === 'Shift') { - this.setState({ - shiftKeyDown: true, - }); + setShiftKeyDown(true); } - // Fix when autosize is enabled - line breaks require shift+enter twice - if (e.key === 'Enter' && !hasTouchSupport && !this.state.shiftKeyDown) { + if (e.key === 'Enter' && !hasTouchSupport && !shiftKeyDown) { e.preventDefault(); - if (this.canSend()) { - this.sendMessage(); + if (canSend) { + sendMessage(); } else { - this.setState({ - message: '', - }); + setMessage(''); } } - } + }; - executeCommand(command) { - const commandToExecute = this.commands.find(cmnd => cmnd.command === command.command); + const executeCommand = command => { + const commandToExecute = commands.find(cmnd => cmnd.command === command.command); if (commandToExecute) { const { params } = command; @@ -175,19 +138,20 @@ export class Chat extends Component { } return null; - } + }; - handleSendClick() { - this.sendMessage.bind(this); - this.textInput.focus(); - } + const handleSendClick = evt => { + evt.preventDefault(); + sendMessage(); + textInputRef.current.focus(); + }; - handleFormSubmit(evt) { + const handleFormSubmit = evt => { evt.preventDefault(); - this.sendMessage(); - } + sendMessage(); + }; - parseCommand(message) { + const parseCommand = message => { const commandTrigger = { command: null, params: [], @@ -207,23 +171,22 @@ export class Chat extends Component { } return false; - } + }; - sendMessage() { - if (!this.canSend()) { + const sendMessage = () => { + if (!canSend) { return; } - const { message } = this.state; - const isCommand = this.parseCommand(message); + const isCommand = parseCommand(message); if (isCommand) { - const res = this.executeCommand(isCommand); + const res = executeCommand(isCommand); if (res === false) { return; } } else { - this.props.sendEncryptedMessage({ + sendEncryptedMessage({ type: 'TEXT_MESSAGE', payload: { text: message, @@ -232,55 +195,41 @@ export class Chat extends Component { }); } - this.setState({ - message: '', - }); - } - - handleInputChange(evt) { - this.setState({ - message: evt.target.value, - }); - } - - canSend() { - return this.state.message.trim().length; - } - - render() { - const touchSupport = this.state.touchSupport; - - return ( -
-