Getting ready for ver. 1

This commit is contained in:
sorenpeter 2023-10-19 07:33:50 +02:00
parent bf5c678f66
commit 485416629d
22 changed files with 808 additions and 431 deletions

View file

@ -12,10 +12,16 @@ $viewDir = '/views/';
// Define your routes using regular expressions // Define your routes using regular expressions
// TODO: re-add auto detection of files in /views as routes
$routes = [ $routes = [
'/' => 'home.php', '/' => 'home.php',
'/admin' => 'admin.php', '/new' => 'new_twt.php',
'/about' => 'about.php', '/add' => 'add_feed.php',
'/following' => 'following.php',
'/refresh' => 'load_twt_files.php',
'/login' => 'login.php',
'/logout' => 'logout.php',
'/profile/([a-zA-Z0-9_-]+)' => 'profile.php', '/profile/([a-zA-Z0-9_-]+)' => 'profile.php',
'/conv/([a-zA-Z0-9]{7})' => 'conv.php', // matches only twtHash of exactly 7 alphanumeric characters '/conv/([a-zA-Z0-9]{7})' => 'conv.php', // matches only twtHash of exactly 7 alphanumeric characters
'/post/([a-zA-Z0-9]{7})' => 'post.php', // matches only twtHash of exactly 7 alphanumeric characters '/post/([a-zA-Z0-9]{7})' => 'post.php', // matches only twtHash of exactly 7 alphanumeric characters

View file

@ -24,10 +24,8 @@
class Slimdown { class Slimdown {
public static $rules = array ( public static $rules = array (
'/```(.*?)```/s' => self::class .'::code_parse', // code blocks '/```(.*?)```/s' => self::class .'::code_parse', // code blocks
//'/\n(#+)(.*)/' => self::class .'::header', // headers '/\n(#+)\s+(.*)/' => self::class .'::header', // headers
'/\n(#\s+)(.*)/' => self::class .'::header', // headers - only with a space between # and text, to avoid matching with `#hashtags` '/\!\[([^\[]*?)\]\(([^\)]+)\)/' => self::class .'::img', // images
//'/\!\[([^\[]+)\]\(([^\)]+)\)/' => self::class .'::img', // images
'/\!\[(.*?)\]\(([^\)]+)\)/' => self::class .'::img', // images 2
'/\[([^\[]+)\]\(([^\)]+)\)/' => self::class .'::link', // links '/\[([^\[]+)\]\(([^\)]+)\)/' => self::class .'::link', // links
'/(\*\*|__)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '<strong>\2</strong>', // bold '/(\*\*|__)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '<strong>\2</strong>', // bold
'/(\*|_)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '<em>\2</em>', // emphasis '/(\*|_)(?=(?:(?:[^`]*`[^`\r\n]*`)*[^`]*$))(?![^\/<]*>.*<\/.+>)(.*?)\1/' => '<em>\2</em>', // emphasis
@ -79,6 +77,7 @@ class Slimdown {
} }
if (! empty ($trimmed)) { if (! empty ($trimmed)) {
//return sprintf ("\n<p>%s</p>\n", $trimmed); //return sprintf ("\n<p>%s</p>\n", $trimmed);
return sprintf ("\n%s\n", $trimmed);
} }
return $trimmed; return $trimmed;
} }

View file

@ -13,11 +13,6 @@ if(isset($_POST['submit_pass']) && $_POST['pass'])
} }
else else
{ {
$error="Incorrect Pssword"; $error="Incorrect Password";
} }
} }
if(isset($_POST['page_logout']))
{
unset($_SESSION['password']);
}

View file

@ -124,7 +124,8 @@ function replaceMentionsFromTwt(string $twtString): string {
// Example output: Hello <a href="?url=https://eapl.mx/twtxt.txt">@eapl.mx@eapl.mx/twtxt.txt</a>, how are you? <a href="?url=https://server.com/something/twtxt.txt">@nick@server.com/something/twtxt.txt</a> // Example output: Hello <a href="?url=https://eapl.mx/twtxt.txt">@eapl.mx@eapl.mx/twtxt.txt</a>, how are you? <a href="?url=https://server.com/something/twtxt.txt">@nick@server.com/something/twtxt.txt</a>
$pattern = '/@<([^ ]+)\s([^>]+)>/'; $pattern = '/@<([^ ]+)\s([^>]+)>/';
$replacement = '<a href="?url=$2">@$1</a>'; //$replacement = '<a href="/?url=$2">@$1</a>';
$replacement = '<a href="/?twts=$2">@$1</a>';
#$twtString = '@<nick https://eapl.mx/twtxt.txt>'; #$twtString = '@<nick https://eapl.mx/twtxt.txt>';
#$pattern = '/@<([^ ]+) ([^>]+)>/'; #$pattern = '/@<([^ ]+) ([^>]+)>/';
#$replacement = '@$1'; #$replacement = '@$1';
@ -137,6 +138,10 @@ function replaceMentionsFromTwt(string $twtString): string {
} }
function replaceLinksFromTwt(string $twtString) { function replaceLinksFromTwt(string $twtString) {
// TODO: Make this NOT match with `inline code` to avoid links in code-snippets
// 1. Look into how yarnd handles this
// Regular expression pattern to match URLs // Regular expression pattern to match URLs
$pattern = '/(?<!\S)(\b(https?|ftp|gemini|spartan|gopher):\/\/\S+|\b(?!:\/\/)\w+(?:\.\w+)+(?:\/\S+)?)(?!\S)/'; $pattern = '/(?<!\S)(\b(https?|ftp|gemini|spartan|gopher):\/\/\S+|\b(?!:\/\/)\w+(?:\.\w+)+(?:\/\S+)?)(?!\S)/';
@ -343,10 +348,11 @@ function getTwtsFromTwtxtString($url) {
// For some reason I was having trouble finding this nomenclature // For some reason I was having trouble finding this nomenclature
// that's why I leave the UTF-8 representation for future reference // that's why I leave the UTF-8 representation for future reference
$twtContent = str_replace("\u{2028}", "\n<br>\n", $twtContent); $twtContent = str_replace("\u{2028}", "\n<br>\n", $twtContent);
$twtContent = replaceLinksFromTwt($twtContent);
//$twtContent = replaceMarkdownLinksFromTwt($twtContent); //$twtContent = replaceMarkdownLinksFromTwt($twtContent);
//$twtContent = replaceImagesFromTwt($twtContent); //$twtContent = replaceImagesFromTwt($twtContent);
$twtContent = Slimdown::render($twtContent); $twtContent = Slimdown::render($twtContent);
$twtContent = replaceLinksFromTwt($twtContent); // TODO:
// Get and remote the hash // Get and remote the hash
$hash = getReplyHashFromTwt($twtContent); $hash = getReplyHashFromTwt($twtContent);
@ -355,7 +361,7 @@ function getTwtsFromTwtxtString($url) {
} }
// TODO: Make ?tag= filtering feature // TODO: Make ?tag= filtering feature
$twtContent = replaceTagsFromTwt($twtContent); //$twtContent = replaceTagsFromTwt($twtContent);
// TODO: Get mentions // TODO: Get mentions
$mentions = getMentionsFromTwt($twtContent); $mentions = getMentionsFromTwt($twtContent);

View file

@ -17,7 +17,7 @@ declare(strict_types=1);
# hash(string) = # hash(string) =
# #
require_once("libs/session.php"); // TODO: Move all to base.php require_once("libs/session.php");
require_once('libs/twtxt.php'); require_once('libs/twtxt.php');
require_once('libs/hash.php'); require_once('libs/hash.php');
require_once('libs/Slimdown.php'); require_once('libs/Slimdown.php');
@ -29,6 +29,8 @@ const TWTS_PER_PAGE = 50;
$config = parse_ini_file('private/config.ini'); $config = parse_ini_file('private/config.ini');
//$url = $config['public_txt_url']; //$url = $config['public_txt_url'];
// TODO: Take the title from the config.ini
$title = "Timeline"; // Fallback, should be set in all views
// HACKED by sp@darch.dk // HACKED by sp@darch.dk
if(!empty($_GET['list'])) { if(!empty($_GET['list'])) {

View file

@ -1,3 +1,8 @@
</main>
<footer><center><small> <footer><center><small>
&copy; 2023 Søren Peter Mørch &copy; 2023 Søren Peter Mørch
</small></center></footer> </small></center></footer>
</body>
</html>

View file

@ -1,26 +1,38 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css">
<link rel="stylesheet" type="text/css" href="/style.css">
<title><?= $title ?></title>
</head>
<body>
<header> <header>
<p>
🧶 <a href="/">Timeline</a> for
<a href="http://localhost:8000/?twts=http://darch.dk/twtxt.txt">sorenpeter</a>@darch.dk
(<a href="http://localhost:8000/twtxt.txt">twtxt.txt</a>)
</p>
<nav> <nav>
<ul> <!-- TODO: make automatic via PHP and show avatar as well -->
<li>🧶 <a href="/">Timeline</a> for
<a href="http://localhost:8000/?twts=http://darch.dk/twtxt.txt">sorenpeter</a>@darch.dk</li> <!-- TODO: make automatic via PHP and show avatar as well -->
<li><?php include 'partials/listSelect.php'; ?></li>
</ul>
<ul class="secondary"> <ul class="secondary">
<li><a href="load_twt_files.php?url=<?= $url ?>">Refresh</a></li> <li><a href="/refresh?url=<?= $url ?>">Refresh</a></li>
<li><a href="/following">Following <?php // echo count($twtFollowingList); ?></a></li>
<?php //if ($validSession) { // TODO: Make login seqcure ?> <?php //if ($validSession) { // TODO: Make login seqcure ?>
<?php if( isset($_SESSION['password'])) { <?php if( isset($_SESSION['password'])) { /*
if($_SESSION['password']=="$password") { // Hacky login ?> if($_SESSION['password']=="$password") {*/ // Hacky login ?>
<li><a href="new_twt.php">New post</a></li> <!-- <li><a href="/new">New post</a></li> -->
<li><a href="follow.php">Add feed</a></li> <li><a href="/add">Add feed</a></li>
<li><a href="/admin">Settings</a></li> <!-- <li><a href="/admin">Settings</a></li> -->
<li><form method="post" action="" id="logout_form"> <li><a href="/logout">Log Out</a></li>
<input type="submit" name="page_logout" value="Log out" class="link-btn"> <?php /*}*/ } else { ?>
</form> <li><a href="/login">Log in</a></li>
</li>
<?php } } else { ?>
<li><a href="login.php">Log in</a></li>
<?php } ?> <?php } ?>
<li><a href="following.php">Following <?php echo count($twtFollowingList); ?> feeds</a></li> <!-- <li><?php //include 'partials/listSelect.php'; ?></li> -->
</ul> </ul>
</nav> </nav>
</header> </header>
<main>

View file

@ -14,28 +14,40 @@ $profile = getTwtsFromTwtxtString($url);
<img class="avatar" src="<?= $profile->avatar ?>" alt="" loading="lazy"> <img class="avatar" src="<?= $profile->avatar ?>" alt="" loading="lazy">
</a> </a>
<section> <div>
<a href="<?= $profile->mainURL ?>" class="author"> <a href="<?= $profile->mainURL ?>" class="author">
<strong><?= $profile->nick ?></strong>@<?= parse_url($profile->mainURL, PHP_URL_HOST); ?> <strong><?= $profile->nick ?></strong>@<?= parse_url($profile->mainURL, PHP_URL_HOST); ?>
</a> </a>
<blockquote><?= $profile->description ?></blockquote> <p><?= $profile->description ?></p>
</section>
<!-- <aside>
<small> <small>
<a href="https://yarn.social" class="button">How to follow...</a> <a href="">Posts</a> |
<a href="">Replies</a> |
<a href="">Gallery</a> |
<!-- <span class="right"> -->
<a href="following.php">Following <?php echo count($twtFollowingList); ?></a> |
<a target="_blank" href="<?= $profile->mainURL ?>"></i>twtxt.txt</a> |
<a href="https://yarn.social">How to follow</a>
<!-- </span> -->
</small> </small>
</aside> -->
</div>
</div> </div>
<nav class="profile"> <!-- <nav>
<ul> <ul>
<li><a href="">Posts</a></li> <li><a href="">Posts</a></li>
<li><a href="">Replies</a></li> <li><a href="">Replies</a></li>
<li><a href="">Gallery</a></li> <li><a href="">Gallery</a></li>
</ul>
<ul class="right">
<li><a href="https://yarn.social" class="button">How to follow...</a></li>
<li><a href="following.php">Following <?php echo count($twtFollowingList); ?></a></li>
<li><a target="_blank" href="<?= $profile->mainURL ?>"></i>twtxt.txt</a></li> <li><a target="_blank" href="<?= $profile->mainURL ?>"></i>twtxt.txt</a></li>
</ul> </ul>
</nav> </nav> -->

View file

@ -8,11 +8,11 @@
<?php foreach ($twts as $twt) { ?> <?php foreach ($twts as $twt) { ?>
<article class="post-entry"> <article class="post-entry">
<a href="?twts=<?= $twt->mainURL ?>"> <a href="/?twts=<?= $twt->mainURL ?>">
<img src='<?= $twt->avatar ?>' class="avatar" onerror="this.onerror=null;this.src='imgs/image_not_found.png';"> <img src='<?= $twt->avatar ?>' class="avatar" onerror="this.onerror=null;this.src='imgs/image_not_found.png';">
</a> </a>
<div> <div>
<a href="?twts=<?= $twt->mainURL ?>" class="author"> <a href="/?twts=<?= $twt->mainURL ?>" class="author">
<strong><?= $twt->nick ?></strong>@<?= parse_url($twt->mainURL, PHP_URL_HOST); ?> <strong><?= $twt->nick ?></strong>@<?= parse_url($twt->mainURL, PHP_URL_HOST); ?>
</a> </a>
@ -27,16 +27,24 @@
</div> </div>
<small> <small>
<?php if($twt->replyToHash) { ?> <?php
<!-- <a href="?hash=<?= $twt->replyToHash?>">Conversation</a> | -->
<a href="/conv/<?= $twt->replyToHash?>">Conversation: #<?= $twt->replyToHash?></a> |
<?php } ?>
<!-- TODO: make depending on session or nor -->
<a href="new_twt.php?hash=<?= $twt->hash ?>">Reply</a>
(<a href="new_twt.php?hash=<?= $twt->hash ?>">via email</a>) <!-- TODO: mailto-link -->
<!-- <a href='/?hash=<?= $twt->hash ?>' class="right"><span title="<?= $twt->fullDate ?> "><?= $twt->displayDate ?></span></a> -->
<a href='/post/<?= $twt->hash ?>' class="right"><span title="<?= $twt->fullDate ?> "><?= $twt->displayDate ?></span></a>
if($twt->replyToHash) {
echo 'In reply to: <a href="/conv/'.$twt->replyToHash.'">#'.$twt->replyToHash.'</a>';
//echo '<a href="/conv/'.$twt->replyToHash.'">Convesation</a>';
}
if ($twt->replyToHash && isset($_SESSION['password'])) {
echo ' | ';
}
if (isset($_SESSION['password'])) {
echo '<a href="/new?hash='.$twt->hash.'">Reply</a>';
}
?>
<!-- (<a href="new_twt.php?hash=<?= $twt->hash ?>">via email</a>) TODO: mailto-link -->
<a href='/post/<?= $twt->hash ?>' class="right"><span title="<?= $twt->fullDate ?> "><?= $twt->displayDate ?></span></a>
</small> </small>
</div> </div>
</article> </article>

269
style.css
View file

@ -1,177 +1,89 @@
* { /* Simple CSS overwrites */
/* border: thin solid pink;*/
::backdrop, :root {
--sans-font: -apple-system,BlinkMacSystemFont,"Avenir Next",Avenir,"Nimbus Sans L",Roboto,"Noto Sans","Segoe UI",Arial,Helvetica,"Helvetica Neue",sans-serif;
--mono-font: Consolas,Menlo,Monaco,"Andale Mono","Ubuntu Mono",monospace;
--standard-border-radius: 0.5rem;
--bg: #fff;
--accent-bg: #f5f7ff;
--text: #212121;
--text-light: #585858;
--border: #d8dae1; /*#898EA4;*/
--accent: #0d47a1;
--code: #d81b60;
--preformatted: #444;
--marked: #ffdd33;
--disabled: #efefef;
} }
/* from PaperMod: https://github.com/adityatelange/hugo-PaperMod/tree/54a3c6073518005182f3c3250ddb7e8c0cacd7ad/assets/css */ body > header {
:root { padding-bottom: 0;
--gap: 1rem;
--content-gap: 20px;
--nav-width: 1024px;
--main-width: 720px;
--header-height: 60px;
--footer-height: 60px;
--radius: 8px;
--theme: rgb(255, 255, 255);
--entry: rgb(255, 255, 255);
--primary: rgb(30, 30, 30);
--secondary: rgb(108, 108, 108);
--tertiary: rgb(214, 214, 214);
--content: rgb(31, 31, 31);
--hljs-bg: rgb(28, 29, 33);
--code-bg: rgb(245, 245, 245);
--border: rgb(238, 238, 238);
} }
body { header > nav a {
background-color: var(--code-bg); /* border: none;*/
font-family: sans-serif;
/* max-width: 700px;
margin: 1rem auto; */
line-height: 1.25;
} }
main {
max-width: 700px;
margin: 1rem auto;
}
a, button, body, h1, h2, h3, h4, h5, h6 { /* Timeline Style */
color: var(--primary);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
/* == Forms (from https://adi.tilde.institute/default.css/) ==================== */
form {
align-content: center;
display: flex;
}
label {
display: block;
font-size: small;
}
input, textarea, select {
box-sizing: border-box;
display: inline-block;
/* margin: .5ex 0 1ex 0;*/
margin-top: -0.5rem;
padding: 1ex .5rem;
border: thin solid var(--border);
border-radius: var(--radius);
/*width: 100%;*/
font-size: 1em;
background-color: var(--entry);
color: var(--primary);
}
input[type="text"],
input[type="file"] {
flex-grow: 1;
margin-right: 0.5rem;
}
input[type=checkbox], input[type=radio] {
display: inline;
width: auto;
}
textarea {
font-family: inherit;
width: 100%;
background-color: var(--input-box);
}
input[type="submit"],
a.button, button {
background-color: var(--pod-color);
border-radius: var(--radius);
border: thin solid var(--pod-color);
color: var(--button-text);
display: block;
/* margin-top: -1rem;*/
font-size: 1em;
padding: 1ex 1rem;
text-align: center;
text-decoration: none;
}
button.primary {
width: 100%;
margin: 1rem 0;
}
fieldset {
border: thin solid var(--border-color);
border-radius: var(--radius);
margin: 0.5rem 0;
padding: 0.5rem 0.75rem;
}
/* --- */
.right { .right {
float: right; float: right;
margin-right: 0.25rem;
} }
hr { /*body {
background: var(--border); font-family: sans-serif;
border: 0; line-height: 1.25;
height: 1px;
width: 100%;
} }
*/
header { /*main {
margin-bottom: 2rem; max-width: 700px;
border-bottom: thin solid var(--tertiary); margin: 1rem auto;
} }
*/
nav { /*nav {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: space-between; justify-content: space-between;
max-width: calc(var(--nav-width) + var(--gap) * 2); max-width: calc(var(--nav-width) + var(--gap) * 2);
margin-inline-start: auto; margin-inline-start: auto;
margin-inline-end: auto; margin-inline-end: auto;
} }*/
nav ul { /*nav ul {
width: 100%; width: 100%;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
padding-left: 0.5rem; padding-left: 0.5rem;
margin: 0.25rem 0rem; margin: 0.25rem 0rem;
}*/
header p a,
header p a:visited {
font-weight: bold;
color: var(--text);
text-decoration: none;
} }
nav ul.secondary { nav ul.secondary {
padding: 0 0.75rem; /* padding: 0 0.75rem;*/
font-size: small; font-size: small;
} }
/* /*nav ul li {
nav ul.secondary a {
text-decoration: underline;
font-weight: normal;
}
*/
nav ul li {
display: inline-block; display: inline-block;
list-style: none; list-style: none;
} }*/
nav a { header a {
text-decoration: none; /* text-decoration: none;*/
font-weight: bold; /* font-weight: bold;*/
line-height: 1.5; /* line-height: 1.5;*/
} }
nav form { nav form {
@ -185,9 +97,8 @@ nav .link-btn {
margin: 0; margin: 0;
padding: 0; padding: 0;
width: 100%; width: 100%;
color: var(--primary); color: var(--text);
font-weight: bold; font-weight: bold;
/*text-decoration: underline;*/
border-radius: 0; border-radius: 0;
} }
@ -199,29 +110,29 @@ img {
} }
img.avatar { img.avatar {
height: 48px; height: 2.5rem;
width: 48px; width: 2.5rem;
object-fit: cover; object-fit: cover;
} }
a.author { a.author {
text-decoration: none; text-decoration: none;
color: var(--primary); color: var(--text);
} }
/* === PROFILE === */
.profile { .profile {
padding: 0 1rem; padding: 0 1rem;
display: grid; display: grid;
/* grid-template-columns: 4rem 3fr 1fr;*/
grid-template-columns: 4rem 1fr; grid-template-columns: 4rem 1fr;
grid-gap: 1rem; grid-gap: 1rem;
margin: 1rem 0; margin-bottom: 2rem;
} }
.profile img.avatar { .profile img.avatar {
width: 4rem; width: 4rem;
height: 4rem; height: 4rem;
/* border-radius: 100%;*/
} }
.profile .author { .profile .author {
@ -229,60 +140,36 @@ a.author {
} }
.profile blockquote { .profile p {
margin: 0.5rem 0; margin: 0.5rem 0;
color: var(--secondary); color: var(--text-light);
}
/*.profile nav a {
font-size: small;
text-decoration: underline;
}*/
nav.profile {
padding: 0;
/* display: flex;*/
/* justify-content: space-around;*/
}
nav.profile a {
/* font-size: small;*/
/* text-decoration: underline;*/
/* border: thin solid var(--border);
border-radius: var(--radius);
background-color: var(--entry);
padding: 0.5rem 1rem;*/
margin: 0 0.5rem;
} }
/* === TIMELINE === */
article { article {
background-color: var(--entry); color: var(--text-light);
color: var(--secondary);
border-radius: 0.25rem;
border: thin solid var(--border);
margin: 0.5rem; margin: 0.5rem;
padding: 0.5rem; padding: 0.5rem;
} }
article.post-entry { article.post-entry {
display: grid; display: grid;
grid-gap: var(--gap); grid-gap: 1rem;
grid-template-columns: 48px auto; grid-template-columns: 2.5rem auto;
} }
article .twt-msg { article .twt-msg {
padding: 0.5rem 0; padding: 0.5rem 0;
} }
article .twt-msg a{ article .twt-msg a {
text-decoration: underline; text-decoration: underline;
} }
article .twt-msg > blockquote { article .twt-msg > blockquote {
margin: 0; margin: 0;
border-left: thick solid var(--border); border-left: thick solid grey;
padding: 0.25rem 0.5rem; padding: 0.25rem 0.5rem;
display: inline-block; display: inline-block;
font-style: italic; font-style: italic;
@ -290,7 +177,6 @@ article .twt-msg > blockquote {
article .twt-msg img { article .twt-msg img {
margin: 0.25rem -0.25rem; margin: 0.25rem -0.25rem;
border: thin solid var(--border);
} }
article .twt-msg > img:first-child { article .twt-msg > img:first-child {
@ -302,19 +188,24 @@ article .twt-msg > img:last-child {
} }
article small { article small {
/* padding-left: 0.15rem;*/ font-size: small;
} }
/* article small a,
article small a { article small a:visited {
text-decoration: none; color: var(--text);
font-weight: bold;
}
*/
article small a.right { }
padding-right: 0.25rem;
font-weight: normal; /* === New Post Form === */
#new_twt {
border: none;
text-align: center
}
#new_twt input[type="submit"] {
min-width: 33%;
} }
nav.pagnation { nav.pagnation {
@ -324,7 +215,7 @@ nav.pagnation {
} }
footer { footer {
border-top: thin solid var(--border); border-top: thin solid grey;
margin-top: 1rem; margin-top: 1rem;
text-align: center; text-align: center;
} }

165
style_minimal.css Normal file
View file

@ -0,0 +1,165 @@
.right {
float: right;
}
body {
font-family: sans-serif;
line-height: 1.25;
}
main {
max-width: 700px;
margin: 1rem auto;
}
nav {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
max-width: calc(var(--nav-width) + var(--gap) * 2);
margin-inline-start: auto;
margin-inline-end: auto;
}
nav ul {
width: 100%;
display: flex;
justify-content: space-between;
padding-left: 0.5rem;
margin: 0.25rem 0rem;
}
nav ul.secondary {
padding: 0 0.75rem;
font-size: small;
}
nav ul li {
display: inline-block;
list-style: none;
}
nav a {
text-decoration: none;
font-weight: bold;
line-height: 1.5;
}
nav form {
margin: 0;
}
nav .link-btn {
background: none;
border: none;
cursor: pointer;
margin: 0;
padding: 0;
width: 100%;
color: var(--primary);
font-weight: bold;
border-radius: 0;
}
img {
object-fit: contain;
max-width: 100%;
height: auto;
border-radius: 0.25rem;
}
img.avatar {
height: 2.5rem;
width: 2.5rem;
object-fit: cover;
}
a.author {
text-decoration: none;
color: var(--primary);
}
.profile {
padding: 0 1rem;
display: grid;
grid-template-columns: 4rem 1fr;
grid-gap: 1rem;
margin: 1rem 0;
}
.profile img.avatar {
width: 4rem;
height: 4rem;
}
.profile .author {
font-size: larger;
}
.profile blockquote {
margin: 0.5rem 0;
color: var(--secondary);
}
article {
background-color: var(--entry);
color: var(--secondary);
border-radius: 0.25rem;
border: thin solid grey;
margin: 0.5rem;
padding: 0.5rem;
}
article.post-entry {
display: grid;
grid-gap: 1rem;
grid-template-columns: 2.5rem auto;
}
article .twt-msg {
padding: 0.5rem 0;
}
article .twt-msg a {
text-decoration: underline;
}
article .twt-msg > blockquote {
margin: 0;
border-left: thick solid grey;
padding: 0.25rem 0.5rem;
display: inline-block;
font-style: italic;
}
article .twt-msg img {
margin: 0.25rem -0.25rem;
border: thin solid grey;
}
article .twt-msg > img:first-child {
margin-top: 0;
}
article .twt-msg > img:last-child {
margin-bottom: 0;
}
article small a.right {
padding-right: 0.25rem;
font-weight: normal;
}
nav.pagnation {
display: flex;
justify-content: center;
padding: 0.5rem 0;
}
footer {
border-top: thin solid grey;
margin-top: 1rem;
text-align: center;
}

330
style_papermod.css Normal file
View file

@ -0,0 +1,330 @@
* {
/* border: thin solid pink;*/
}
/* from PaperMod: https://github.com/adityatelange/hugo-PaperMod/tree/54a3c6073518005182f3c3250ddb7e8c0cacd7ad/assets/css */
:root {
--gap: 1rem;
--content-gap: 20px;
--nav-width: 1024px;
--main-width: 720px;
--header-height: 60px;
--footer-height: 60px;
--radius: 8px;
--theme: rgb(255, 255, 255);
--entry: rgb(255, 255, 255);
--primary: rgb(30, 30, 30);
--secondary: rgb(108, 108, 108);
--tertiary: rgb(214, 214, 214);
--content: rgb(31, 31, 31);
--hljs-bg: rgb(28, 29, 33);
--code-bg: rgb(245, 245, 245);
--border: rgb(238, 238, 238);
}
body {
background-color: var(--code-bg);
font-family: sans-serif;
/* max-width: 700px;
margin: 1rem auto; */
line-height: 1.25;
}
main {
max-width: 700px;
margin: 1rem auto;
}
a, button, body, h1, h2, h3, h4, h5, h6 {
color: var(--primary);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
/* == Forms (from https://adi.tilde.institute/default.css/) ==================== */
form {
align-content: center;
display: flex;
}
label {
display: block;
font-size: small;
}
input, textarea, select {
box-sizing: border-box;
display: inline-block;
/* margin: .5ex 0 1ex 0;*/
margin-top: -0.5rem;
padding: 1ex .5rem;
border: thin solid var(--border);
border-radius: var(--radius);
/*width: 100%;*/
font-size: 1em;
background-color: var(--entry);
color: var(--primary);
}
input[type="text"],
input[type="file"] {
flex-grow: 1;
margin-right: 0.5rem;
}
input[type=checkbox], input[type=radio] {
display: inline;
width: auto;
}
textarea {
font-family: inherit;
width: 100%;
background-color: var(--input-box);
}
input[type="submit"],
a.button, button {
background-color: var(--pod-color);
border-radius: var(--radius);
border: thin solid var(--pod-color);
color: var(--button-text);
display: block;
/* margin-top: -1rem;*/
font-size: 1em;
padding: 1ex 1rem;
text-align: center;
text-decoration: none;
}
button.primary {
width: 100%;
margin: 1rem 0;
}
fieldset {
border: thin solid var(--border-color);
border-radius: var(--radius);
margin: 0.5rem 0;
padding: 0.5rem 0.75rem;
}
/* --- */
.right {
float: right;
}
hr {
background: var(--border);
border: 0;
height: 1px;
width: 100%;
}
header {
margin-bottom: 2rem;
border-bottom: thin solid var(--tertiary);
}
nav {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
max-width: calc(var(--nav-width) + var(--gap) * 2);
margin-inline-start: auto;
margin-inline-end: auto;
}
nav ul {
width: 100%;
display: flex;
justify-content: space-between;
padding-left: 0.5rem;
margin: 0.25rem 0rem;
}
nav ul.secondary {
padding: 0 0.75rem;
font-size: small;
}
/*
nav ul.secondary a {
text-decoration: underline;
font-weight: normal;
}
*/
nav ul li {
display: inline-block;
list-style: none;
}
nav a {
text-decoration: none;
font-weight: bold;
line-height: 1.5;
}
nav form {
margin: 0;
}
nav .link-btn {
background: none;
border: none;
cursor: pointer;
margin: 0;
padding: 0;
width: 100%;
color: var(--primary);
font-weight: bold;
/*text-decoration: underline;*/
border-radius: 0;
}
img {
object-fit: contain;
max-width: 100%;
height: auto;
border-radius: 0.25rem;
}
img.avatar {
height: 48px;
width: 48px;
object-fit: cover;
}
a.author {
text-decoration: none;
color: var(--primary);
}
.profile {
padding: 0 1rem;
display: grid;
/* grid-template-columns: 4rem 3fr 1fr;*/
grid-template-columns: 4rem 1fr;
grid-gap: 1rem;
margin: 1rem 0;
}
.profile img.avatar {
width: 4rem;
height: 4rem;
/* border-radius: 100%;*/
}
.profile .author {
font-size: larger;
}
.profile blockquote {
margin: 0.5rem 0;
color: var(--secondary);
}
/*.profile nav a {
font-size: small;
text-decoration: underline;
}*/
nav.profile {
padding: 0;
/* display: flex;*/
/* justify-content: space-around;*/
}
nav.profile a {
/* font-size: small;*/
/* text-decoration: underline;*/
/* border: thin solid var(--border);
border-radius: var(--radius);
background-color: var(--entry);
padding: 0.5rem 1rem;*/
margin: 0 0.5rem;
}
article {
background-color: var(--entry);
color: var(--secondary);
border-radius: 0.25rem;
border: thin solid var(--border);
margin: 0.5rem;
padding: 0.5rem;
}
article.post-entry {
display: grid;
grid-gap: var(--gap);
grid-template-columns: 48px auto;
}
article .twt-msg {
padding: 0.5rem 0;
}
article .twt-msg a{
text-decoration: underline;
}
article .twt-msg > blockquote {
margin: 0;
border-left: thick solid var(--border);
padding: 0.25rem 0.5rem;
display: inline-block;
font-style: italic;
}
article .twt-msg img {
margin: 0.25rem -0.25rem;
border: thin solid var(--border);
}
article .twt-msg > img:first-child {
margin-top: 0;
}
article .twt-msg > img:last-child {
margin-bottom: 0;
}
article small {
/* padding-left: 0.15rem;*/
}
/*
article small a {
text-decoration: none;
font-weight: bold;
}
*/
article small a.right {
padding-right: 0.25rem;
font-weight: normal;
}
nav.pagnation {
display: flex;
justify-content: center;
padding: 0.5rem 0;
}
footer {
border-top: thin solid var(--border);
margin-top: 1rem;
text-align: center;
}

View file

@ -1,4 +1,5 @@
<?php <?php require_once('partials/base.php');
// TODO: Give a warning if the file is not found // TODO: Give a warning if the file is not found
$config = parse_ini_file('private/config.ini'); $config = parse_ini_file('private/config.ini');
@ -10,7 +11,7 @@ if ($config['debug_mode']) {
$txt_file_path = $config['txt_file_path']; $txt_file_path = $config['txt_file_path'];
require_once('partials/base.php');
/* /*
if (!has_valid_session()) { if (!has_valid_session()) {
@ -60,29 +61,31 @@ if (isset($_POST['url'])) {
header('Refresh:0; url=.'); header('Refresh:0; url=.');
exit; exit;
} else { ?> } else { ?>
<!DOCTYPE html>
<html lang="en"> <?php
<head> require_once("partials/base.php");
<meta charset="UTF-8">
<title>twtxt</title> $title = "Add feed - ".$title;
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<link rel="stylesheet" type="text/css" href="style.css"> include 'partials/header.php';
</head> ?>
<body>
<h1><a href=".">twtxt</a></h1> <h1>Add a new feed to follow</h1>
<form method="POST" class="column">
<div id="follow"> <form method="POST" class="column">
<label for="url">URL to follow</label> <div id="follow">
<br> <label for="url">URL to follow</label>
<input type="url" id="url" name="url" class="input" size="50" autocomplete="off" required> <br>
<br> <input type="url" id="url" name="url" class="input" size="50" autocomplete="off" required>
<label for="nick">Nick</label> <br>
<br> <label for="nick">Nick</label>
<input type="text" id="nick" name="nick" class="input" size="50" autocomplete="off" required> <br>
<br> <input type="text" id="nick" name="nick" class="input" size="50" autocomplete="off" required>
<input type="submit" value="Follow" class="btn"> <br>
</div> <input type="submit" value="Follow" class="btn">
</form> </div>
</body> </form>
</html>
<!-- PHP: GET FOOTER --><?php include 'partials/footer.php';?>
<?php } ?> <?php } ?>

View file

@ -10,32 +10,15 @@ if (!empty($id)) {
// && !preg_match('/conv/', $request) // && !preg_match('/conv/', $request)
$title = "Conversation: ".$id." - ".$title;
include 'partials/header.php';
?> ?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" type="text/css" href="/style.css">
<title>Conversation: <?= $id ?></title>
</head>
<body >
<!-- PHP: GET HEADER --><?php include 'partials/header.php';?>
<main>
<h2>Conversation</h2> <h2>Conversation</h2>
<p>Recent twts in reply to <a href="/post/<?= $id ?>">#<?= $id ?></a></p> <p>Recent twts in reply to <a href="/post/<?= $id ?>">#<?= $id ?></a></p>
<!-- PHP: GET TIMELIE --><?php include 'partials/timeline.php'?> <!-- PHP: GET TIMELIE --><?php include 'partials/timeline.php'?>
</main>
<!-- PHP: GET FOOTER --><?php include 'partials/footer.php';?> <!-- PHP: GET FOOTER --><?php include 'partials/footer.php';?>
</body>
</html>

View file

@ -1,37 +1,36 @@
<?php require_once("partials/base.php"); ?> <?php
require_once("partials/base.php");
<html> $title = "Following - ".$title;
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" type="text/css" href="style.css">
<title><?= $title ?> - Timeline</title>
</head>
<body >
<!-- PHP: GET HEADER --><?php include 'partials/header.php';?> include 'partials/header.php';
?>
<center> <center>
<h1>Following: <?php echo count($twtFollowingList); ?> feeds</h1> <h1>Following <?php echo count($twtFollowingList); ?> feeds</h1>
<table> <table>
<tr><th></th><th>Nick</th><th>URL</th></tr>
<?php foreach ($twtFollowingList as $currentFollower) { ?> <tr>
<tr> <!-- <th></th> -->
<td></td> <th>Nick</th>
<td><a href="?url=<?= $currentFollower[1] ?>"><?= $currentFollower[0] ?></a></td> <th>URL</th></tr>
<td><?= $currentFollower[1] ?>
<!-- <?php if ($validSession) { ?> --> <?php foreach ($twtFollowingList as $currentFollower) { ?>
<!-- <a href="?remove_url=<?= $currentFollower[1] ?>">Remove</a> --> <tr>
<!-- <?php } ?> --> <!-- <td></td> -->
</td> <td><a href="/?twts=<?= $currentFollower[1] ?>"><?= $currentFollower[0] ?></a></td>
</tr> <!-- <td><a href="/?twt=<?= $currentFollower[1] ?>"><?= $currentFollower[0] ?></a></td> -->
<?php } ?> <td><?= $currentFollower[1] ?>
<!-- <?php if ($validSession) { ?> -->
<!-- <a href="?remove_url=<?= $currentFollower[1] ?>">Remove</a> -->
<!-- <?php } ?> -->
</td>
</tr>
<?php } ?>
</table> </table>
</center> </center>
<!-- PHP: GET FOOTER --><?php include 'partials/footer.php';?> <!-- FOOTER --><?php include 'partials/footer.php';?>
</body>
</html>

View file

@ -1,18 +1,12 @@
<?php require_once("partials/base.php"); ?> <?php
require_once("partials/base.php");
<html> //$title = "Login - ".$title;
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" type="text/css" href="style.css">
<title>Timeline</title>
</head>
<body >
<!-- PHP: GET HEADER --><?php include 'partials/header.php';?> include 'partials/header.php';
?>
<main> <!-- PHP: PROFILE CARD -->
<!-- PHP: GET PROFILE CARD -->
<?php <?php
if (!empty($_GET['twts'])) { // Show twts for some user if (!empty($_GET['twts'])) { // Show twts for some user
$twtsURL = $_GET['twts']; $twtsURL = $_GET['twts'];
@ -30,11 +24,13 @@ if (!empty($_GET['twts'])) { // Show twts for some user
} ?> } ?>
<!-- PHP: GET TIMELIE --><?php include 'partials/timeline.php'?> <!-- PHP: NEW POST BOX -->
<?php
if( isset($_SESSION['password'])) {
include 'views/new_twt.php'; // TODO: Split up new_twt into a view and a partial
} ?>
</main> <!-- PHP: TIMELINE --><?php include 'partials/timeline.php'?>
<!-- PHP: GET FOOTER --><?php include 'partials/footer.php';?> <!-- PHP: FOOTER --><?php include 'partials/footer.php';?>
</body>
</html>

View file

@ -28,7 +28,7 @@ if (filter_var($url, FILTER_VALIDATE_URL) === FALSE) {
die('Not a valid URL'); die('Not a valid URL');
} }
#echo "Loading URL: $url<br>\n<br>\n"; echo "Loading URL: $url<br>\n<br>\n";
#ob_flush(); #ob_flush();
const DEBUG_TIME_SECS = 300; const DEBUG_TIME_SECS = 300;
@ -50,12 +50,12 @@ foreach ($fileLines as $currentLine) {
# Load all the files # Load all the files
# Save a flag to know it's loading files in the background # Save a flag to know it's loading files in the background
foreach ($twtFollowingList as $following) { foreach ($twtFollowingList as $following) {
#echo "Updating: $following[1]<br>\n"; echo "Updating: $following[1]<br>\n";
#ob_flush(); #ob_flush();
updateCachedFile($following[1]); updateCachedFile($following[1]);
} }
#echo 'Finished'; echo 'Finished';
#ob_flush(); #ob_flush();
header('Location: .'); header('Location: /');
exit(); exit();

View file

@ -1,39 +1,31 @@
<?php <?php
require_once("libs/session.php"); // TODO: Move all to base.php require_once("partials/base.php");
?>
<html> $title = "Login - ".$title;
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> include 'partials/header.php';
<meta name="viewport" content="width=device-width, initial-scale=1" /> ?>
<link rel="stylesheet" type="text/css" href="../style.css">
<title>Log in</title>
</head>
<body >
<?php <?php
//$config = parse_ini_file('private/config.ini'); //$config = parse_ini_file('private/config.ini');
//$password = $config['password']; //$password = $config['password'];
if( isset($_SESSION['password'])) { if( isset($_SESSION['password'])) {
if($_SESSION['password']=="$password") if($_SESSION['password']=="$password") {
{
header("Location: ."); header("Location: .");
die(); die();
?> }
<h1>You are loggged in now</h1> }
<form method="post" action="" id="logout_form">
<input type="submit" name="page_logout" value="LOGOUT" style="background-color: #000; color: #f00; font-family: monospace;">
</form>
<?php } } else { ?> else { ?>
<h1>Log in:</h1> <center>
<h2>Enter password:</h2>
<form method="post" action="" id="login_form"> <form method="post" action="" id="login_form">
<input type="password" name="pass"><br> <input type="password" name="pass"><br>
<input type="submit" name="submit_pass" value="Login"> <input type="submit" name="submit_pass" value="Login">
<p><font style="color:red;"><?php if(isset($error)) {echo $error;}?></font></p> <p><font style="color:red;"><?php if(isset($error)) {echo $error;}?></font></p>
</form> </form>
</center>
<?php } ?> <?php } ?>
</body> <!-- PHP: GET FOOTER --><?php include 'partials/footer.php';?>
</html>

9
views/logout.php Normal file
View file

@ -0,0 +1,9 @@
<?php
session_start();
session_unset();
session_destroy();
header("Location: /");
die();

View file

@ -14,13 +14,16 @@ $timezone = $config['timezone'];
require_once('libs/session.php'); require_once('libs/session.php');
// if (!has_valid_session()) {
// header('Location: /login.php');
// exit();
// }
if (!has_valid_session()) { if (!isset($_SESSION['password'])) {
header('Location: login.php'); header('Location: /login');
exit(); exit();
} }
$textareaValue = ''; $textareaValue = '';
if (isset($_GET['hash'])) { if (isset($_GET['hash'])) {
$hash = $_GET['hash']; $hash = $_GET['hash'];
@ -76,26 +79,31 @@ if (isset($_POST['submit'])) {
header('Refresh:0; url=.'); header('Refresh:0; url=.');
exit; exit;
} else { ?> } else { ?>
<!DOCTYPE html>
<html lang="en"> <?php
<head> require_once("partials/base.php");
<meta charset="UTF-8">
<title>twtxt</title> $title = "New post - ".$title;
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<link rel="stylesheet" type="text/css" href="style.css"> include_once 'partials/header.php';
</head> ?>
<body>
<h1><a href=".">twtxt</a></h1> <article id="new_twt">
<form method="POST" class="column"> <form method="POST">
<div id="posting"> <div id="posting">
<textarea class="textinput" id="new_post" name="new_post" <textarea class="textinput" id="new_post" name="new_post"
rows="4" cols="100" autofocus required rows="4" cols="100" autofocus required
placeholder="Your twt"><?= $textareaValue ?></textarea> placeholder="Your twt"><?= $textareaValue ?></textarea>
<br> <!-- <br> -->
<input class="btn" type="submit" value="Post" name="submit"> <input type="submit" value="Post" name="submit">
</div> </div>
</form> </form>
</body> </article>
</html>
<!-- PHP: GET TIMELIE --><?php include_once 'partials/timeline.php'?>
<!-- PHP: GET FOOTER --><?php include_once 'partials/footer.php';?>
<?php } ?> <?php } ?>

View file

@ -7,28 +7,13 @@ if (!empty($id)) {
}); });
} }
$title = "Post: ".$id." - ".$title;
include 'partials/header.php';
?> ?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" type="text/css" href="/style.css">
<title>Post: <?= $id ?></title>
</head>
<body >
<!-- PHP: GET HEADER --><?php include 'partials/header.php';?>
<main>
<h2>Post: #<?= $id ?></h2> <h2>Post: #<?= $id ?></h2>
<!-- PHP: GET TIMELIE --><?php include 'partials/timeline.php'?> <!-- PHP: GET TIMELIE --><?php include 'partials/timeline.php'?>
</main>
<!-- PHP: GET FOOTER --><?php include 'partials/footer.php';?> <!-- PHP: GET FOOTER --><?php include 'partials/footer.php';?>
</body>
</html>

View file

@ -1,29 +0,0 @@
<?php
require_once("partials/session.php"); // TODO: Move all to base.php
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" type="text/css" href="../style.css">
<title>index.html</title>
</head>
<body >
<?php
if($_SESSION['password']=="æøå123") // TODO: Replace by var from config.ini
{
?>
<h1>You are loggged in now</h1>
<form method="post" action="" id="logout_form">
<input type="submit" name="page_logout" value="LOGOUT" style="background-color: #000; color: #f00; font-family: monospace;">
</form>
<?php
} else {
?>
<h1><a href="/login">Log in</a></h1>
<?php } ?>
</body>
</html>