aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Digitigrade/Model.php13
-rw-r--r--Digitigrade/Model/Actor.php4
-rw-r--r--Digitigrade/Model/Note.php4
-rw-r--r--routes/user.php29
-rw-r--r--static/style.css39
-rw-r--r--templates/actor_avatar.php4
-rw-r--r--templates/actor_profile.php11
-rw-r--r--templates/actor_profile_page.php16
-rw-r--r--templates/note.php12
-rw-r--r--templates/skeleton.php4
10 files changed, 99 insertions, 37 deletions
diff --git a/Digitigrade/Model.php b/Digitigrade/Model.php
index 0db27ef..dca1484 100644
--- a/Digitigrade/Model.php
+++ b/Digitigrade/Model.php
@@ -153,12 +153,21 @@ abstract class Model {
return static::fromDbRow($stmt->fetch(\PDO::FETCH_ASSOC));
}
- public static function findAllWhere(string $whereClause, array $parameters): array {
+ public static function findAllWhere(
+ string $whereClause,
+ array $parameters,
+ ?int $limit = null,
+ int $offset = 0
+ ): array {
$classNameParts = explode('\\', static::class);
$className = $classNameParts[count($classNameParts) - 1];
$tableName = self::mangleName($className);
- $stmt = Db::getInstance()->getPdo()->prepare("SELECT * FROM $tableName WHERE $whereClause");
+ $query = "SELECT * FROM $tableName WHERE $whereClause";
+ if ($limit != null) {
+ $query .= " LIMIT $limit OFFSET $offset";
+ }
+ $stmt = Db::getInstance()->getPdo()->prepare($query);
$stmt->execute($parameters);
return array_map(function ($row) {
return static::fromDbRow($row);
diff --git a/Digitigrade/Model/Actor.php b/Digitigrade/Model/Actor.php
index 8059409..d3589ae 100644
--- a/Digitigrade/Model/Actor.php
+++ b/Digitigrade/Model/Actor.php
@@ -204,6 +204,10 @@ class Actor extends PushableModel implements RpcReceiver {
return $instances;
}
+ public function getFullHandle(): string {
+ return $this->handle . ($this->isLocal ? '' : '@' . hostname_from_uri($this->uri));
+ }
+
public function jsonSerialize(): array {
if ($this->deleted) {
return [
diff --git a/Digitigrade/Model/Note.php b/Digitigrade/Model/Note.php
index 8dbec90..105f475 100644
--- a/Digitigrade/Model/Note.php
+++ b/Digitigrade/Model/Note.php
@@ -102,8 +102,8 @@ class Note extends PushableModel {
return $actors;
}
- public static function findAllWithAuthor(Actor $author): array {
- return self::findAllWhere('author = ?', [$author->id]);
+ public static function findAllWithAuthor(Actor $author, ?int $limit = null, int $offset = 0): array {
+ return self::findAllWhere('author = ?', [$author->id], $limit, $offset);
}
public function getInteractions(): array {
diff --git a/routes/user.php b/routes/user.php
index 8626c38..c0a632a 100644
--- a/routes/user.php
+++ b/routes/user.php
@@ -5,26 +5,15 @@ use Digitigrade\Model\Actor;
use Digitigrade\Router;
Router::getInstance()->mount('/@/:handle', function (array $args) {
- $actor = Actor::findLocalByHandle($args['handle']);
+ if (str_contains($args['handle'], '@')) {
+ // remote actor
+ $actor = Actor::findByWebfinger($args['handle']);
+ } else {
+ // local actor
+ $actor = Actor::findLocalByHandle($args['handle']);
+ }
if ($actor == null || $actor->deleted) {
- throw new NotFound("i don't know any local user called " . $args['handle']);
+ throw new NotFound("i don't know any user called " . $args['handle']);
}
-
- ?>
- <!DOCTYPE html>
- <html>
-
- <head>
- <title><?= $actor->displayName ?> (@<?= $actor->handle ?>)</title>
- </head>
-
- <body>
- <h1><?= $actor->displayName ?></h1>
- <p>@<?= $actor->handle ?></p>
- <hr>
- <p><?= $actor->bio ?></p>
- </body>
-
- </html>
- <?php
+ render_template('actor_profile_page', ['actor' => $actor]);
}); \ No newline at end of file
diff --git a/static/style.css b/static/style.css
index 95244cb..fc548fc 100644
--- a/static/style.css
+++ b/static/style.css
@@ -64,6 +64,11 @@ h1 {
padding: 0;
}
+hr {
+ border: none;
+ border-top: 1px solid #5554;
+}
+
article.note {
background: #fee4;
border: 1px solid #3b005e44;
@@ -74,15 +79,15 @@ article.note {
grid-template-columns: max-content 1fr;
gap: 16px;
- img.authorAvatar {
+ picture.avatar,
+ picture.avatar > * {
width: 64px;
aspect-ratio: 1;
}
.infoLine {
display: grid;
- grid-auto-columns: max-content 1fr max-content;
- grid-auto-flow: column;
+ grid-template-columns: max-content 1fr max-content;
align-items: baseline;
margin-bottom: 4px;
gap: 8px;
@@ -113,3 +118,31 @@ article.note {
padding: 0;
}
}
+
+.fullProfile {
+ border-radius: 8px;
+ margin: 16px;
+ padding: 16px;
+ border: 1px solid #23f4;
+ background: #e6eaff44;
+
+ .basicInfo {
+ display: grid;
+ grid-template-columns: max-content 1fr;
+ gap: 16px;
+
+ picture.avatar,
+ picture.avatar > * {
+ width: 96px;
+ aspect-ratio: 1;
+ }
+ .displayName {
+ font-size: 16pt;
+ font-weight: bold;
+ }
+ .handle,
+ .joinedDate {
+ font-size: 10pt;
+ }
+ }
+}
diff --git a/templates/actor_avatar.php b/templates/actor_avatar.php
new file mode 100644
index 0000000..d428006
--- /dev/null
+++ b/templates/actor_avatar.php
@@ -0,0 +1,4 @@
+<picture class="avatar">
+ <source srcset="<?= $actor->avatar ?>">
+ <img src="/static/default-avatar.svg">
+</picture> \ No newline at end of file
diff --git a/templates/actor_profile.php b/templates/actor_profile.php
new file mode 100644
index 0000000..45a0a59
--- /dev/null
+++ b/templates/actor_profile.php
@@ -0,0 +1,11 @@
+<div class="fullProfile">
+ <div class="basicInfo">
+ <?php call_template('actor_avatar', ['actor' => $actor]); ?>
+ <div>
+ <div class="displayName"><?= $actor->displayName ?></div>
+ <div class="handle">@<?= $actor->getFullHandle() ?></div>
+ <div class="joinedDate">Joined on <?= $actor->created->format('Y-m-d') ?></div>
+ </div>
+ </div>
+ <p class="bio"><?= $actor->bio ?></p>
+</div> \ No newline at end of file
diff --git a/templates/actor_profile_page.php b/templates/actor_profile_page.php
new file mode 100644
index 0000000..e745433
--- /dev/null
+++ b/templates/actor_profile_page.php
@@ -0,0 +1,16 @@
+<?php
+
+use Digitigrade\Model\Note;
+
+call_template('skeleton', [
+ 'pageTitle' => "$actor->displayName - @" . $actor->getFullHandle(),
+ 'renderTitleHeading' => false
+], function () {
+ global $actor;
+ call_template('actor_profile', ['actor' => $actor]);
+ echo '<hr>';
+ $notes = Note::findAllWithAuthor($actor, 50);
+ foreach ($notes as $n) {
+ call_template('note', ['note' => $n]);
+ }
+}); \ No newline at end of file
diff --git a/templates/note.php b/templates/note.php
index 9c4f609..6fcb477 100644
--- a/templates/note.php
+++ b/templates/note.php
@@ -1,17 +1,11 @@
-<?php
-$fullHandle = $note->author->handle . ($note->author->isLocal ? '' : '@' . hostname_from_uri($note->author->uri));
-?>
<article class="note">
- <a href="/@/<?= $fullHandle ?>">
- <picture>
- <source srcset="<?= $note->author->avatar ?>">
- <img class="authorAvatar" src="/static/default-avatar.svg">
- </picture>
+ <a href="/@/<?= $note->author->getFullHandle() ?>">
+ <?php call_template('actor_avatar', ['actor' => $note->author]); ?>
</a>
<div>
<div class="infoLine">
<span class="authorName"><?= $note->author->displayName ?></span>
- <span class="authorHandle">@<?= $fullHandle ?></span>
+ <span class="authorHandle">@<?= $note->author->getFullHandle() ?></span>
<span class="timestamp">
<?=
$note->created->format('Y-m-d \a\t H:i')
diff --git a/templates/skeleton.php b/templates/skeleton.php
index 8a7fdf1..acf86bf 100644
--- a/templates/skeleton.php
+++ b/templates/skeleton.php
@@ -18,7 +18,9 @@
</nav>
</header>
<main>
- <h1><?= $pageTitle ?></h1>
+ <?php if (!isset($renderTitleHeading) || $renderTitleHeading): ?>
+ <h1><?= $pageTitle ?></h1>
+ <?php endif; ?>
<?php slot(); ?>
</main>
</body>