[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.

133 lines
4.6 KiB

5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
4 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
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
  1. // app.tsx
  2. // Copyright (C) 2020 Dwayne Harris
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation, either version 3 of the License, or
  6. // (at your option) any later version.
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU General Public License for more details.
  11. // You should have received a copy of the GNU General Public License
  12. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  13. import React, { FC, useState, useEffect } from 'react'
  14. import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
  15. import { faShieldAlt, faSpinner } from '@fortawesome/free-solid-svg-icons'
  16. import { Communicator, Post, Theme } from '../../../communicator'
  17. import '../../../styles/default.css'
  18. const prompts = [
  19. "What's going on?",
  20. 'What it do?',
  21. "What's happening?",
  22. "How's your day going?"
  23. ]
  24. interface Props {
  25. communicator: Communicator
  26. }
  27. const App: FC<Props> = ({ communicator }) => {
  28. const maxCharacters = 256
  29. const [content, setContent] = useState('')
  30. const [cover, setCover] = useState('')
  31. const [posting, setPosting] = useState(false)
  32. const [parent, setParent] = useState<Post | null>(null)
  33. const [theme, setTheme] = useState<Theme>({
  34. primary: '#333',
  35. primaryAlternate: '#fff',
  36. secondary: '#777',
  37. backgroundPrimary: '#fff',
  38. backgroundSecondary: '#ccc',
  39. text: '#555',
  40. red: '#ff1a1a',
  41. green: '#00802b',
  42. blue: '#005ce6',
  43. })
  44. const charactersLeft = maxCharacters - content.length
  45. const showCharactersLeft = charactersLeft < (maxCharacters / 2)
  46. const buttonDisabled = charactersLeft < 1 || content.length === 0 || posting
  47. const showCharactersDanger = charactersLeft < (maxCharacters * 0.1)
  48. const buttonText = parent ? 'Reply!' : 'Post!'
  49. useEffect(() => {
  50. const init = async () => {
  51. try {
  52. const response = await communicator.init()
  53. if (response!.parent) setParent(response!.parent)
  54. if (response!.theme) setTheme(response!.theme)
  55. await communicator.setHeight(document.body.offsetHeight)
  56. } catch (err) {}
  57. }
  58. init()
  59. }, [])
  60. const post = async () => {
  61. if (!content.length) return
  62. try {
  63. setPosting(true)
  64. await communicator.post({
  65. text: content,
  66. cover,
  67. visible: true,
  68. })
  69. setContent('')
  70. setCover('')
  71. } catch (err) {}
  72. setPosting(false)
  73. }
  74. return (
  75. <div style={{ backgroundColor: theme.backgroundPrimary }}>
  76. <div className="control">
  77. <textarea
  78. style={{ backgroundColor: theme.backgroundSecondary, borderColor: theme.secondary, color: theme.text }}
  79. placeholder={prompts[Math.floor(Math.random() * prompts.length)]}
  80. value={content}
  81. onChange={(e) => setContent(e.target.value)} />
  82. </div>
  83. <div className="field">
  84. <div className="control-container">
  85. <div className="icon" style={{ backgroundColor: theme.primary, color: theme.primaryAlternate }}>
  86. <FontAwesomeIcon icon={faShieldAlt} />
  87. </div>
  88. <div className="control">
  89. <input
  90. style={{ backgroundColor: theme.backgroundSecondary, borderColor: theme.secondary, color: theme.text }}
  91. type="text"
  92. placeholder="Cover Text"
  93. value={cover}
  94. onChange={(e) => setCover(e.target.value)} />
  95. </div>
  96. </div>
  97. </div>
  98. <nav className="level">
  99. <div>
  100. {showCharactersLeft ? <p style={{ color: showCharactersDanger ? theme.red : theme.text }}>{charactersLeft} Chars Left</p> : <p>&nbsp;</p>}
  101. </div>
  102. <div>
  103. <button style={{ backgroundColor: theme.primary, color: theme.primaryAlternate }} onClick={() => post()} disabled={buttonDisabled}>
  104. {posting ? <FontAwesomeIcon icon={faSpinner} spin /> : <span>{buttonText}</span>}
  105. </button>
  106. </div>
  107. </nav>
  108. </div>
  109. )
  110. }
  111. export default App