Initial commit. (all done by @madr)

This commit is contained in:
Tomáš Mládek 2018-10-17 13:22:43 +02:00
commit 64f4fcc83e
7 changed files with 394 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
outchat.db

43
api.php Normal file
View file

@ -0,0 +1,43 @@
<?php
$database = new SQLite3('outchat.db');
$action = $_GET['action'];
if($action === 'getMessages'){
$timestamp = $database->escapeString(htmlspecialchars($_GET['timestamp']));
$timestamp = ($timestamp == 0) ? strtotime('-6 hours') : $timestamp;
$results = $database->query('SELECT * FROM messages WHERE timestamp > '.$timestamp);
$messageArray = [];
while($row = $results->fetchArray(SQLITE3_ASSOC)) {
$row['datetime'] = date('d/m H:i', $row['timestamp']);
$image_search = preg_match('/(http|https):\/\/[^ ]+(\.gif|\.jpg|\.jpeg|\.png)/', $row['text'], $out);
if($image_search > 0){
$row['text_processed'] = str_replace($out[0], '<p><img src="'.$out[0].'" /></p>', $row['text']);
} else {
$row['text_processed'] = $row['text'];
}
$messageArray[] = $row;
}
echo json_encode($messageArray);
}
if($action === 'createMessage'){
$timestamp = time();
$name = $database->escapeString(htmlspecialchars($_POST['name']));
$text = $database->escapeString(htmlspecialchars($_POST['text']));
/*
$payload = file_get_contents('php://input');
$data = json_decode($payload);
var_dump($data);
*/
$database->query('INSERT INTO messages (name, text, timestamp) VALUES ("'.$name.'", "'.$text.'", "'.$timestamp.'")');
}
?>

39
helpers.js Normal file
View file

@ -0,0 +1,39 @@
function htmlToElements(html) {
const template = document.createElement('template')
template.innerHTML = html
return template.content.childNodes
}
function hashCode(str) { // java String#hashCode
var hash = 0;
for (var i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
return hash;
}
function intToRGB(i){
const c = (i & 0x00FFFFFF)
.toString(16)
.toUpperCase();
return "00000".substring(0, 6 - c.length) + c;
}
function getCookie(name) {
const value = "; " + document.cookie;
const parts = value.split("; " + name + "=");
if (parts.length == 2) return parts.pop().split(";").shift();
}
function nl2br(str, is_xhtml){
if (typeof str === 'undefined' || str === null) {
return '';
}
var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '<br />' : '<br>';
return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2');
}
function scrollWindowDown(){
window.scrollTo(0, document.body.scrollHeight)
}

39
index.php Normal file
View file

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>outposts</title>
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
<link rel="stylesheet" href="main.css">
</head>
<body>
<?php
if(!isset($_COOKIE['outchat_name'])){
echo '
<div class="modal">
<form action="" method="post" class="modal__form">
<input type="text" name="name" placeholder="name" minLength="3" maxLength="20" class="modal__form-input">
<input type="submit" value="»" class="modal__form-submit">
</form>
</div>
';
}
?>
<div class="chat">
</div>
<form method="post" action="api.php?action=createMessage" class="form">
<textarea name="text" class="form__input-message" placeholder="message"></textarea>
<input type="hidden" name="name" value="kent">
<input type="submit" value="»" class="form__input-submit">
</form>
<script src="helpers.js"></script>
<script src="main.js"></script>
</body>
</html>

153
main.css Normal file
View file

@ -0,0 +1,153 @@
* {
box-sizing: border-box;
}
html {
color: #fff;
background-color: #111;
font-family: Courier, Verdana;
font-size: 14px;
}
body {
margin: 0;
}
.chat {
width: 100%;
padding: 30px 30px 80px 30px;
position: relative;
overflow: auto;
}
.message {
width: 100%;
margin-bottom: 40px;
}
.message__info {
width: 100%;
margin-bottom: 5px;
line-height: 1;
display: flex;
align-items: flex-end;
}
.message__info-name {
font-weight: 700;
margin-right: 15px;
font-size: 18px;
line-height: .8;
}
.message__text {
position: relative;
white-space: pre-line;
}
.message__text p {
margin: 0;
}
.message__text img {
margin: 10px 0 0 0;
width: 100%;
max-width: 320px;
display: block;
height: auto;
}
.form {
left: 15px;
bottom: 15px;
width: calc(100% - 30px);
height: 60px;
background-color: #fff;
position: fixed;
display: flex;
}
.form__input-message {
padding: 20px;
width: calc(100% - 60px);
height: 100%;
border: 0;
outline: 0;
margin: 0;
font-size: 16px;
resize: none;
white-space: pre-line;
}
.form__input-submit {
right: 0;
top: 0;
width: 60px;
height: 60px;
font-size: 30px;
font-weight: 700;
outline: 0;
border: 0;
cursor: pointer;
position: absolute;
background: none;
}
.modal {
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 100;
background-color: #000;
position: fixed;
}
.modal__form {
width: 100%;
max-width: 600px;
height: 60px;
margin: 50px auto;
position: relative;
}
.modal__form-input {
padding: 0 90px 0 30px;
width: 100%;
height: 100%;
border: 0;
outline: 0;
font-size: 16px;
}
.modal__form-submit {
right: 0;
top: 0;
width: 60px;
height: 60px;
font-size: 30px;
font-weight: 700;
outline: 0;
border: 0;
cursor: pointer;
position: absolute;
background: none;
}
@media (max-width: 640px) {
.chat {
padding: 10px 10px 50px 10px;
}
.form {
left: 10px;
bottom: 10px;
width: calc(100% - 20px);
}
.message {
margin-bottom: 25px;
}
}

112
main.js Normal file
View file

@ -0,0 +1,112 @@
// modal form handle
if(document.querySelector('.modal__form-submit')){
document.querySelector('.modal__form-submit').addEventListener('click', function(e){
e.preventDefault()
const value = document.querySelector('.modal__form-input').value
if(value.length >= 3){
var date = new Date(Date.now())
date = date.setTime(date.getTime() + (90*24*60*60*1000))
date = new Date(date)
const expires = '; expires=' + date.toUTCString()
document.cookie = 'outchat_name=' + (value || '') + expires + '; path=/'
window.location.href = ''
}
})
}
document.querySelector('.form__input-message').addEventListener('keydown', function(e){
if(e.ctrlKey && e.keyCode == 13){
document.querySelector('.form__input-submit').click()
}
})
document.querySelector('.form__input-submit').addEventListener('click', function(e){
e.preventDefault()
const name = getCookie('outchat_name')
const text = document.querySelector('.form__input-message').value
document.querySelector('.form__input-message').value = ''
var formData = new FormData()
formData.append(name, text)
fetch('api.php?action=createMessage', {
method: 'post',
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: 'name='+name+'&text='+text
})
.then(function(data){
getMessages()
})
.catch(function(error){
console.log(error)
})
})
function getMessages(){
const timestamp = (document.querySelector('.chat').lastElementChild) ? document.querySelector('.chat').lastElementChild.getAttribute('data-timestamp') : 0
fetch('api.php?action=getMessages&timestamp='+timestamp)
.then(function(data){
return data.json()
})
.then(function(data){
if(data.length > 0){
if((window.scrollY + window.innerHeight) == document.body.scrollHeight){
setTimeout(function(){
scrollWindowDown()
}, 100)
}
for(message of data){
createMessageNode(message.name, message.text_processed, message.timestamp, message.datetime)
}
}
})
.catch(function(error){
console.log(error)
})
}
function createMessageNode(name, text, timestamp, datetime){
const elementMain = document.createElement('div', { class: 'message' })
const elementText = document.createElement('div', { class: 'message__text'})
const elementInfo = document.createElement('div', { class: 'message__info'})
const elementName = document.createElement('div', { id: 'message__info-name'})
const elementDatetime = document.createElement('div', { id: 'message__info-datetime'})
const contentName = document.createTextNode(name)
const contentDatetime = document.createTextNode('['+datetime+']')
//const contentText = document.createTextNode(text)
// element creation
elementMain.classList.add('message')
elementText.classList.add('message__text')
elementInfo.classList.add('message__info')
elementDatetime.classList.add('message__info-datetime')
elementName.classList.add('message__info-name')
// "hash" name color
elementName.style.color = "#"+intToRGB(hashCode(name))
// append everything to chat
elementName.appendChild(contentName)
elementDatetime.appendChild(contentDatetime)
elementText.innerHTML = text
elementInfo.appendChild(elementName)
elementInfo.appendChild(elementDatetime)
elementMain.appendChild(elementInfo)
elementMain.appendChild(elementText)
elementMain.setAttribute('data-timestamp', timestamp)
document.querySelector('.chat').appendChild(elementMain)
return true
}
getMessages()
setInterval(function(){
getMessages()
}, 2000)

7
outchat-ddl.sql Normal file
View file

@ -0,0 +1,7 @@
CREATE TABLE `messages` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`name` TEXT,
`text` TEXT,
`timestamp` INTEGER
);