diff --git a/package.json b/package.json
index d98a5c6..5ba3874 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "spacesocial-client",
- "version": "0.2.0_rev1",
+ "version": "0.2.0_rev2",
"description": "social media for the galaxy-wide-web! 🌌",
"type": "module",
"scripts": {
diff --git a/src/App.svelte b/src/App.svelte
index 7538a88..6f05334 100644
--- a/src/App.svelte
+++ b/src/App.svelte
@@ -20,6 +20,7 @@
}
if (client.app && client.app.token) {
+ // this triggers the client actually getting the authenticated user's data.
client.verifyCredentials().then(res => {
if (res) {
console.log(`Logged in as @${client.user.username}@${client.user.host}`);
diff --git a/src/client/api.js b/src/client/api.js
index dfcf733..e063e75 100644
--- a/src/client/api.js
+++ b/src/client/api.js
@@ -131,6 +131,83 @@ export async function getPostContext(post_id) {
return data;
}
+export async function boostPost(post_id) {
+ let client = get(Client.get());
+ let url = `https://${client.instance.host}/api/v1/statuses/${post_id}/reblog`;
+ const data = await fetch(url, {
+ method: 'POST',
+ headers: { "Authorization": "Bearer " + client.app.token }
+ }).then(res => { return res.ok ? res.json() : false });
+
+ if (data === false) return false;
+ return data;
+}
+
+export async function unboostPost(post_id) {
+ let client = get(Client.get());
+ let url = `https://${client.instance.host}/api/v1/statuses/${post_id}/unreblog`;
+ const data = await fetch(url, {
+ method: 'POST',
+ headers: { "Authorization": "Bearer " + client.app.token }
+ }).then(res => { return res.ok ? res.json() : false });
+
+ if (data === false) return false;
+ return data;
+}
+
+export async function favouritePost(post_id) {
+ let client = get(Client.get());
+ let url = `https://${client.instance.host}/api/v1/statuses/${post_id}/favourite`;
+ const data = await fetch(url, {
+ method: 'POST',
+ headers: { "Authorization": "Bearer " + client.app.token }
+ }).then(res => { return res.ok ? res.json() : false });
+
+ if (data === false) return false;
+ return data;
+}
+
+export async function unfavouritePost(post_id) {
+ let client = get(Client.get());
+ let url = `https://${client.instance.host}/api/v1/statuses/${post_id}/unfavourite`;
+ const data = await fetch(url, {
+ method: 'POST',
+ headers: { "Authorization": "Bearer " + client.app.token }
+ }).then(res => { return res.ok ? res.json() : false });
+
+ if (data === false) return false;
+ return data;
+}
+
+export async function reactPost(post_id, shortcode) {
+ // for whatever reason (at least in my testing on iceshrimp)
+ // using shortcodes for external emoji results in a fallback
+ // to the default like emote.
+ // identical api calls on chuckya instances do not display
+ // this behaviour.
+ let client = get(Client.get());
+ let url = `https://${client.instance.host}/api/v1/statuses/${post_id}/react/${encodeURIComponent(shortcode)}`;
+ const data = await fetch(url, {
+ method: 'POST',
+ headers: { "Authorization": "Bearer " + client.app.token }
+ }).then(res => { return res.ok ? res.json() : false });
+
+ if (data === false) return false;
+ return data;
+}
+
+export async function unreactPost(post_id, shortcode) {
+ let client = get(Client.get());
+ let url = `https://${client.instance.host}/api/v1/statuses/${post_id}/unreact/${encodeURIComponent(shortcode)}`;
+ const data = await fetch(url, {
+ method: 'POST',
+ headers: { "Authorization": "Bearer " + client.app.token }
+ }).then(res => { return res.ok ? res.json() : false });
+
+ if (data === false) return false;
+ return data;
+}
+
export async function parsePost(data, parent_replies, child_replies) {
let client = get(Client.get());
let post = new Post();
@@ -166,6 +243,9 @@ export async function parsePost(data, parent_replies, child_replies) {
post.warning = data.spoiler_text;
post.boost_count = data.reblogs_count;
post.reply_count = data.replies_count;
+ post.favourite_count = data.favourites_count;
+ post.favourited = data.favourited;
+ post.boosted = data.boosted;
post.mentions = data.mentions;
post.files = data.media_attachments;
post.url = data.url;
@@ -185,33 +265,7 @@ export async function parsePost(data, parent_replies, child_replies) {
}
if (data.reactions && client.instance.capabilities.includes(capabilities.REACTIONS)) {
- post.reactions = [];
- data.reactions.forEach(reaction_data => {
- if (/^[\w\-.@]+$/g.exec(reaction_data.name)) {
- let name = reaction_data.name.split('@')[0];
- let host = reaction_data.name.includes('@') ? reaction_data.name.split('@')[1] : client.instance.host;
- post.reactions.push({
- count: reaction_data.count,
- emoji: parseEmoji({
- id: name + '@' + host,
- name: name,
- host: host,
- url: reaction_data.url,
- }),
- me: reaction_data.me,
- });
- } else {
- if (reaction_data.name == '❤') reaction_data.name = '❤️'; // stupid heart unicode
- post.reactions.push({
- count: reaction_data.count,
- emoji: {
- html: reaction_data.name,
- name: reaction_data.name,
- },
- me: reaction_data.me,
- });
- }
- });
+ post.reactions = parseReactions(data.reactions);
}
return post;
}
@@ -251,6 +305,21 @@ export async function parseUser(data) {
return user;
}
+export function parseReactions(data) {
+ let client = get(Client.get());
+ 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;
+}
+
export function parseEmoji(data) {
let emoji = new Emoji(
data.id,
diff --git a/src/client/client.js b/src/client/client.js
index 575c293..862f1d2 100644
--- a/src/client/client.js
+++ b/src/client/client.js
@@ -100,6 +100,30 @@ export class Client {
return await api.getPost(post_id, parent_replies, child_replies);
}
+ async boostPost(post_id) {
+ return await api.boostPost(post_id);
+ }
+
+ async unboostPost(post_id) {
+ return await api.unboostPost(post_id);
+ }
+
+ async favouritePost(post_id) {
+ return await api.favouritePost(post_id);
+ }
+
+ async unfavouritePost(post_id) {
+ return await api.unfavouritePost(post_id);
+ }
+
+ async reactPost(post_id, shortcode) {
+ return await api.reactPost(post_id, shortcode);
+ }
+
+ async unreactPost(post_id, shortcode) {
+ return await api.unreactPost(post_id, shortcode);
+ }
+
putCacheUser(user) {
this.cache.users[user.id] = user;
client.set(this);
@@ -148,7 +172,6 @@ export class Client {
if (!json) return false;
let saved = JSON.parse(json);
if (!saved.version || saved.version !== APP_VERSION) {
- localStorage.setItem(save_name + '-backup', json);
localStorage.removeItem(save_name);
return false;
}
diff --git a/src/emoji.js b/src/emoji.js
index 9cd5e12..4fdd161 100644
--- a/src/emoji.js
+++ b/src/emoji.js
@@ -5,9 +5,7 @@ export const EMOJI_REGEX = /:[\w\-.]{0,32}@[\w\-.]{0,32}:/g;
export const EMOJI_NAME_REGEX = /:[\w\-.]{0,32}:/g;
export default class Emoji {
- id;
name;
- host;
url;
constructor(id, name, host, url) {
@@ -18,7 +16,10 @@ export default class Emoji {
}
get html() {
- return ``;
+ if (this.url)
+ return ``;
+ else
+ return `${this.name}`;
}
}
diff --git a/src/post.js b/src/post.js
index 1468ef9..9971daa 100644
--- a/src/post.js
+++ b/src/post.js
@@ -8,6 +8,9 @@ export default class Post {
warning;
boost_count;
reply_count;
+ favourite_count;
+ favourited;
+ boosted;
mentions;
reactions;
emojis;
diff --git a/src/sound.js b/src/sound.js
index c5dc1fb..bc12022 100644
--- a/src/sound.js
+++ b/src/sound.js
@@ -1,10 +1,11 @@
const sounds = {
- "default": new Audio("sound/log.ogg"),
- "post": new Audio("sound/success.ogg"),
- "boost": new Audio("sound/hello.ogg"),
+ "default": new Audio("/sound/log.ogg"),
+ "post": new Audio("/sound/success.ogg"),
+ "boost": new Audio("/sound/hello.ogg"),
};
export function play_sound(name) {
+ if (name === false) return;
if (!name) name = "default";
const sound = sounds[name];
if (!sound) {
diff --git a/src/ui/post/ActionButton.svelte b/src/ui/post/ActionButton.svelte
index e62ce0f..ab34e5c 100644
--- a/src/ui/post/ActionButton.svelte
+++ b/src/ui/post/ActionButton.svelte
@@ -1,21 +1,36 @@