Add private vanishing messages
This commit is contained in:
parent
929a46d8cb
commit
d207b512a3
|
@ -66,11 +66,17 @@ router.get("/", async (_req, res) => {
|
|||
res.redirect("/about");
|
||||
}
|
||||
|
||||
const [posts, friends] = await Promise.all([
|
||||
const [posts, friends, vanishingMessages] = await Promise.all([
|
||||
queries.getPosts(ssbServer, context.profile),
|
||||
queries.getFriends(ssbServer, context.profile),
|
||||
queries.getVanishingMessages(ssbServer, context.profile),
|
||||
]);
|
||||
res.render("index", { posts, friends });
|
||||
res.render("index", {
|
||||
posts,
|
||||
friends,
|
||||
vanishingMessages,
|
||||
profile: context.profile,
|
||||
});
|
||||
});
|
||||
|
||||
router.get("/profile/:id", async (req, res) => {
|
||||
|
@ -101,12 +107,25 @@ router.post("/publish", async (req, res) => {
|
|||
|
||||
router.post("/profile/:id/publish", async (req, res) => {
|
||||
const id = req.params.id;
|
||||
const visibility = req.body.visibility;
|
||||
console.log("req.body", req.body);
|
||||
|
||||
if (visibility == "vanishing") {
|
||||
await ssbServer.private.publish(
|
||||
{
|
||||
type: "post",
|
||||
text: req.body.message,
|
||||
root: id,
|
||||
},
|
||||
[id]
|
||||
);
|
||||
} else {
|
||||
await ssbServer.publish({
|
||||
type: "post",
|
||||
text: req.body.message,
|
||||
root: id,
|
||||
});
|
||||
}
|
||||
|
||||
res.redirect("/profile/" + id);
|
||||
});
|
||||
|
|
|
@ -76,6 +76,7 @@ const getPosts = (ssbServer, profile) =>
|
|||
{
|
||||
$filter: {
|
||||
value: {
|
||||
private: { $not: true },
|
||||
content: {
|
||||
root: profile.id,
|
||||
},
|
||||
|
@ -92,6 +93,7 @@ const getPosts = (ssbServer, profile) =>
|
|||
$filter: {
|
||||
value: {
|
||||
author: profile.id,
|
||||
private: { $not: true },
|
||||
content: {
|
||||
type: "post",
|
||||
root: { $not: true },
|
||||
|
@ -115,6 +117,64 @@ const getPosts = (ssbServer, profile) =>
|
|||
);
|
||||
});
|
||||
|
||||
const getVanishingMessages = (ssbServer, profile) =>
|
||||
debug("Fetching vanishing messages") ||
|
||||
new Promise((resolve, reject) => {
|
||||
pull(
|
||||
// @ts-ignore
|
||||
cat([
|
||||
ssbServer.query.read({
|
||||
reverse: true,
|
||||
query: [
|
||||
{
|
||||
$filter: {
|
||||
value: {
|
||||
private: true,
|
||||
content: {
|
||||
root: profile.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
limit: 100,
|
||||
}),
|
||||
ssbServer.query.read({
|
||||
reverse: true,
|
||||
query: [
|
||||
{
|
||||
$filter: {
|
||||
value: {
|
||||
author: profile.id,
|
||||
private: true,
|
||||
content: {
|
||||
type: "post",
|
||||
root: { $not: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
limit: 100,
|
||||
}),
|
||||
]),
|
||||
pull.filter(
|
||||
(msg) =>
|
||||
msg.value.content.type == "post" &&
|
||||
(msg.value.content.root ||
|
||||
msg.value.content.recps.includes(profile.id))
|
||||
),
|
||||
paramap(mapProfiles(ssbServer)),
|
||||
pull.collect((err, msgs) => {
|
||||
debug("Done fetching vanishing messages");
|
||||
const entries = msgs.map((x) => x.value);
|
||||
|
||||
if (err) return reject(err);
|
||||
return resolve(entries);
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
const searchPeople = (ssbServer, search) =>
|
||||
debug("Searching people") ||
|
||||
new Promise((resolve, reject) => {
|
||||
|
@ -242,4 +302,5 @@ module.exports = {
|
|||
getFriends,
|
||||
getAllEntries,
|
||||
getProfile,
|
||||
getVanishingMessages,
|
||||
};
|
||||
|
|
|
@ -16,7 +16,8 @@ Server.use(require("ssb-master"))
|
|||
.use(require("ssb-device-address"))
|
||||
.use(require("ssb-identities"))
|
||||
.use(require("ssb-peer-invites"))
|
||||
.use(require("ssb-blobs"));
|
||||
.use(require("ssb-blobs"))
|
||||
.use(require("ssb-private"));
|
||||
|
||||
const server = Server(config);
|
||||
console.log("SSB server started at", config.port);
|
||||
|
|
|
@ -2711,6 +2711,18 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"ssb-private": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ssb-private/-/ssb-private-0.2.3.tgz",
|
||||
"integrity": "sha512-SiLBKOB1hxkrohzOrRWURlzj6HvPFvr9LLd5P5I5C5KU/RtaWe79nYuFgjUFJFnjWw7X4szCy32/EZMihV1l/Q==",
|
||||
"requires": {
|
||||
"base64-url": "^2.2.0",
|
||||
"explain-error": "^1.0.4",
|
||||
"flumeview-query": "^6.1.0",
|
||||
"pull-stream": "^3.6.7",
|
||||
"ssb-keys": "^7.0.14"
|
||||
}
|
||||
},
|
||||
"ssb-query": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/ssb-query/-/ssb-query-2.4.3.tgz",
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
"ssb-keys": "^7.2.2",
|
||||
"ssb-master": "^1.0.3",
|
||||
"ssb-peer-invites": "^2.0.2",
|
||||
"ssb-private": "^0.2.3",
|
||||
"ssb-query": "^2.4.3",
|
||||
"ssb-replicate": "^1.3.2",
|
||||
"ssb-server": "^15.2.0"
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
const messages = document.querySelectorAll(".vanishing-message");
|
||||
messages.forEach((message) => {
|
||||
message.addEventListener("click", () => {
|
||||
const overlay = message.parentElement.querySelector(".overlay");
|
||||
const modal = message.parentElement.querySelector(".modal");
|
||||
const closeButton = message.parentElement.querySelector(".modal-close");
|
||||
|
||||
overlay.style.display = "block";
|
||||
modal.style.display = "block";
|
||||
|
||||
const onClose = () => {
|
||||
const parent = modal.parentElement;
|
||||
parent.parentElement.removeChild(parent);
|
||||
if (document.querySelectorAll(".vanishing-message").length == 0) {
|
||||
document.querySelector(".vanishing-messages").style.display = "none";
|
||||
}
|
||||
};
|
||||
|
||||
overlay.addEventListener("click", onClose);
|
||||
closeButton.addEventListener("click", onClose);
|
||||
});
|
||||
});
|
|
@ -1,9 +1,25 @@
|
|||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
margin: 0;
|
||||
line-height: 1.3em;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
button {
|
||||
font-size: 14px;
|
||||
background: #ddd;
|
||||
color: #5f5f5f;
|
||||
border-radius: 3px;
|
||||
padding: 8px 10px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
button:hover {
|
||||
background: #959eab;
|
||||
color: #fff;
|
||||
}
|
||||
header {
|
||||
padding: 0 30px;
|
||||
border-bottom: 1px solid #666;
|
||||
|
@ -70,7 +86,7 @@ h1 {
|
|||
}
|
||||
|
||||
.wall {
|
||||
padding: 20px;
|
||||
padding: 0 20px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
|
@ -106,3 +122,57 @@ h1 {
|
|||
.profile-pic {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
button.vanishing-message {
|
||||
background: none;
|
||||
width: 84px;
|
||||
text-align: center;
|
||||
border: 1px solid #333;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 2;
|
||||
background: #fff;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
padding-bottom: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
padding: 10px;
|
||||
background: #fffbf4;
|
||||
border-top: 1px solid #ddd;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
</main>
|
||||
<script src="/js/index.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,13 @@
|
|||
<div class="post">
|
||||
<div>
|
||||
<img src="<%= profileImageUrl(post.authorProfile) %>" class="post-profile-pic" />
|
||||
</div>
|
||||
<div class="post-content">
|
||||
<div class="content-header">
|
||||
<%= post.authorProfile.name %>
|
||||
</div>
|
||||
<div class="content-body">
|
||||
<%= post.content.text.slice(0, 140) %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,27 +1,66 @@
|
|||
<%- include('_header') %>
|
||||
|
||||
<h1>Home</h1>
|
||||
<div class="columns">
|
||||
<div class="about">
|
||||
<img class="profile-pic" src="<%= profileImageUrl(profile) %>" />
|
||||
<h1><%= profile.name %></h1>
|
||||
|
||||
<form action="/publish" method="POST">
|
||||
<textarea name="message"></textarea>
|
||||
<input type="submit" value="Send" />
|
||||
</form>
|
||||
<%= profile.description %>
|
||||
|
||||
<% posts.map(entry => { %>
|
||||
<div><%= entry.authorProfile.name %> (<%= entry.author.slice(0, 8) %>): <%= entry.content.text %></div>
|
||||
<hr />
|
||||
<% }) %>
|
||||
<h2>Friends</h2>
|
||||
|
||||
<h2>Friends</h2>
|
||||
|
||||
<ul>
|
||||
<ul>
|
||||
<% friends.map(friend => { %>
|
||||
<li>
|
||||
<a href="<%= profileUrl(friend.content.contact) %>">
|
||||
<%= friend.content.contactProfile && friend.content.contactProfile.name %> (<%= friend.content.contact.slice(0, 8) %>)
|
||||
<%= friend.content.contactProfile?.name %> (<%= friend.content.contact.slice(0, 8) %>)
|
||||
</a>
|
||||
</li>
|
||||
<% }) %>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="wall">
|
||||
<% if (vanishingMessages.length > 0) { %>
|
||||
<div class="vanishing-messages" style="padding-bottom: 20px">
|
||||
<h2>Vanishing Messages</h2>
|
||||
<% vanishingMessages.map(post => { %>
|
||||
<span>
|
||||
<button class="vanishing-message">
|
||||
<div><img src="<%= profileImageUrl(post.authorProfile) %>" class="post-profile-pic" /></div>
|
||||
<div><%= post.authorProfile.name %></div>
|
||||
</button>
|
||||
<div class="overlay"></div>
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<img src="<%= profileImageUrl(post.authorProfile) %>" class="post-profile-pic" style="padding-right: 10px" />
|
||||
<%= post.authorProfile.name %>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<%= post.content.text %>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
after you close this box the message will be gone forever
|
||||
<button class="modal-close">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<% }) %>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<h2>Your Wall</h2>
|
||||
|
||||
<form action="/publish" method="POST">
|
||||
<textarea name="message"></textarea>
|
||||
<input type="submit" value="Send" />
|
||||
</form>
|
||||
|
||||
<% posts.map(post => { %>
|
||||
<%- include('_post', { post }) %>
|
||||
<% }) %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%- include('_footer') %>
|
|
@ -22,27 +22,25 @@
|
|||
|
||||
<div class="wall">
|
||||
<h1><%= profile.name %>'s Wall</h1>
|
||||
<!--
|
||||
|
||||
<h2>Leave <%= profile.name %> a message</h2>
|
||||
<form action="<%= profileUrl(profile.id, "/publish") %>" method="POST">
|
||||
<div>
|
||||
<label>
|
||||
<input type="radio" name="visibility" value="public">
|
||||
Public
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="visibility" value="vanishing">
|
||||
Vanishing
|
||||
</label>
|
||||
</div>
|
||||
<textarea name="message"></textarea>
|
||||
<input type="submit" value="Send" />
|
||||
</form> -->
|
||||
</form>
|
||||
|
||||
<% posts.map(entry => { %>
|
||||
<div class="post">
|
||||
<div>
|
||||
<img src="<%= profileImageUrl(entry.authorProfile) %>" class="post-profile-pic" />
|
||||
</div>
|
||||
<div class="post-content">
|
||||
<div class="content-header">
|
||||
<%= entry.authorProfile.name %>
|
||||
</div>
|
||||
<div class="content-body">
|
||||
<%= entry.content.text.slice(0, 140) %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% posts.map(post => { %>
|
||||
<%- include('_post', { post }) %>
|
||||
<% }) %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue