[ABANDONDED] Set of "apps" for the Flexor social network.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

105 lines
3.3 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. import React, { FC, useState, useEffect } from 'react'
  2. import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
  3. import { faEyeSlash } from '@fortawesome/free-solid-svg-icons'
  4. import { Communicator } from '../../../communicator'
  5. import classNames from 'classnames'
  6. import { ClassDictionary, Post } from '../../../types'
  7. import '../../../styles/default.scss'
  8. interface Props {
  9. communicator: Communicator
  10. }
  11. const App: FC<Props> = ({ communicator }) => {
  12. const maxCharacters = 256
  13. const [content, setContent] = useState('')
  14. const [cover, setCover] = useState('')
  15. const [posting, setPosting] = useState(false)
  16. const [parent, setParent] = useState<Post | null>(null)
  17. const charactersLeft = maxCharacters - content.length
  18. const showCharactersLeft = charactersLeft < (maxCharacters / 2)
  19. const buttonDisabled = charactersLeft < 1 || content.length === 0 || posting
  20. const showCharactersStyle: ClassDictionary = {
  21. 'has-text-danger': charactersLeft < (maxCharacters * 0.1),
  22. }
  23. const buttonStyle: ClassDictionary = {
  24. 'button': true,
  25. 'is-primary': true,
  26. 'is-loading': posting,
  27. }
  28. const buttonText = parent ? 'Reply!' : 'Post!'
  29. useEffect(() => {
  30. const init = async () => {
  31. try {
  32. const response = await communicator.init()
  33. if (response!.parent) setParent(response!.parent)
  34. await communicator.setHeight(document.body.offsetHeight)
  35. } catch (err) {
  36. console.error('App Component: ', err)
  37. }
  38. }
  39. init()
  40. }, [])
  41. const post = async () => {
  42. if (!content.length) return
  43. try {
  44. setPosting(true)
  45. await communicator.post({
  46. text: content,
  47. cover,
  48. visible: true,
  49. })
  50. setContent('')
  51. setCover('')
  52. } catch (err) {
  53. console.error('App Component: ', err)
  54. }
  55. setPosting(false)
  56. }
  57. return (
  58. <div>
  59. <div className="field">
  60. <div className="control">
  61. <textarea className="textarea" placeholder="What it do?" value={content} onChange={(e) => setContent(e.target.value)} />
  62. </div>
  63. </div>
  64. <div className="field">
  65. <p className="control has-icons-left">
  66. <input className="input" type="text" placeholder="Cover Text" value={cover} onChange={(e) => setCover(e.target.value)} />
  67. <span className="icon is-small is-left">
  68. <FontAwesomeIcon icon={faEyeSlash} />
  69. </span>
  70. </p>
  71. </div>
  72. <nav className="level">
  73. <div className="level-left">
  74. <div className="level-item">
  75. {showCharactersLeft && <p className={classNames(showCharactersStyle)}>{charactersLeft} Chars Left</p>}
  76. </div>
  77. </div>
  78. <div className="level-right">
  79. <div className="level-item">
  80. <button className={classNames(buttonStyle)} onClick={() => post()} disabled={buttonDisabled}>{buttonText}</button>
  81. </div>
  82. </div>
  83. </nav>
  84. </div>
  85. )
  86. }
  87. export default App