|
|
// app.tsx
// Copyright (C) 2020 Dwayne Harris
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import React, { FC, useState, useEffect } from 'react' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faShieldAlt, faSpinner } from '@fortawesome/free-solid-svg-icons' import { Communicator, Post, Theme } from '../../../communicator'
import '../../../styles/default.css'
const prompts = [ "What's going on?", 'What it do?', "What's happening?", "How's your day going?" ]
interface Props { communicator: Communicator }
const App: FC<Props> = ({ communicator }) => { const maxCharacters = 256 const [content, setContent] = useState('') const [cover, setCover] = useState('') const [posting, setPosting] = useState(false) const [parent, setParent] = useState<Post | null>(null)
const [theme, setTheme] = useState<Theme>({ primary: '#333', primaryAlternate: '#fff', secondary: '#777', backgroundPrimary: '#fff', backgroundSecondary: '#ccc', text: '#555', red: '#ff1a1a', green: '#00802b', blue: '#005ce6', })
const charactersLeft = maxCharacters - content.length const showCharactersLeft = charactersLeft < (maxCharacters / 2) const buttonDisabled = charactersLeft < 1 || content.length === 0 || posting const showCharactersDanger = charactersLeft < (maxCharacters * 0.1)
const buttonText = parent ? 'Reply!' : 'Post!'
useEffect(() => { const init = async () => { try { const response = await communicator.init() if (response!.parent) setParent(response!.parent) if (response!.theme) setTheme(response!.theme)
await communicator.setHeight(document.body.offsetHeight) } catch (err) {} } init() }, [])
const post = async () => { if (!content.length) return
try { setPosting(true) await communicator.post({ text: content, cover, visible: true, }) setContent('') setCover('') } catch (err) {}
setPosting(false) }
return ( <div style={{ backgroundColor: theme.backgroundPrimary }}> <div className="control"> <textarea style={{ backgroundColor: theme.backgroundSecondary, borderColor: theme.secondary, color: theme.text }} placeholder={prompts[Math.floor(Math.random() * prompts.length)]} value={content} onChange={(e) => setContent(e.target.value)} /> </div>
<div className="field"> <div className="control-container"> <div className="icon" style={{ backgroundColor: theme.primary, color: theme.primaryAlternate }}> <FontAwesomeIcon icon={faShieldAlt} /> </div> <div className="control"> <input style={{ backgroundColor: theme.backgroundSecondary, borderColor: theme.secondary, color: theme.text }} type="text" placeholder="Cover Text" value={cover} onChange={(e) => setCover(e.target.value)} /> </div> </div> </div>
<nav className="level"> <div> {showCharactersLeft ? <p style={{ color: showCharactersDanger ? theme.red : theme.text }}>{charactersLeft} Chars Left</p> : <p> </p>} </div>
<div> <button style={{ backgroundColor: theme.primary, color: theme.primaryAlternate }} onClick={() => post()} disabled={buttonDisabled}> {posting ? <FontAwesomeIcon icon={faSpinner} spin /> : <span>{buttonText}</span>} </button> </div> </nav> </div> ) }
export default App
|