about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorVika <vika@fireburn.ru>2021-12-05 22:55:32 +0300
committerVika <vika@fireburn.ru>2021-12-05 22:55:32 +0300
commitc0b552318cb08872c7deae82a10122b0e16b7ae8 (patch)
treeec372ac488be069c0897338ca15ea08b7abca683 /src
parent24b109448bc8f1d30c88bbb9d01a05eec74b3d51 (diff)
Added author mini-cards on h-entries
Diffstat (limited to 'src')
-rw-r--r--src/database/file/mod.rs106
-rw-r--r--src/frontend/style.css24
-rw-r--r--src/frontend/templates/mod.rs11
3 files changed, 100 insertions, 41 deletions
diff --git a/src/database/file/mod.rs b/src/database/file/mod.rs
index 67b3549..d67c920 100644
--- a/src/database/file/mod.rs
+++ b/src/database/file/mod.rs
@@ -6,6 +6,7 @@ use async_trait::async_trait;
 use futures::stream;
 use futures_util::StreamExt;
 use futures_util::TryStreamExt;
+use serde_json::json;
 use crate::database::{ErrorKind, Result, Storage, StorageError, filter_post};
 use fd_lock::RwLock;
 use log::debug;
@@ -184,6 +185,34 @@ impl FileStorage {
     }
 }
 
+async fn hydrate_author<S: Storage>(feed: &mut serde_json::Value, user: &'_ Option<String>, storage: &S) {
+    let url = feed["properties"]["uid"][0].as_str().unwrap();
+    if let Some(author) = feed["properties"]["author"].clone().as_array() {
+        if !feed["type"].as_array().unwrap().iter().any(|i| i == "h-card") {
+            let author_list: Vec<serde_json::Value> = stream::iter(author.iter())
+                .then(|i| async move {
+                    if let Some(i) = i.as_str() {
+                        match storage.get_post(i).await {
+                            Ok(post) => match post {
+                                Some(post) => match filter_post(post, user) {
+                                    Some(author) => author,
+                                        None => json!(i)
+                                },
+                                None => json!(i)
+                            },
+                            Err(e) => {
+                                log::error!("Error while hydrating post {}: {}", url, e);
+                                json!(i)
+                            }
+                        }
+                    } else { i.clone() }
+                })
+                .collect::<Vec<_>>().await;
+            feed["properties"].as_object_mut().unwrap()["author"] = json!(author_list);
+        }
+    }
+}
+
 #[async_trait]
 impl Storage for FileStorage {
     async fn post_exists(&self, url: &str) -> Result<bool> {
@@ -386,50 +415,53 @@ impl Storage for FileStorage {
         limit: usize,
         user: &'a Option<String>,
     ) -> Result<Option<serde_json::Value>> {
-        match self.get_post(url).await? {
-            Some(feed) => match filter_post(feed, user) {
-                Some(mut feed) => {
-                    if feed["children"].is_array() {
-                        let children = feed["children"].as_array().unwrap().clone();
-                        let mut posts_iter = children.into_iter()
-                            .map(|s: serde_json::Value| s.as_str().unwrap().to_string());
-                        if after.is_some() {
-                            loop {
-                                let i = posts_iter.next();
-                                if &i == after {
-                                    break;
-                                }
+        if let Some(feed) = self.get_post(url).await? {
+            if let Some(mut feed) = filter_post(feed, user) {
+                if feed["children"].is_array() {
+                    let children = feed["children"].as_array().unwrap().clone();
+                    let mut posts_iter = children.into_iter()
+                        .map(|s: serde_json::Value| s.as_str().unwrap().to_string());
+                    if after.is_some() {
+                        loop {
+                            let i = posts_iter.next();
+                            if &i == after {
+                                break;
                             }
                         }
-                        let posts = stream::iter(posts_iter)
-                            .map(|url: String| async move {
-                                self.get_post(&url).await
-                            })
-                            .buffered(std::cmp::min(3, limit))
-                            // Hack to unwrap the Option and sieve out broken links
-                            // Broken links return None, and Stream::filter_map skips Nones.
-                            .try_filter_map(|post: Option<serde_json::Value>| async move { Ok(post) })
-                            .try_filter_map(|post| async move { Ok(filter_post(post, user)) })
-                            .take(limit);
-
-                        match posts.try_collect::<Vec<serde_json::Value>>().await {
-                            Ok(posts) => feed["children"] = serde_json::json!(posts),
-                            Err(err) => {
-                                return Err(StorageError::with_source(
-                                    ErrorKind::Other, "Feed assembly error",
-                                    Box::new(err)
-                                ));
-                            }
+                    }
+                    let posts = stream::iter(posts_iter)
+                        .map(|url: String| async move {
+                            self.get_post(&url).await
+                        })
+                        .buffered(std::cmp::min(3, limit))
+                    // Hack to unwrap the Option and sieve out broken links
+                    // Broken links return None, and Stream::filter_map skips Nones.
+                        .try_filter_map(|post: Option<serde_json::Value>| async move { Ok(post) })
+                        .and_then(|mut post| async move { hydrate_author(&mut post, user, self).await; Ok(post) })
+                        .try_filter_map(|post| async move { Ok(filter_post(post, user)) })
+
+                        .take(limit);
+
+                    match posts.try_collect::<Vec<serde_json::Value>>().await {
+                        Ok(posts) => feed["children"] = serde_json::json!(posts),
+                        Err(err) => {
+                            return Err(StorageError::with_source(
+                                ErrorKind::Other, "Feed assembly error",
+                                Box::new(err)
+                            ));
                         }
                     }
-                    Ok(Some(feed))
-                },
-                None => Err(StorageError::new(
+                }
+                hydrate_author(&mut feed, user, self).await;
+                Ok(Some(feed))
+            } else {
+                Err(StorageError::new(
                     ErrorKind::PermissionDenied,
                     "specified user cannot access this post",
                 ))
-            },
-            None => Ok(None)
+            }
+        } else {
+            Ok(None)
         }
     }
 
diff --git a/src/frontend/style.css b/src/frontend/style.css
index 1d6586b..a0add44 100644
--- a/src/frontend/style.css
+++ b/src/frontend/style.css
@@ -26,9 +26,9 @@ h1, .xxxlarge {
     margin-bottom: 0;
     font-size: 3.052rem;
 }
-h2 .xxlarge {font-size: 2.441rem;}
-h3 .xlarge {font-size: 1.953rem;}
-h4 .larger {font-size: 1.563rem;}  
+h2, .xxlarge {font-size: 2.441rem;}
+h3, .xlarge {font-size: 1.953rem;}
+h4, .larger {font-size: 1.563rem;}
 h5, .large {font-size: 1.25rem;}
 h6, .normal {font-size: 1rem;}
 small, .small { font-size: 0.8em; }
@@ -159,4 +159,20 @@ article.h-card img.u-photo {
     height: 8rem;
     border: 1px solid gray;
     margin-right: .75em;
-}
\ No newline at end of file
+}
+
+.mini-h-card img {
+    height: 2em;
+    display: inline-block;
+    border: 2px solid gray;
+    border-radius: 100%;
+    margin-right: 0.5rem;
+}
+
+.mini-h-card * {
+    vertical-align: middle;
+}
+
+.mini-h-card a {
+    text-decoration: none;
+}
diff --git a/src/frontend/templates/mod.rs b/src/frontend/templates/mod.rs
index a7c01e0..3585804 100644
--- a/src/frontend/templates/mod.rs
+++ b/src/frontend/templates/mod.rs
@@ -68,6 +68,17 @@ markup::define! {
                     h1."p-name" {
                         @post["properties"]["name"][0].as_str().unwrap()
                     }
+                } else {
+                    @if post["properties"]["author"][0].is_object() {
+                        section."mini-h-card" {
+                            a.larger[href=post["properties"]["author"][0]["properties"]["uid"][0].as_str().unwrap()] {
+                                @if post["properties"]["author"][0]["properties"]["photo"][0].is_string() {
+                                    img[src=post["properties"]["author"][0]["properties"]["photo"][0].as_str().unwrap()] {}
+                                }
+                                @post["properties"]["author"][0]["properties"]["name"][0].as_str().unwrap()
+                            }
+                        }
+                    }
                 }
                 div {
                     span {