mirror of
https://github.com/chylex/Discord-History-Tracker.git
synced 2025-07-04 10:38:52 +02:00
Compare commits
11 Commits
5533505731
...
2600da8a08
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2600da8a08 | ||
![]() |
7ba012ef5c | ||
![]() |
c52572b387 | ||
![]() |
5ba80dc12f | ||
![]() |
37a0feddcc | ||
![]() |
47f448dcde | ||
![]() |
0281b49815 | ||
![]() |
648b221bb8 | ||
![]() |
7d8558ae04 | ||
![]() |
41053549ab | ||
![]() |
f279bb4d16 |
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
<link rel="stylesheet" href="styles/main.css">
|
<link rel="stylesheet" href="styles/main.css">
|
||||||
<link rel="stylesheet" href="styles/menu.css">
|
<link rel="stylesheet" href="styles/menu.css">
|
||||||
|
<link rel="stylesheet" href="styles/servers.css">
|
||||||
<link rel="stylesheet" href="styles/channels.css">
|
<link rel="stylesheet" href="styles/channels.css">
|
||||||
<link rel="stylesheet" href="styles/messages.css">
|
<link rel="stylesheet" href="styles/messages.css">
|
||||||
<link rel="stylesheet" href="styles/modal.css">
|
<link rel="stylesheet" href="styles/modal.css">
|
||||||
@ -75,6 +76,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="app">
|
<div id="app">
|
||||||
|
<div id="servers"></div>
|
||||||
<div id="channels">
|
<div id="channels">
|
||||||
<div class="loading"></div>
|
<div class="loading"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,6 +2,7 @@ import discord from "./discord.mjs";
|
|||||||
import gui from "./gui.mjs";
|
import gui from "./gui.mjs";
|
||||||
import state from "./state.mjs";
|
import state from "./state.mjs";
|
||||||
import "./polyfills.mjs";
|
import "./polyfills.mjs";
|
||||||
|
import servers from "./servers.mjs";
|
||||||
|
|
||||||
window.DISCORD = discord;
|
window.DISCORD = discord;
|
||||||
|
|
||||||
@ -25,10 +26,12 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
|
|
||||||
state.onUsersRefreshed(users => {
|
state.onUsersRefreshed(users => {
|
||||||
gui.updateUserList(users);
|
gui.updateUserList(users);
|
||||||
|
servers.update()
|
||||||
});
|
});
|
||||||
|
|
||||||
state.onChannelsRefreshed((channels, selected) => {
|
state.onChannelsRefreshed((channels, selected) => {
|
||||||
gui.updateChannelList(channels, selected, state.selectChannel);
|
gui.updateChannelList(channels, selected, state.selectChannel);
|
||||||
|
servers.update()
|
||||||
});
|
});
|
||||||
|
|
||||||
state.onMessagesRefreshed(messages => {
|
state.onMessagesRefreshed(messages => {
|
||||||
|
@ -113,16 +113,17 @@ export default (function() {
|
|||||||
return {
|
return {
|
||||||
setup() {
|
setup() {
|
||||||
templateChannelServer = new template([
|
templateChannelServer = new template([
|
||||||
"<div class='channel' data-channel='{id}'>",
|
"<div class='channel ServerChannel' data-channel='{id}' server-id='{serverId}' server-name='{server.name}' server-type='{server.type}'>",
|
||||||
"<div class='info' title='{topic}'><strong class='name'>#{name}</strong>{nsfw}<span class='tag'>{msgcount}</span></div>",
|
"<div class='info' title='{topic}'><strong class='name'>#{name}</strong>{nsfw}<span class='tag'>{msgcount}</span></div>",
|
||||||
"<span class='server'>{server.name} ({server.type})</span>",
|
"<!--<span class='server'>{server.name} ({server.type})</span>-->",
|
||||||
"</div>"
|
"</div>"
|
||||||
].join(""));
|
].join(""));
|
||||||
|
|
||||||
templateChannelPrivate = new template([
|
templateChannelPrivate = new template([
|
||||||
"<div class='channel' data-channel='{id}'>",
|
"<div class='channel UserChannel' data-channel='{id}' server-id='0' server-name='{server.name}' server-type='{server.type}'>",
|
||||||
|
"<div class='avatar'>{icon}</div>",
|
||||||
"<div class='info'><strong class='name'>{name}</strong><span class='tag'>{msgcount}</span></div>",
|
"<div class='info'><strong class='name'>{name}</strong><span class='tag'>{msgcount}</span></div>",
|
||||||
"<span class='server'>({server.type})</span>",
|
"<!--<span class='server'>{server.name} ({server.type})</span>-->",
|
||||||
"</div>"
|
"</div>"
|
||||||
].join(""));
|
].join(""));
|
||||||
|
|
||||||
@ -166,7 +167,7 @@ export default (function() {
|
|||||||
|
|
||||||
// noinspection HtmlUnknownTarget
|
// noinspection HtmlUnknownTarget
|
||||||
templateEmbedImageWithSize = new template([
|
templateEmbedImageWithSize = new template([
|
||||||
"<a href='{url}' class='embed thumbnail loading'><img src='{src}' width='{width}' height='{height}' alt='' onload='window.DISCORD.handleImageLoad(this)' onerror='window.DISCORD.handleImageLoadError(this)'></a><br>"
|
"<a href='{url}' class='embed thumbnail loading'><img src='{src}' width='{width}' alt='' onload='window.DISCORD.handleImageLoad(this)' onerror='window.DISCORD.handleImageLoadError(this)'></a><br>"
|
||||||
].join(""));
|
].join(""));
|
||||||
|
|
||||||
// noinspection HtmlUnknownTarget
|
// noinspection HtmlUnknownTarget
|
||||||
|
109
app/Resources/Viewer/scripts/servers.mjs
Normal file
109
app/Resources/Viewer/scripts/servers.mjs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
import state from "./state.mjs";
|
||||||
|
|
||||||
|
const servers = (() => {
|
||||||
|
let currentServerId = "0";
|
||||||
|
|
||||||
|
function getIcon(name) {
|
||||||
|
return name.split(" ").map(word => {
|
||||||
|
if (word.startsWith("[") && word.length > 1) return word[1];
|
||||||
|
return word[0] || "";
|
||||||
|
}).join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
const channels = document.querySelectorAll("#channels .channel");
|
||||||
|
const serversMap = new Map();
|
||||||
|
|
||||||
|
// Check if there are any channels with server-id 0 (DM)
|
||||||
|
const hasDMChannels = Array.from(channels).some(channel => {
|
||||||
|
return channel.getAttribute("server-id") === "0";
|
||||||
|
});
|
||||||
|
|
||||||
|
if (hasDMChannels) {
|
||||||
|
serversMap.set("0", {
|
||||||
|
id: "0",
|
||||||
|
name: "DM",
|
||||||
|
icon: "DM",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
channels.forEach(channel => {
|
||||||
|
const serverId = channel.getAttribute("server-id") || "0";
|
||||||
|
const serverType = channel.getAttribute("server-type");
|
||||||
|
const serverName = channel.getAttribute("server-name");
|
||||||
|
|
||||||
|
if (serverType === "server" && !serversMap.has(serverId)) {
|
||||||
|
serversMap.set(serverId, {
|
||||||
|
id: serverId,
|
||||||
|
name: serverName,
|
||||||
|
icon: getIcon(serverName),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const serversDiv = document.getElementById("servers");
|
||||||
|
serversDiv.innerHTML = "";
|
||||||
|
|
||||||
|
if (hasDMChannels) {
|
||||||
|
const dmServer = serversMap.get("0");
|
||||||
|
const dmElement = document.createElement("div");
|
||||||
|
dmElement.className = `Server${dmServer.id === currentServerId ? " active" : ""}`;
|
||||||
|
dmElement.id = "DM";
|
||||||
|
dmElement.dataset.serverId = dmServer.id;
|
||||||
|
dmElement.innerHTML = `
|
||||||
|
<div class="icon">DM</div>
|
||||||
|
<div class="name" title="Direct Messages">Direct Messages</div>
|
||||||
|
`;
|
||||||
|
dmElement.addEventListener("click", () => selectServer(dmServer.id));
|
||||||
|
serversDiv.appendChild(dmElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
serversMap.forEach(server => {
|
||||||
|
if (server.id === "0") return; // Skip DM since it's already added
|
||||||
|
|
||||||
|
const serverElement = document.createElement("div");
|
||||||
|
serverElement.className = `Server${server.id === currentServerId ? " active" : ""}`;
|
||||||
|
serverElement.dataset.serverId = server.id;
|
||||||
|
serverElement.innerHTML = `
|
||||||
|
<div class="icon">${server.icon}</div>
|
||||||
|
<div class="name" title="${server.name}">${server.name}</div>
|
||||||
|
`;
|
||||||
|
serverElement.addEventListener("click", () => selectServer(server.id));
|
||||||
|
serversDiv.appendChild(serverElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!serversMap.has(currentServerId)) {
|
||||||
|
currentServerId = "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
updateChannelVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectServer(serverId) {
|
||||||
|
// Remove active class from all servers
|
||||||
|
document.querySelectorAll("#servers .Server").forEach(server => {
|
||||||
|
server.classList.remove("active");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add active class to the selected server
|
||||||
|
const selectedServer = document.querySelector(`#servers .Server[data-server-id="${serverId}"]`);
|
||||||
|
if (selectedServer) {
|
||||||
|
selectedServer.classList.add("active");
|
||||||
|
}
|
||||||
|
|
||||||
|
currentServerId = serverId;
|
||||||
|
updateChannelVisibility();
|
||||||
|
state.selectChannel(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateChannelVisibility() {
|
||||||
|
document.querySelectorAll("#channels .channel").forEach(channel => {
|
||||||
|
const channelServerId = channel.getAttribute("server-id") || "0";
|
||||||
|
channel.classList.toggle("visible", channelServerId === currentServerId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return { update };
|
||||||
|
})();
|
||||||
|
|
||||||
|
export default servers;
|
@ -2,13 +2,25 @@ import settings from "./settings.mjs";
|
|||||||
import processor from "./processor.mjs";
|
import processor from "./processor.mjs";
|
||||||
|
|
||||||
// noinspection FunctionWithInconsistentReturnsJS
|
// noinspection FunctionWithInconsistentReturnsJS
|
||||||
export default (function() {
|
export default (function () {
|
||||||
/**
|
/**
|
||||||
* @type {{}}
|
* @type {{}}
|
||||||
* @property {{}} users
|
* @property {{}} users
|
||||||
* @property {{}} servers
|
* @property {{}} servers
|
||||||
* @property {{}} channels
|
* @property {{}} channels
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
const fileUrlProcessor = function (serverToken) {
|
||||||
|
if (typeof serverToken === "string") {
|
||||||
|
return url => "/get-downloaded-file/" + encodeURIComponent(url) + "?token=" + encodeURIComponent(serverToken);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return url => url;
|
||||||
|
}
|
||||||
|
}(window.DHT_SERVER_TOKEN);
|
||||||
|
|
||||||
|
|
||||||
let loadedFileMeta;
|
let loadedFileMeta;
|
||||||
let loadedFileData;
|
let loadedFileData;
|
||||||
|
|
||||||
@ -19,19 +31,39 @@ export default (function() {
|
|||||||
let currentPage;
|
let currentPage;
|
||||||
let messagesPerPage;
|
let messagesPerPage;
|
||||||
|
|
||||||
const getUser = function(id) {
|
const getUser = function (id) {
|
||||||
return loadedFileMeta.users[id] || { "name": "<unknown>" };
|
return loadedFileMeta.users[id] || { "name": "<unknown>" };
|
||||||
};
|
};
|
||||||
|
|
||||||
const getUserList = function() {
|
const getUserList = function () {
|
||||||
return loadedFileMeta ? loadedFileMeta.users : [];
|
return loadedFileMeta ? loadedFileMeta.users : [];
|
||||||
};
|
};
|
||||||
|
|
||||||
const getServer = function(id) {
|
const getServer = function (id) {
|
||||||
return loadedFileMeta.servers[id] || { "name": "<unknown>", "type": "unknown" };
|
return loadedFileMeta.servers[id] || { "name": "<unknown>", "type": "unknown" };
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateChannelHierarchy = function() {
|
const getUserIDByName = function (name) {
|
||||||
|
for (let userId in loadedFileMeta.users) {
|
||||||
|
let user = loadedFileMeta.users[userId];
|
||||||
|
if (user.name === name) {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getUserByName = function (name) {
|
||||||
|
for (let userId in loadedFileMeta.users) {
|
||||||
|
let user = loadedFileMeta.users[userId];
|
||||||
|
if (user.name === name) {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateChannelHierarchy = function () {
|
||||||
/**
|
/**
|
||||||
* @type {Map<string, Set>}
|
* @type {Map<string, Set>}
|
||||||
*/
|
*/
|
||||||
@ -55,7 +87,7 @@ export default (function() {
|
|||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [ id, channel ] of Object.entries(loadedFileMeta.channels)) {
|
for (const [id, channel] of Object.entries(loadedFileMeta.channels)) {
|
||||||
getChildren(channel.parent || "").add(id);
|
getChildren(channel.parent || "").add(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +120,7 @@ export default (function() {
|
|||||||
return hierarchy;
|
return hierarchy;
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateChannelOrder = function() {
|
const generateChannelOrder = function () {
|
||||||
if (!loadedFileMeta) {
|
if (!loadedFileMeta) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -136,7 +168,7 @@ export default (function() {
|
|||||||
return orderMap;
|
return orderMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getChannelList = function() {
|
const getChannelList = function () {
|
||||||
if (!loadedFileMeta) {
|
if (!loadedFileMeta) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -144,23 +176,28 @@ export default (function() {
|
|||||||
const channels = loadedFileMeta.channels;
|
const channels = loadedFileMeta.channels;
|
||||||
const channelOrder = generateChannelOrder();
|
const channelOrder = generateChannelOrder();
|
||||||
|
|
||||||
|
|
||||||
return Object.keys(channels).map(key => ({
|
return Object.keys(channels).map(key => ({
|
||||||
"id": key,
|
"id": key,
|
||||||
|
"serverId": channels[key].server,
|
||||||
"name": channels[key].name,
|
"name": channels[key].name,
|
||||||
"server": getServer(channels[key].server),
|
"server": getServer(channels[key].server),
|
||||||
"msgcount": getFilteredMessageKeys(key).length,
|
"msgcount": getFilteredMessageKeys(key).length,
|
||||||
"topic": channels[key].topic || "",
|
"topic": channels[key].topic || "",
|
||||||
"nsfw": channels[key].nsfw || false,
|
"nsfw": channels[key].nsfw || false,
|
||||||
|
"icon": getServer(channels[key].server).type === "group"
|
||||||
|
? `<!--<span>${channels[key].name.split(" ").map(word => word[0]).join("")}</span>-->` //Discord default naming without a icon
|
||||||
|
: `<img src='${fileUrlProcessor("https://cdn.discordapp.com/avatars/" + getUserIDByName(channels[key].name) + "/" + getUserByName(channels[key].name).avatar+".webp")}'>`
|
||||||
})).sort((ac, bc) => {
|
})).sort((ac, bc) => {
|
||||||
return channelOrder[ac.id] - channelOrder[bc.id];
|
return channelOrder[ac.id] - channelOrder[bc.id];
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getMessages = function(channel) {
|
const getMessages = function (channel) {
|
||||||
return loadedFileData[channel] || {};
|
return loadedFileData[channel] || {};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getMessageById = function(id) {
|
const getMessageById = function (id) {
|
||||||
for (const messages of Object.values(loadedFileData)) {
|
for (const messages of Object.values(loadedFileData)) {
|
||||||
if (id in messages) {
|
if (id in messages) {
|
||||||
return messages[id];
|
return messages[id];
|
||||||
@ -170,8 +207,8 @@ export default (function() {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getMessageChannel = function(id) {
|
const getMessageChannel = function (id) {
|
||||||
for (const [ channel, messages ] of Object.entries(loadedFileData)) {
|
for (const [channel, messages] of Object.entries(loadedFileData)) {
|
||||||
if (id in messages) {
|
if (id in messages) {
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
@ -180,7 +217,7 @@ export default (function() {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getMessageList = function() {
|
const getMessageList = function () {
|
||||||
if (!loadedMessages) {
|
if (!loadedMessages) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -252,19 +289,19 @@ export default (function() {
|
|||||||
let eventOnChannelsRefreshed;
|
let eventOnChannelsRefreshed;
|
||||||
let eventOnMessagesRefreshed;
|
let eventOnMessagesRefreshed;
|
||||||
|
|
||||||
const triggerUsersRefreshed = function() {
|
const triggerUsersRefreshed = function () {
|
||||||
eventOnUsersRefreshed && eventOnUsersRefreshed(getUserList());
|
eventOnUsersRefreshed && eventOnUsersRefreshed(getUserList());
|
||||||
};
|
};
|
||||||
|
|
||||||
const triggerChannelsRefreshed = function(selectedChannel) {
|
const triggerChannelsRefreshed = function (selectedChannel) {
|
||||||
eventOnChannelsRefreshed && eventOnChannelsRefreshed(getChannelList(), selectedChannel);
|
eventOnChannelsRefreshed && eventOnChannelsRefreshed(getChannelList(), selectedChannel);
|
||||||
};
|
};
|
||||||
|
|
||||||
const triggerMessagesRefreshed = function() {
|
const triggerMessagesRefreshed = function () {
|
||||||
eventOnMessagesRefreshed && eventOnMessagesRefreshed(getMessageList());
|
eventOnMessagesRefreshed && eventOnMessagesRefreshed(getMessageList());
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFilteredMessageKeys = function(channel) {
|
const getFilteredMessageKeys = function (channel) {
|
||||||
const messages = getMessages(channel);
|
const messages = getMessages(channel);
|
||||||
let keys = Object.keys(messages);
|
let keys = Object.keys(messages);
|
||||||
|
|
||||||
|
@ -8,15 +8,21 @@ export default class {
|
|||||||
};
|
};
|
||||||
|
|
||||||
apply(obj, processor) {
|
apply(obj, processor) {
|
||||||
|
|
||||||
|
//Keys to not escape
|
||||||
|
const allowHTMLKeys = new Set(["icon"]); //Example with more: Set(["icon", "description", "content"]);
|
||||||
|
|
||||||
return this.contents.replace(TEMPLATE_REGEX, (full, match) => {
|
return this.contents.replace(TEMPLATE_REGEX, (full, match) => {
|
||||||
const value = match.split(".").reduce((o, property) => o[property], obj);
|
const value = match.split(".").reduce((o, property) => o[property], obj);
|
||||||
|
|
||||||
if (processor) {
|
if (processor) {
|
||||||
const updated = processor(match, value);
|
const updated = processor(match, value);
|
||||||
return typeof updated === "undefined" ? dom.escapeHTML(value) : updated;
|
return typeof updated === "undefined" ? (allowHTMLKeys.has(match) ? value : dom.escapeHTML(value)) : updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dom.escapeHTML(value);
|
|
||||||
|
return allowHTMLKeys.has(match) ? value : dom.escapeHTML(value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,9 @@
|
|||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
color: #eee;
|
color: #eee;
|
||||||
background-color: #1c1e22;
|
background-color: #2B2D31;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
|
padding: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#channels > div.loading {
|
#channels > div.loading {
|
||||||
@ -14,27 +15,93 @@
|
|||||||
height: 150px;
|
height: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#channels > div.channel {
|
#channels > div.loading {
|
||||||
cursor: pointer;
|
background-color: rgba(0, 0, 0, 0) !important;
|
||||||
padding: 10px 12px;
|
|
||||||
border-bottom: 1px solid #333333;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#channels > div.channel:hover, #channels > div.channel.active {
|
|
||||||
background-color: #282b30;
|
#channels > div.channel.visible {
|
||||||
|
display: flex !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#channels > div.channel {
|
||||||
|
display: none !important;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px 8px;
|
||||||
|
|
||||||
|
color: #eee;
|
||||||
|
font-size: 15px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.ServerChannel {
|
||||||
|
padding: 8px 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#channels > div.channel:hover,
|
||||||
|
#channels > div.channel.active {
|
||||||
|
background-color: rgba(78, 80, 88, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
#channels > div.channel.active > .info > .name {
|
||||||
|
color: oklab(0.999994 0.0000455678 0.0000200868);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#channels .info {
|
#channels .info {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 16px;
|
width: 100%;
|
||||||
margin-bottom: 4px;
|
}
|
||||||
|
|
||||||
|
.ServerChannel > .info {
|
||||||
|
padding: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.UserChannel > .info {
|
||||||
|
align-self: center;
|
||||||
|
padding-left: 6px !important;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
width: 150px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[server-type="group"] > .info {
|
||||||
|
padding: 6px;
|
||||||
|
|
||||||
|
width: 172px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.UserChannel > .info > .name {
|
||||||
|
min-height: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#channels .name {
|
#channels .name {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: clip;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
color: oklab(0.686636 -0.00407365 -0.0149199);
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 16px;
|
||||||
|
/* max-width: 200px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.ServerChannel .name {
|
||||||
|
height: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#channels .tag {
|
#channels .tag {
|
||||||
@ -46,3 +113,25 @@
|
|||||||
padding: 2px 5px;
|
padding: 2px 5px;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#channels > div:hover,
|
||||||
|
#channels > div.active {
|
||||||
|
background-color: #404249
|
||||||
|
}
|
||||||
|
|
||||||
|
#channels > div > .avatar {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#channels > div > .avatar > * {
|
||||||
|
width: 30px;
|
||||||
|
|
||||||
|
min-width: 30px;
|
||||||
|
min-height: 30px;
|
||||||
|
/*Make not loaded images be 30px*/
|
||||||
|
|
||||||
|
border-radius: 100%;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
@ -17,6 +17,10 @@ body {
|
|||||||
--loading-backdrop: rgba(0, 0, 0, 0);
|
--loading-backdrop: rgba(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.loading:hover {
|
||||||
|
background-color: rgba(0, 0, 0, 0) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.loading::after {
|
.loading::after {
|
||||||
content: "";
|
content: "";
|
||||||
background: var(--loading-backdrop)
|
background: var(--loading-backdrop)
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
background-color: #17181c;
|
background-color: #313338;
|
||||||
border-bottom: 1px dotted #5d626b;
|
border-bottom: 2px solid #27292D;
|
||||||
}
|
}
|
||||||
|
|
||||||
#menu .splitter {
|
#menu .splitter {
|
||||||
@ -23,7 +23,9 @@
|
|||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
#menu button, #menu select, #menu input[type="text"] {
|
#menu button,
|
||||||
|
#menu select,
|
||||||
|
#menu input[type="text"] {
|
||||||
height: 31px;
|
height: 31px;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
background-color: #7289da;
|
background-color: #7289da;
|
||||||
@ -64,11 +66,13 @@
|
|||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#menu .nav > button, #menu .nav > p {
|
#menu .nav > button,
|
||||||
|
#menu .nav > p {
|
||||||
margin: 0 1px;
|
margin: 0 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#opt-filter-list > select, #opt-filter-list > input {
|
#opt-filter-list > select,
|
||||||
|
#opt-filter-list > input {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,9 +5,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#messages > div {
|
#messages > div {
|
||||||
margin: 0 24px;
|
padding: 0 4px 0 24px;
|
||||||
padding: 4px 0 12px;
|
|
||||||
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
|
margin-bottom: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#messages > div:hover {
|
||||||
|
background-color: oklab(0.0846607 0.00000385568 0.00000169128 / 0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
#messages h2 {
|
#messages h2 {
|
||||||
@ -23,6 +28,8 @@
|
|||||||
align-content: flex-start;
|
align-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#messages .avatar-wrapper > div {
|
#messages .avatar-wrapper > div {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
@ -50,14 +57,9 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
letter-spacing: 0;
|
letter-spacing: 0;
|
||||||
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#messages .info::before {
|
|
||||||
content: "\2022";
|
|
||||||
text-align: center;
|
|
||||||
display: inline-block;
|
|
||||||
width: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#messages .jump {
|
#messages .jump {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -66,20 +68,22 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.message {
|
.message {
|
||||||
margin-top: 6px;
|
margin-top: 2px;
|
||||||
color: rgba(255, 255, 255, 0.7);
|
color: oklab(0.89908 -0.00192907 -0.0048306);
|
||||||
font-size: 15px;
|
font-size: 16px;
|
||||||
line-height: 1.1em;
|
line-height: 1.1em;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message .link, .reply-message .link {
|
.message .link,
|
||||||
|
.reply-message .link {
|
||||||
color: #7289da;
|
color: #7289da;
|
||||||
background-color: rgba(115, 139, 215, 0.1);
|
background-color: rgba(115, 139, 215, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.message a, .reply-message a {
|
.message a,
|
||||||
|
.reply-message a {
|
||||||
color: #0096cf;
|
color: #0096cf;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
@ -126,7 +130,8 @@
|
|||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message .embed:first-child, .message .download + .download {
|
.message .embed:first-child,
|
||||||
|
.message .download+.download {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
79
app/Resources/Viewer/styles/servers.css
Normal file
79
app/Resources/Viewer/styles/servers.css
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#servers {
|
||||||
|
width: 76px;
|
||||||
|
background-color: #1e1f22;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Server {
|
||||||
|
width: 54px;
|
||||||
|
height: 54px;
|
||||||
|
margin-left: 11px;
|
||||||
|
margin-top: 8px;
|
||||||
|
border-radius: 100%;
|
||||||
|
transition: .15s ease-out;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #313338;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Server:hover {
|
||||||
|
border-radius: 20px;
|
||||||
|
background-color: #5865f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Server.active {
|
||||||
|
border-radius: 20px;
|
||||||
|
background-color: #5865f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ServerImg {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg.ServerImg {
|
||||||
|
width: 100%;
|
||||||
|
height: 70%;
|
||||||
|
/* margin-top: 15%; */
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#servers .Server .icon {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.5em;
|
||||||
|
text-align: center;
|
||||||
|
word-wrap: break-word;
|
||||||
|
word-break: break-all;
|
||||||
|
white-space: normal;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#servers .Server .name {
|
||||||
|
display: none;
|
||||||
|
font-weight: bold;
|
||||||
|
white-space: normal;
|
||||||
|
word-wrap: break-word;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
#servers .Server .name {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#servers .Server:hover .name {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
color: white;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-left: 60px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user