mirror of
https://github.com/MathMan05/Fermi.git
synced 2026-10-24 06:12:55 +00:00
first thread commits
This commit is contained in:
1 parent
2c05b6bbd0
commit
0737279146
8 files changed
+348
-43
No files matched your search
+74
-13
@@ -16,6 +16,7 @@ import {
|
||||
mute_config,
|
||||
readyjson,
|
||||
startTypingjson,
|
||||
threadMember,
|
||||
} from "./jsontypes.js";
|
||||
import {MarkDown} from "./markdown.js";
|
||||
import {Member} from "./member.js";
|
||||
@@ -120,6 +121,35 @@ class Channel extends SnowFlake {
|
||||
},
|
||||
);
|
||||
this.contextmenu.addSeperator();
|
||||
this.contextmenu.addButton(
|
||||
() => I18n.threads.leave(),
|
||||
function () {
|
||||
fetch(this.info.api + "/channels/" + this.id + "/thread-members/@me", {
|
||||
method: "DELETE",
|
||||
headers: this.headers,
|
||||
});
|
||||
},
|
||||
{
|
||||
visible: function () {
|
||||
return !!this.member;
|
||||
},
|
||||
},
|
||||
);
|
||||
this.contextmenu.addButton(
|
||||
() => I18n.threads.join(),
|
||||
function () {
|
||||
fetch(this.info.api + "/channels/" + this.id + "/thread-members/@me", {
|
||||
method: "POST",
|
||||
headers: this.headers,
|
||||
});
|
||||
},
|
||||
{
|
||||
visible: function () {
|
||||
return !this.member;
|
||||
},
|
||||
},
|
||||
);
|
||||
this.contextmenu.addSeperator();
|
||||
//TODO notifcations icon
|
||||
this.contextmenu.addButton(
|
||||
() => I18n.guild.notifications(),
|
||||
@@ -501,6 +531,7 @@ class Channel extends SnowFlake {
|
||||
);
|
||||
}
|
||||
last_pin_timestamp?: string;
|
||||
member?: threadMember;
|
||||
constructor(json: channeljson | -1, owner: Guild, id: string = json === -1 ? "" : json.id) {
|
||||
super(id);
|
||||
this.idToNext = owner.localuser.idToNext;
|
||||
@@ -513,6 +544,7 @@ class Channel extends SnowFlake {
|
||||
if (json === -1) {
|
||||
return;
|
||||
}
|
||||
this.member = json.member;
|
||||
this.rate_limit_per_user = json.rate_limit_per_user || 0;
|
||||
this.editing;
|
||||
this.type = json.type;
|
||||
@@ -527,7 +559,7 @@ class Channel extends SnowFlake {
|
||||
this.guild_id = json.guild_id;
|
||||
this.permission_overwrites = new Map();
|
||||
this.permission_overwritesar = [];
|
||||
for (const thing of json.permission_overwrites) {
|
||||
for (const thing of json.permission_overwrites || []) {
|
||||
if (!this.permission_overwrites.has(thing.id)) {
|
||||
//either a bug in the server requires this, or the API is cursed
|
||||
this.permission_overwrites.set(thing.id, new Permissions(thing.allow, thing.deny));
|
||||
@@ -560,6 +592,11 @@ class Channel extends SnowFlake {
|
||||
}
|
||||
this.setUpInfiniteScroller();
|
||||
this.perminfo ??= {};
|
||||
const read = this.localuser.unknownRead.get(this.id);
|
||||
if (read) {
|
||||
this.readStateInfo(read);
|
||||
this.localuser.unknownRead.delete(this.id);
|
||||
}
|
||||
}
|
||||
get perminfo() {
|
||||
return this.guild.perminfo.channels[this.id];
|
||||
@@ -714,7 +751,7 @@ class Channel extends SnowFlake {
|
||||
return a.position - b.position;
|
||||
});
|
||||
}
|
||||
resolveparent(_guild: Guild) {
|
||||
resolveparent(_guild: Guild = this.owner) {
|
||||
const parentid = this.parent_id;
|
||||
if (!parentid) return false;
|
||||
this.parent = this.localuser.channelids.get(parentid);
|
||||
@@ -754,7 +791,7 @@ class Channel extends SnowFlake {
|
||||
return [build, position] as const;
|
||||
}
|
||||
static dragged: [Channel, HTMLDivElement] | [] = [];
|
||||
html: WeakRef<HTMLElement> | undefined;
|
||||
html: WeakRef<HTMLDivElement> | undefined;
|
||||
get visible() {
|
||||
return this.hasPermission("VIEW_CHANNEL");
|
||||
}
|
||||
@@ -808,8 +845,12 @@ class Channel extends SnowFlake {
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
isThread() {
|
||||
return this.type === 10 || this.type === 11 || this.type === 12;
|
||||
}
|
||||
createguildHTML(admin = false): HTMLDivElement {
|
||||
const div = document.createElement("div");
|
||||
const div = this.html?.deref() || document.createElement("div");
|
||||
div.innerHTML = "";
|
||||
|
||||
if (this.muted) {
|
||||
div.classList.add("muted");
|
||||
@@ -820,6 +861,7 @@ class Channel extends SnowFlake {
|
||||
Math.min((this.mute_config?.end_time as number) - Date.now(), 2147483647),
|
||||
);
|
||||
}
|
||||
|
||||
this.html = new WeakRef(div);
|
||||
if (!this.visible) {
|
||||
let quit = true;
|
||||
@@ -832,7 +874,7 @@ class Channel extends SnowFlake {
|
||||
return div;
|
||||
}
|
||||
}
|
||||
div.draggable = admin;
|
||||
div.draggable = admin && !this.isThread();
|
||||
div.addEventListener("dragstart", (e) => {
|
||||
Channel.dragged = [this, div];
|
||||
e.stopImmediatePropagation();
|
||||
@@ -840,6 +882,14 @@ class Channel extends SnowFlake {
|
||||
div.addEventListener("dragend", () => {
|
||||
Channel.dragged = [];
|
||||
});
|
||||
const childrendiv = document.createElement("div");
|
||||
childrendiv.classList.add("channels");
|
||||
for (const channel of this.children.filter(
|
||||
(_) => !_.isThread() || _.member || this.localuser.channelfocus === _,
|
||||
)) {
|
||||
childrendiv.appendChild(channel.createguildHTML(admin));
|
||||
}
|
||||
|
||||
if (this.type === 4) {
|
||||
this.sortchildren();
|
||||
const caps = document.createElement("div");
|
||||
@@ -855,7 +905,7 @@ class Channel extends SnowFlake {
|
||||
this.nameSpan = new WeakRef(myhtml);
|
||||
decdiv.appendChild(myhtml);
|
||||
caps.appendChild(decdiv);
|
||||
const childrendiv = document.createElement("div");
|
||||
|
||||
if (admin) {
|
||||
const addchannel = document.createElement("span");
|
||||
addchannel.classList.add("addchannel", "svgicon", "svg-plus");
|
||||
@@ -872,16 +922,12 @@ class Channel extends SnowFlake {
|
||||
|
||||
Channel.contextmenu.bindContextmenu(decdiv, this, undefined);
|
||||
|
||||
for (const channel of this.children) {
|
||||
childrendiv.appendChild(channel.createguildHTML(admin));
|
||||
}
|
||||
childrendiv.classList.add("channels");
|
||||
setTimeout((_: any) => {
|
||||
if (!this.perminfo.collapsed) {
|
||||
childrendiv.style.height = childrendiv.scrollHeight + "px";
|
||||
}
|
||||
}, 100);
|
||||
div.appendChild(childrendiv);
|
||||
|
||||
if (this.perminfo.collapsed) {
|
||||
decoration.classList.add("hiddencat");
|
||||
childrendiv.style.height = "0px";
|
||||
@@ -909,10 +955,11 @@ class Channel extends SnowFlake {
|
||||
handleColapse();
|
||||
};
|
||||
} else {
|
||||
childrendiv.classList.add("threads");
|
||||
div.classList.add("channel");
|
||||
this.unreads();
|
||||
Channel.contextmenu.bindContextmenu(div, this, undefined);
|
||||
if (admin) {
|
||||
if (admin && !this.isThread()) {
|
||||
this.coatDropDiv(div);
|
||||
}
|
||||
const button = document.createElement("button");
|
||||
@@ -938,6 +985,7 @@ class Channel extends SnowFlake {
|
||||
this.updateVoiceUsers();
|
||||
}
|
||||
}
|
||||
div.appendChild(childrendiv);
|
||||
return div;
|
||||
}
|
||||
async moveForDrag(x: number) {
|
||||
@@ -1822,8 +1870,15 @@ class Channel extends SnowFlake {
|
||||
this.myhtml.classList.add("viewChannel");
|
||||
}
|
||||
const id = ++Channel.genid;
|
||||
|
||||
if (this.localuser.channelfocus && this.localuser.channelfocus !== this) {
|
||||
this.localuser.channelfocus.infinite.delete();
|
||||
|
||||
if (this.localuser.channelfocus.isThread() && !this.localuser.channelfocus.member) {
|
||||
const prev = this.localuser.channelfocus;
|
||||
this.localuser.channelfocus = this;
|
||||
prev.parent?.createguildHTML();
|
||||
}
|
||||
} else if (this.localuser.channelfocus === this && !aroundMessage) {
|
||||
if (this.lastmessageid)
|
||||
this.infinite.focus(aroundMessage || this.lastmessageid, !!aroundMessage, true);
|
||||
@@ -1833,6 +1888,13 @@ class Channel extends SnowFlake {
|
||||
this.guild.perminfo.prevchannel = this.id;
|
||||
this.localuser.channelfocus = this;
|
||||
|
||||
if (this.isThread() && !this.member) {
|
||||
this.parent?.createguildHTML();
|
||||
if (this.myhtml) {
|
||||
this.myhtml.classList.add("viewChannel");
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
this.nsfw && //@ts-ignore another hack
|
||||
(!this.perminfo.nsfwOk || !this.localuser.user.nsfw_allowed)
|
||||
@@ -2320,7 +2382,6 @@ class Channel extends SnowFlake {
|
||||
this.parent_id = undefined;
|
||||
}
|
||||
|
||||
this.children = [];
|
||||
this.guild_id = json.guild_id;
|
||||
const oldover = this.permission_overwrites;
|
||||
this.permission_overwrites = new Map();
|
||||
|
||||
+34
-10
@@ -1373,6 +1373,7 @@ class Guild extends SnowFlake {
|
||||
this.channels.push(temp);
|
||||
this.localuser.channelids.set(temp.id, temp);
|
||||
}
|
||||
|
||||
this.headchannels = [];
|
||||
for (const thing of this.channels) {
|
||||
const parent = thing.resolveparent(this);
|
||||
@@ -1380,6 +1381,11 @@ class Guild extends SnowFlake {
|
||||
this.headchannels.push(thing);
|
||||
}
|
||||
}
|
||||
for (const thread of json.threads) {
|
||||
const temp = new Channel(thread, this);
|
||||
this.localuser.channelids.set(temp.id, temp);
|
||||
temp.resolveparent(this);
|
||||
}
|
||||
this.prevchannel = this.localuser.channelids.get(this.perminfo.prevchannel);
|
||||
this.stickers = json.stickers.map((_) => new Sticker(_, this)) || [];
|
||||
}
|
||||
@@ -1675,6 +1681,21 @@ class Guild extends SnowFlake {
|
||||
noti.classList.add("notiunread");
|
||||
}
|
||||
}
|
||||
async goToThread(threadId: string) {
|
||||
if (!this.localuser.channelids.has(threadId)) {
|
||||
const channelJson = (await (
|
||||
await fetch(this.info.api + "/channels/" + threadId, {
|
||||
headers: this.headers,
|
||||
})
|
||||
).json()) as channeljson;
|
||||
const channel = new Channel(channelJson, this);
|
||||
this.localuser.channelids.set(channel.id, channel);
|
||||
channel.resolveparent(this);
|
||||
const par = this.localuser.channelids.get(channel.parent_id as string);
|
||||
par?.createguildHTML();
|
||||
}
|
||||
this.localuser.goToChannel(threadId);
|
||||
}
|
||||
getHTML() {
|
||||
const sideContainDiv = document.getElementById("sideContainDiv");
|
||||
if (sideContainDiv) {
|
||||
@@ -1737,6 +1758,9 @@ class Guild extends SnowFlake {
|
||||
if (channel) {
|
||||
await channel.getHTML(addstate, undefined, message);
|
||||
return;
|
||||
} else {
|
||||
await this.goToThread(ID);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.prevchannel && ID !== null && this.prevchannel.visible) {
|
||||
@@ -1809,22 +1833,22 @@ class Guild extends SnowFlake {
|
||||
updateChannel(json: channeljson) {
|
||||
const channel = this.localuser.channelids.get(json.id);
|
||||
if (channel) {
|
||||
const parent = channel.parent;
|
||||
channel.updateChannel(json);
|
||||
this.headchannels = [];
|
||||
for (const thing of this.channels) {
|
||||
thing.children = [];
|
||||
}
|
||||
this.headchannels = [];
|
||||
for (const thing of this.channels) {
|
||||
const parent = thing.resolveparent(this);
|
||||
if (!parent) {
|
||||
this.headchannels.push(thing);
|
||||
this.channels = this.channels.sort((a, b) => a.position - b.position);
|
||||
if (parent !== channel.parent) {
|
||||
if (parent) parent.children.filter((_) => _ !== channel);
|
||||
channel.resolveparent();
|
||||
} else if (parent && !json.parent_id) {
|
||||
this.headchannels.push(channel);
|
||||
for (const thing of this.channels) {
|
||||
thing.children = thing.children.filter((_) => _ !== channel);
|
||||
}
|
||||
}
|
||||
|
||||
for (const channel of this.channels) {
|
||||
channel.children = channel.children.sort((a, b) => a.position - b.position);
|
||||
}
|
||||
this.channels = this.channels.sort((a, b) => a.position - b.position);
|
||||
this.printServers();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,9 +84,9 @@ if (window.location.pathname.startsWith("/channels")) {
|
||||
}
|
||||
|
||||
regSwap(thisUser);
|
||||
thisUser.initwebsocket().then(() => {
|
||||
thisUser.initwebsocket().then(async () => {
|
||||
thisUser.loaduser();
|
||||
thisUser.init();
|
||||
await thisUser.init();
|
||||
const loading = document.getElementById("loading") as HTMLDivElement;
|
||||
loading.classList.add("doneloading");
|
||||
loading.classList.remove("loading");
|
||||
|
||||
@@ -48,13 +48,7 @@ interface readyjson {
|
||||
guilds: guildjson[];
|
||||
relationships: relationJson[];
|
||||
read_state: {
|
||||
entries: {
|
||||
id: string;
|
||||
channel_id: string;
|
||||
last_message_id: string;
|
||||
last_pin_timestamp: string;
|
||||
mention_count: number; //in theory, the server doesn't actually send this as far as I'm aware
|
||||
}[];
|
||||
entries: readStateEntry[];
|
||||
partial: boolean;
|
||||
version: number;
|
||||
};
|
||||
@@ -91,6 +85,13 @@ interface readyjson {
|
||||
};
|
||||
};
|
||||
}
|
||||
export interface readStateEntry {
|
||||
id: string;
|
||||
channel_id: string;
|
||||
last_message_id: string;
|
||||
last_pin_timestamp: string;
|
||||
mention_count: number; //in theory, the server doesn't actually send this as far as I'm aware
|
||||
}
|
||||
export interface sessionJson {
|
||||
active: boolean;
|
||||
activities: []; //will need to find example of this
|
||||
@@ -455,6 +456,7 @@ type emojipjson = emojijson & {
|
||||
type guildjson = {
|
||||
application_command_counts: {[key: string]: number};
|
||||
channels: channeljson[];
|
||||
threads: channeljson[];
|
||||
data_mode: string;
|
||||
emojis: emojipjson[];
|
||||
guild_scheduled_events: [];
|
||||
@@ -503,7 +505,6 @@ type guildjson = {
|
||||
roles: rolesjson[];
|
||||
stage_instances: [];
|
||||
stickers: stickerJson[];
|
||||
threads: [];
|
||||
version: string;
|
||||
guild_hashes: {};
|
||||
joined_at: string;
|
||||
@@ -530,7 +531,20 @@ type startTypingjson = {
|
||||
member?: memberjson;
|
||||
};
|
||||
};
|
||||
export interface threadMember {
|
||||
id: string;
|
||||
user_id: string;
|
||||
join_timestamp: string;
|
||||
flags: number;
|
||||
muted: boolean;
|
||||
mute_config?: {
|
||||
end_time?: string;
|
||||
selected_time_window?: number;
|
||||
};
|
||||
member?: memberjson;
|
||||
}
|
||||
type channeljson = {
|
||||
member: threadMember;
|
||||
id: string;
|
||||
rate_limit_per_user?: number;
|
||||
owner_id?: string;
|
||||
@@ -683,6 +697,7 @@ type messagejson = {
|
||||
emoji: emojijson; //very likely needs expanding
|
||||
me: boolean;
|
||||
}[];
|
||||
thread?: channeljson;
|
||||
interaction?: {
|
||||
id: string;
|
||||
type: 2 | 3;
|
||||
@@ -842,6 +857,18 @@ type wsjson =
|
||||
s: number;
|
||||
t: "MESSAGE_DELETE";
|
||||
}
|
||||
| {
|
||||
op: 0;
|
||||
t: "THREAD_MEMBERS_UPDATE";
|
||||
d: {
|
||||
guild_id: string;
|
||||
id: string;
|
||||
member_count: number;
|
||||
added_members?: [threadMember];
|
||||
removed_member_ids?: string[];
|
||||
};
|
||||
s: 3;
|
||||
}
|
||||
| {
|
||||
op: 0;
|
||||
d: {
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
messageCreateJson,
|
||||
messagejson,
|
||||
presencejson,
|
||||
readStateEntry,
|
||||
readyjson,
|
||||
startTypingjson,
|
||||
wsjson,
|
||||
@@ -122,10 +123,10 @@ class Localuser {
|
||||
sessionStorage.setItem("currentuser", specialUser.uid);
|
||||
localStorage.setItem("userinfos", JSON.stringify(Localuser.users));
|
||||
|
||||
thisUser.initwebsocket().then(() => {
|
||||
thisUser.initwebsocket().then(async () => {
|
||||
const loaddesc = document.getElementById("load-desc") as HTMLElement;
|
||||
thisUser.loaduser();
|
||||
thisUser.init();
|
||||
await thisUser.init();
|
||||
loading.classList.add("doneloading");
|
||||
loaddesc.textContent = I18n.loaded();
|
||||
loading.classList.remove("loading");
|
||||
@@ -331,6 +332,7 @@ class Localuser {
|
||||
}
|
||||
}
|
||||
guildFolders: guildFolder[] = [];
|
||||
unknownRead = new Map<string, readStateEntry>();
|
||||
async gottenReady(ready: readyjson): Promise<void> {
|
||||
await I18n.done;
|
||||
this.queryBlog();
|
||||
@@ -406,6 +408,7 @@ class Localuser {
|
||||
for (const thing of ready.d.read_state.entries) {
|
||||
const channel = this.channelids.get(thing.channel_id);
|
||||
if (!channel) {
|
||||
this.unknownRead.set(thing.channel_id, thing);
|
||||
continue;
|
||||
}
|
||||
channel.readStateInfo(thing);
|
||||
@@ -654,9 +657,9 @@ class Localuser {
|
||||
() => {
|
||||
if (this.swapped) return;
|
||||
loaddesc.textContent = I18n.retrying();
|
||||
this.initwebsocket().then(() => {
|
||||
this.initwebsocket().then(async () => {
|
||||
this.loaduser();
|
||||
this.init();
|
||||
await this.init();
|
||||
const loading = document.getElementById("loading") as HTMLElement;
|
||||
loading.classList.add("doneloading");
|
||||
loading.classList.remove("loading");
|
||||
@@ -695,6 +698,31 @@ class Localuser {
|
||||
}
|
||||
if (temp.op == 0) {
|
||||
switch (temp.t) {
|
||||
case "THREAD_MEMBERS_UPDATE": {
|
||||
const channel = this.channelids.get(temp.d.id);
|
||||
if (!channel) return;
|
||||
if (temp.d.added_members) {
|
||||
for (const memb of temp.d.added_members) {
|
||||
if (memb.user_id === this.user.id) {
|
||||
channel.member = memb;
|
||||
channel.parent?.createguildHTML();
|
||||
} else {
|
||||
//TODO store these somewhere
|
||||
}
|
||||
}
|
||||
}
|
||||
if (temp.d.removed_member_ids) {
|
||||
for (const id of temp.d.removed_member_ids) {
|
||||
if (id === this.user.id) {
|
||||
channel.member = undefined;
|
||||
channel.parent?.createguildHTML();
|
||||
} else {
|
||||
//TODO unstore these somewhere
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "INTERACTION_FAILURE":
|
||||
case "INTERACTION_CREATE":
|
||||
case "INTERACTION_SUCCESS":
|
||||
@@ -1507,7 +1535,7 @@ class Localuser {
|
||||
this.loadGuild(json.guild_id, true);
|
||||
}
|
||||
}
|
||||
init(): void {
|
||||
async init() {
|
||||
const location = window.location.href.split("/");
|
||||
this.buildservers();
|
||||
if (location[3] === "channels") {
|
||||
@@ -1515,7 +1543,7 @@ class Localuser {
|
||||
if (!guild) {
|
||||
return;
|
||||
}
|
||||
guild.loadChannel(location[5], true, location[6]);
|
||||
await guild.loadChannel(location[5], true, location[6]);
|
||||
this.channelfocus = this.channelids.get(location[5]);
|
||||
}
|
||||
}
|
||||
|
||||
+105
-2
@@ -8,7 +8,14 @@ import {Localuser} from "./localuser.js";
|
||||
import {Role} from "./role.js";
|
||||
import {File} from "./file.js";
|
||||
import {SnowFlake} from "./snowflake.js";
|
||||
import {emojijson, interactionEvents, memberjson, messagejson, userjson} from "./jsontypes.js";
|
||||
import {
|
||||
channeljson,
|
||||
emojijson,
|
||||
interactionEvents,
|
||||
memberjson,
|
||||
messagejson,
|
||||
userjson,
|
||||
} from "./jsontypes.js";
|
||||
import {Emoji} from "./emoji.js";
|
||||
import {mobile} from "./utils/utils.js";
|
||||
import {I18n} from "./i18n.js";
|
||||
@@ -118,6 +125,33 @@ class Message extends SnowFlake {
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
Message.contextmenu.addButton(
|
||||
() => I18n.message.createThread(),
|
||||
function () {
|
||||
const dio = new Dialog(I18n.message.threadOptions());
|
||||
const opt = dio.options.addForm(
|
||||
"",
|
||||
(body) => {
|
||||
const channelJson = body as channeljson;
|
||||
this.guild.goToThread(channelJson.id);
|
||||
dio.hide();
|
||||
},
|
||||
{
|
||||
fetchURL:
|
||||
this.info.api + "/channels/" + this.channel.id + "/messages/" + this.id + "/threads",
|
||||
headers: this.headers,
|
||||
},
|
||||
);
|
||||
opt.addTextInput(I18n.threads.name(), "name");
|
||||
dio.show();
|
||||
},
|
||||
{
|
||||
visible: function () {
|
||||
return this.channel.hasPermission("CREATE_PUBLIC_THREADS");
|
||||
},
|
||||
},
|
||||
);
|
||||
Message.contextmenu.addButton(
|
||||
() => I18n.message.reactions(),
|
||||
function (this: Message) {
|
||||
@@ -335,6 +369,7 @@ class Message extends SnowFlake {
|
||||
}
|
||||
components?: Components;
|
||||
edited_timestamp: string | null = null;
|
||||
thread?: Channel;
|
||||
giveData(messagejson: messagejson) {
|
||||
const func = this.channel.infinite.snapBottom();
|
||||
for (const thing of Object.keys(messagejson)) {
|
||||
@@ -370,6 +405,14 @@ class Message extends SnowFlake {
|
||||
} else if (thing === "components" && messagejson.components) {
|
||||
this.components = new Components(messagejson.components, this);
|
||||
continue;
|
||||
} else if (thing === "thread" && messagejson.thread) {
|
||||
let thread = this.localuser.channelids.get(messagejson.thread.id);
|
||||
if (!thread) {
|
||||
thread = new Channel(messagejson.thread, this.guild);
|
||||
thread.resolveparent();
|
||||
this.localuser.channelids.set(thread.id, thread);
|
||||
this.thread = thread;
|
||||
}
|
||||
}
|
||||
(this as any)[thing] = (messagejson as any)[thing];
|
||||
}
|
||||
@@ -606,6 +649,15 @@ class Message extends SnowFlake {
|
||||
if (div === this.div) {
|
||||
this.div.classList.add("messagediv");
|
||||
}
|
||||
if (this.type === 21) {
|
||||
this.channel.parent?.getmessage(this.message_reference?.message_id as string).then((_) => {
|
||||
const gen = _?.generateMessage(undefined, undefined, div);
|
||||
if (!gen) {
|
||||
//idk
|
||||
}
|
||||
});
|
||||
return div;
|
||||
}
|
||||
|
||||
const editmode = this.channel.editing === this;
|
||||
if (!premessage && !dupe) {
|
||||
@@ -722,7 +774,7 @@ class Message extends SnowFlake {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.message_reference && this.type !== 6) {
|
||||
if (this.message_reference && this.type !== 6 && this.type !== 18) {
|
||||
const replyline = document.createElement("div");
|
||||
|
||||
const minipfp = document.createElement("img");
|
||||
@@ -1031,6 +1083,38 @@ class Message extends SnowFlake {
|
||||
afterText.classList.add("pinText");
|
||||
text.append(afterText);
|
||||
|
||||
const time = document.createElement("span");
|
||||
time.textContent = " " + formatTime(new Date(this.timestamp));
|
||||
time.classList.add("timestamp");
|
||||
text.append(time);
|
||||
div.classList.add("topMessage");
|
||||
} else if (this.type === 18) {
|
||||
const text = document.createElement("div");
|
||||
build.appendChild(text);
|
||||
|
||||
const m = I18n.message.pin("|||", "???").split("|||");
|
||||
if (m.length === 2) text.append(m.shift() as string);
|
||||
|
||||
const username = document.createElement("span");
|
||||
username.textContent = this.author.name;
|
||||
//this.author.profileclick(username);
|
||||
this.author.bind(username, this.guild);
|
||||
text.appendChild(username);
|
||||
username.classList.add("username");
|
||||
const midText = m[0].split("???");
|
||||
|
||||
const afterText = document.createElement("span");
|
||||
afterText.textContent = midText[0];
|
||||
text.append(afterText);
|
||||
|
||||
const threadName = document.createElement("span");
|
||||
threadName.textContent = this.content.rawString;
|
||||
threadName.classList.add("pinText");
|
||||
text.append(threadName);
|
||||
threadName.onclick = () => {
|
||||
this.guild.goToThread(this.message_reference?.channel_id as string);
|
||||
};
|
||||
|
||||
const time = document.createElement("span");
|
||||
time.textContent = " " + formatTime(new Date(this.timestamp));
|
||||
time.classList.add("timestamp");
|
||||
@@ -1111,6 +1195,25 @@ class Message extends SnowFlake {
|
||||
}
|
||||
this.bindButtonEvent();
|
||||
|
||||
if (!dupe && this.thread) {
|
||||
const thread = this.thread;
|
||||
const threadBox = document.createElement("div");
|
||||
threadBox.classList.add("flexttb", "threadBox");
|
||||
const topRow = document.createElement("div");
|
||||
topRow.classList.add("flexltr");
|
||||
const title = document.createElement("span");
|
||||
title.textContent = thread.name;
|
||||
topRow.onclick = () => {
|
||||
this.localuser.goToChannel(thread.id);
|
||||
};
|
||||
const messages = document.createElement("span");
|
||||
messages.classList.add("clickable");
|
||||
messages.textContent = I18n.message.messages("10");
|
||||
topRow.append(title, messages);
|
||||
threadBox.append(topRow);
|
||||
div.append(threadBox);
|
||||
}
|
||||
|
||||
return div;
|
||||
}
|
||||
bindButtonEvent() {
|
||||
|
||||
+55
-2
@@ -1706,6 +1706,33 @@ span.instanceStatus {
|
||||
color: var(--primary-text-soft);
|
||||
overflow-y: auto;
|
||||
}
|
||||
.threads {
|
||||
button {
|
||||
position: relative;
|
||||
}
|
||||
button::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
height: calc(50% - 1px);
|
||||
width: 3px;
|
||||
border-bottom: 2px solid var(--reply-line);
|
||||
border-left: 2px solid var(--reply-line);
|
||||
border-bottom-left-radius: 8px;
|
||||
}
|
||||
button::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
height: calc(50% - 1px);
|
||||
width: 3px;
|
||||
border-top: 2px solid var(--reply-line);
|
||||
border-left: 2px solid var(--reply-line);
|
||||
border-top-left-radius: 8px;
|
||||
}
|
||||
}
|
||||
.channels {
|
||||
overflow-y: hidden;
|
||||
transition: height 0.2s ease-in-out;
|
||||
@@ -1744,8 +1771,8 @@ span.instanceStatus {
|
||||
.channels .channelbutton {
|
||||
margin-left: 8px;
|
||||
}
|
||||
.viewChannel .channelbutton,
|
||||
.viewChannel .channelbutton:hover {
|
||||
.viewChannel > .channelbutton,
|
||||
.viewChannel > .channelbutton:hover {
|
||||
background: var(--channel-selected);
|
||||
font-weight: bold;
|
||||
color: var(--primary-text-prominent);
|
||||
@@ -4636,3 +4663,29 @@ img.error::after {
|
||||
object-fit: cover;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.threadBox {
|
||||
padding: 6px;
|
||||
background: #00000063;
|
||||
border-radius: 4px;
|
||||
margin: 6px;
|
||||
min-width: 300px;
|
||||
width: fit-content;
|
||||
margin-left: 50px;
|
||||
margin-top: 10px;
|
||||
position: relative;
|
||||
::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
left: -32px;
|
||||
height: calc(100% - 8px);
|
||||
width: 26px;
|
||||
border-bottom: 2px solid var(--reply-line);
|
||||
border-left: 2px solid var(--reply-line);
|
||||
border-bottom-left-radius: 8px;
|
||||
}
|
||||
.clickable {
|
||||
color: var(--link);
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
@@ -137,6 +137,11 @@
|
||||
"unmute": "Unmute Channel",
|
||||
"voice": "Voice"
|
||||
},
|
||||
"threads":{
|
||||
"leave":"Leave Thread",
|
||||
"join":"Join Thread",
|
||||
"name":"Name:"
|
||||
},
|
||||
"channelLink": "# $1",
|
||||
"clientDesc": "Client version: $1\n\n[Join the official Fermi guild]($2/invite/USgYJo?instance=https%3A%2F%2Fspacebar.chat)\n\n[Help translate Fermi](https://translatewiki.net/wiki/Translating:JankClient#sortable:3=desc) \n\n[Help create Fermi](https://github.com/MathMan05/Fermi)\n\n[Help maintain the server Fermi relies on](https://github.com/spacebarchat/server)\n\n[Read the blog](https://blog.fermi.chat/)\n\nCalculated rights: $3",
|
||||
"commands": {
|
||||
@@ -555,6 +560,7 @@
|
||||
"timeoutTime": "Timeout Time:"
|
||||
},
|
||||
"message": {
|
||||
"messages":"$1 {{PLURAL:$1|Message|Messages}} >",
|
||||
"andMore": "$1, and more!",
|
||||
"attached": "Sent an attachment",
|
||||
"delete": "Delete message",
|
||||
@@ -564,8 +570,11 @@
|
||||
"edited": "(edited)",
|
||||
"fullMessage": "Full message:",
|
||||
"pin": "$1 has pinned a message",
|
||||
"pin": "$1 has created a thread: $2",
|
||||
"reactedWith": "Reacted with $1",
|
||||
"reactionAdd": "Add reaction",
|
||||
"createThread":"Create Thread",
|
||||
"threadOptions":"Thread options",
|
||||
"reactions": "View Reactions",
|
||||
"reactionsTitle": "Reactions",
|
||||
"retry": "Resend errored message",
|
||||
|
||||
Reference in new issue
Block a user