huge refactor. addresses #21 w/ inifinite scrolling notifications
This commit is contained in:
parent
f883b61659
commit
2e64f63caa
29 changed files with 887 additions and 1030 deletions
235
src/lib/post.js
235
src/lib/post.js
|
@ -1,177 +1,82 @@
|
|||
import { parseText as parseEmoji } from './emoji.js';
|
||||
import * as api from '$lib/api.js';
|
||||
import { server } from '$lib/client/server.js';
|
||||
import { app } from '$lib/client/app.js';
|
||||
import { parseAccount } from '$lib/account.js';
|
||||
import { parseEmoji, renderEmoji } from '$lib/emoji.js';
|
||||
import { get, writable } from 'svelte/store';
|
||||
|
||||
export default class Post {
|
||||
id;
|
||||
created_at;
|
||||
user;
|
||||
text;
|
||||
warning;
|
||||
boost_count;
|
||||
reply_count;
|
||||
favourite_count;
|
||||
favourited;
|
||||
boosted;
|
||||
mentions;
|
||||
reactions;
|
||||
emojis;
|
||||
files;
|
||||
url;
|
||||
reply;
|
||||
reply_id;
|
||||
replies;
|
||||
boost;
|
||||
visibility;
|
||||
const cache = writable({});
|
||||
|
||||
async rich_text() {
|
||||
return parseEmoji(this.text, this.user.host);
|
||||
/**
|
||||
* Parses a post using API data, and returns a writable store object.
|
||||
* @param {Object} data
|
||||
* @param {number} ancestor_count
|
||||
*/
|
||||
export async function parsePost(data, ancestor_count) {
|
||||
let post = {};
|
||||
if (!ancestor_count) ancestor_count = 0;
|
||||
|
||||
post.html = data.content;
|
||||
|
||||
post.reply = null;
|
||||
if ((data.in_reply_to_id || data.reply) && ancestor_count !== 0) {
|
||||
const reply_data = data.reply || await api.getPost(get(server).host, get(app).token, data.in_reply_to_id);
|
||||
// if the post returns false, we probably don't have permission to read it.
|
||||
// we'll respect the thread's privacy, and leave it alone :)
|
||||
if (!reply_data) return false;
|
||||
post.reply = await parsePost(reply_data, ancestor_count - 1, false);
|
||||
}
|
||||
|
||||
/*
|
||||
async rich_text() {
|
||||
let text = this.text;
|
||||
if (!text) return text;
|
||||
let client = Client.get();
|
||||
post.boost = data.reblog ? await parsePost(data.reblog, 1, false) : null;
|
||||
|
||||
const markdown_tokens = [
|
||||
{ tag: "pre", token: "```" },
|
||||
{ tag: "code", token: "`" },
|
||||
{ tag: "strong", token: "**" },
|
||||
{ tag: "strong", token: "__" },
|
||||
{ tag: "em", token: "*" },
|
||||
{ tag: "em", token: "_" },
|
||||
];
|
||||
post.id = data.id;
|
||||
post.created_at = new Date(data.created_at);
|
||||
post.account = await parseAccount(data.account);
|
||||
post.warning = data.spoiler_text;
|
||||
post.reply_count = data.replies_count;
|
||||
post.boost_count = data.reblogs_count;
|
||||
post.boosted = data.reblogged;
|
||||
post.favourite_count = data.favourites_count;
|
||||
post.favourited = data.favourited;
|
||||
post.mentions = data.mentions;
|
||||
post.media = data.media_attachments;
|
||||
post.url = data.url;
|
||||
post.visibility = data.visibility;
|
||||
|
||||
let response = "";
|
||||
let md_layer;
|
||||
let index = 0;
|
||||
while (index < text.length) {
|
||||
let sample = text.substring(index);
|
||||
let md_nostack = !(md_layer && md_layer.nostack);
|
||||
post.emojis = [];
|
||||
data.emojis.forEach(emoji => {
|
||||
post.emojis[emoji.shortcode] = parseEmoji(emoji.shortcode, emoji.url);
|
||||
});
|
||||
|
||||
// handle newlines
|
||||
if (md_nostack && sample.startsWith('\n')) {
|
||||
response += "<br>";
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
if (data.reactions) post.reactions = parseReactions(data.reactions);
|
||||
|
||||
// handle mentions
|
||||
if (client.instance.capabilities.includes(capabilities.MARKDOWN_CONTENT)
|
||||
&& md_nostack
|
||||
&& sample.match(/^@[\w\-.]+@[\w\-.]+/g)
|
||||
) {
|
||||
// find end of the mention
|
||||
let length = 1;
|
||||
while (index + length < text.length && /[a-z0-9-_.]/.test(text[index + length])) length++;
|
||||
length++; // skim the middle @
|
||||
while (index + length < text.length && /[a-z0-9-_.]/.test(text[index + length])) length++;
|
||||
post.rich_text = renderEmoji(post.html, post.emojis);
|
||||
|
||||
let mention = text.substring(index, index + length);
|
||||
return post;
|
||||
|
||||
// attempt to resolve mention to a user
|
||||
let user = await client.getUserByMention(mention);
|
||||
if (user) {
|
||||
const out = `<a href="/${user.mention}" class="mention">` +
|
||||
`<img src="${user.avatar_url}" class="mention-avatar" width="20" height="20">` +
|
||||
'@' + user.username + '@' + user.host + "</a>";
|
||||
if (md_layer) md_layer.text += out;
|
||||
else response += out;
|
||||
} else {
|
||||
response += mention;
|
||||
}
|
||||
index += mention.length;
|
||||
continue;
|
||||
}
|
||||
// let cache_post = get(cache)[post.id];
|
||||
// if (cache_post) {
|
||||
// cache_post.set(post);
|
||||
// } else {
|
||||
// cache.update(cache => {
|
||||
// cache[post.id] = writable(post);
|
||||
// return cache;
|
||||
// });
|
||||
// }
|
||||
|
||||
// handle links
|
||||
if (client.instance.capabilities.includes(capabilities.MARKDOWN_CONTENT)
|
||||
&& md_nostack
|
||||
&& sample.match(/^[a-z]{3,6}:\/\/[^\s]+/g)
|
||||
) {
|
||||
// get length of link
|
||||
let length = text.substring(index).search(/\s|$/g);
|
||||
let url = text.substring(index, index + length);
|
||||
let out = `<a href="${url}">${url}</a>`;
|
||||
if (md_layer) md_layer.text += out;
|
||||
else response += out;
|
||||
index += length;
|
||||
continue;
|
||||
}
|
||||
|
||||
// handle emojis
|
||||
if (md_nostack && sample.match(/^:[\w\-.]{0,32}:/g)) {
|
||||
// find the emoji name
|
||||
let length = text.substring(index + 1).search(':');
|
||||
if (length <= 0) return text;
|
||||
let emoji_name = text.substring(index + 1, index + length + 1);
|
||||
let emoji = client.getEmoji(emoji_name + '@' + this.user.host);
|
||||
|
||||
index += length + 2;
|
||||
|
||||
if (!emoji) {
|
||||
let out = ':' + emoji_name + ':';
|
||||
if (md_layer) md_layer.text += out;
|
||||
else response += out;
|
||||
continue;
|
||||
}
|
||||
|
||||
let out = emoji.html;
|
||||
if (md_layer) md_layer.text += out;
|
||||
else response += out;
|
||||
continue;
|
||||
}
|
||||
|
||||
// handle markdown
|
||||
// TODO: handle misskey-flavoured markdown(?)
|
||||
if (md_layer) {
|
||||
// try to pop layer
|
||||
if (sample.startsWith(md_layer.token)) {
|
||||
index += md_layer.token.length;
|
||||
let out = `<${md_layer.tag}>${md_layer.text}</${md_layer.tag}>`;
|
||||
if (md_layer.token === '```')
|
||||
out = `<code><pre>${md_layer.text}</pre></code>`;
|
||||
if (md_layer.parent) md_layer.parent.text += out;
|
||||
else response += out;
|
||||
md_layer = md_layer.parent;
|
||||
} else {
|
||||
md_layer.text += sample[0];
|
||||
index++;
|
||||
}
|
||||
} else if (md_nostack) {
|
||||
// should we add a layer?
|
||||
let pushed = false;
|
||||
for (let i = 0; i < markdown_tokens.length; i++) {
|
||||
let item = markdown_tokens[i];
|
||||
if (sample.startsWith(item.token)) {
|
||||
let new_md_layer = {
|
||||
token: item.token,
|
||||
tag: item.tag,
|
||||
text: "",
|
||||
parent: md_layer,
|
||||
};
|
||||
if (item.token === '```' || item.token === '`') new_md_layer.nostack = true;
|
||||
md_layer = new_md_layer;
|
||||
pushed = true;
|
||||
index += md_layer.token.length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!pushed) {
|
||||
response += sample[0];
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// destroy the remaining stack
|
||||
while (md_layer) {
|
||||
let out = md_layer.token + md_layer.text;
|
||||
if (md_layer.parent) md_layer.parent.text += out;
|
||||
else response += out;
|
||||
md_layer = md_layer.parent;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
*/
|
||||
// return get(cache)[post.id];
|
||||
}
|
||||
|
||||
export function parseReactions(data) {
|
||||
let reactions = [];
|
||||
data.forEach(reaction_data => {
|
||||
let reaction = {
|
||||
count: reaction_data.count,
|
||||
name: reaction_data.name,
|
||||
me: reaction_data.me,
|
||||
};
|
||||
if (reaction_data.url) reaction.url = reaction_data.url;
|
||||
reactions.push(reaction);
|
||||
});
|
||||
return reactions;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue