Add a lot of styling
This commit is contained in:
parent
3f1e6cf657
commit
4872eee4ed
6 changed files with 180 additions and 37 deletions
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>Ripcord log viewer</title>
|
<title>Ripcord log viewer</title>
|
||||||
|
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Roboto+Condensed:300,400&display=swap" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="style/layout.scss" />
|
<link rel="stylesheet" href="style/layout.scss" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,13 @@ function channelsFirst(a: GQLChannel, b: GQLChannel): number {
|
||||||
return a.name > b.name ? 1 : -1;
|
return a.name > b.name ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isActive(currentChatData, ws, ch): boolean {
|
||||||
|
return (
|
||||||
|
currentChatData?.currentChat?.workspace == ws &&
|
||||||
|
currentChatData?.currentChat?.channel == ch
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default function ChannelList() {
|
export default function ChannelList() {
|
||||||
const { loading, error, data } = useQuery(gql`
|
const { loading, error, data } = useQuery(gql`
|
||||||
{
|
{
|
||||||
|
@ -31,6 +38,15 @@ export default function ChannelList() {
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
const { loading: currentChatLoading, data: currentChatData } = useQuery(gql`
|
||||||
|
{
|
||||||
|
currentChat {
|
||||||
|
workspace
|
||||||
|
channel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <div>Loading</div>;
|
return <div>Loading</div>;
|
||||||
}
|
}
|
||||||
|
@ -51,6 +67,9 @@ export default function ChannelList() {
|
||||||
{ws.channels.sort(channelsFirst).map(ch => (
|
{ws.channels.sort(channelsFirst).map(ch => (
|
||||||
<li
|
<li
|
||||||
key={ch.name}
|
key={ch.name}
|
||||||
|
className={
|
||||||
|
isActive(currentChatData, ws.name, ch.name) ? "active" : ""
|
||||||
|
}
|
||||||
onClick={a =>
|
onClick={a =>
|
||||||
gotoChat({
|
gotoChat({
|
||||||
variables: { workspace: ws.name, channel: ch.name }
|
variables: { workspace: ws.name, channel: ch.name }
|
||||||
|
|
|
@ -1,8 +1,40 @@
|
||||||
import React from "react";
|
import React, { useEffect, useRef } from "react";
|
||||||
import { useQuery } from "@apollo/react-hooks";
|
import { useQuery } from "@apollo/react-hooks";
|
||||||
import { gql } from "apollo-boost";
|
import { gql } from "apollo-boost";
|
||||||
import { GQLMessage } from "./gql-types";
|
import { GQLMessage } from "./gql-types";
|
||||||
|
|
||||||
|
function perDay(messages: GQLMessage[]) {
|
||||||
|
const days = messages.reduce((acc, msg) => {
|
||||||
|
const [day] = msg.time.split("T");
|
||||||
|
if (!(day in acc)) {
|
||||||
|
acc[day] = [];
|
||||||
|
}
|
||||||
|
acc[day].push(msg);
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
return Object.entries(days).sort(([a], [b]) => {
|
||||||
|
if (a > b) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatTime(time: string): string {
|
||||||
|
const t = new Date(time);
|
||||||
|
return [t.getHours(), t.getMinutes(), t.getSeconds()]
|
||||||
|
.map(x => `0${x}`.slice(-2))
|
||||||
|
.join(":");
|
||||||
|
}
|
||||||
|
|
||||||
|
function colorname(name: string): string {
|
||||||
|
const n = name
|
||||||
|
.split("")
|
||||||
|
.map(x => x.charCodeAt(0))
|
||||||
|
.reduce((a, b) => a + b, 0);
|
||||||
|
return `hsl(${n % 360}, 60%, 50%)`;
|
||||||
|
}
|
||||||
|
|
||||||
export default function Chatroom() {
|
export default function Chatroom() {
|
||||||
const {
|
const {
|
||||||
loading: localLoading,
|
loading: localLoading,
|
||||||
|
@ -47,6 +79,11 @@ export default function Chatroom() {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const lastMessage = useRef(null);
|
||||||
|
useEffect(() => {
|
||||||
|
lastMessage.current?.scrollIntoView();
|
||||||
|
});
|
||||||
|
|
||||||
if (localLoading || remoteLoading) {
|
if (localLoading || remoteLoading) {
|
||||||
return <div>Loading</div>;
|
return <div>Loading</div>;
|
||||||
}
|
}
|
||||||
|
@ -64,17 +101,34 @@ export default function Chatroom() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<ul className="chatlog">
|
<ul className="chatlog">
|
||||||
{remoteData.messages.messages.map((msg: GQLMessage) => (
|
{perDay(remoteData.messages.messages).map(([day, messages]) => (
|
||||||
|
<li>
|
||||||
|
<div className="day">{day}</div>
|
||||||
|
<ul>
|
||||||
|
{messages.map((msg: GQLMessage) => (
|
||||||
<li key={msg.messageId}>
|
<li key={msg.messageId}>
|
||||||
<article className="message">
|
<article className="message">
|
||||||
<header>
|
<header>
|
||||||
{msg.userRealname} ({msg.username}) ({msg.messageId})
|
<div className="time" title={msg.time}>
|
||||||
|
{formatTime(msg.time)}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="realname"
|
||||||
|
style={{ color: colorname(msg.username) }}
|
||||||
|
>
|
||||||
|
{msg.userRealname}
|
||||||
|
</div>
|
||||||
|
<div className="username">{msg.username}</div>
|
||||||
</header>
|
</header>
|
||||||
<p>{msg.content}</p>
|
<p>{msg.content}</p>
|
||||||
</article>
|
</article>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
<div ref={lastMessage}></div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ export interface GQLMessageList {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GQLMessage {
|
export interface GQLMessage {
|
||||||
time: Date;
|
time: string;
|
||||||
content: string;
|
content: string;
|
||||||
username: string;
|
username: string;
|
||||||
userRealname: string;
|
userRealname: string;
|
||||||
|
|
|
@ -3,10 +3,103 @@
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
body,
|
body,
|
||||||
.main {
|
.main {
|
||||||
@include full;
|
@include full;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
overflow: hidden;
|
||||||
|
font-family: "Inter var", -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
@import "./sidebar.scss";
|
.chatroom {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: scroll;
|
||||||
|
|
||||||
|
.day {
|
||||||
|
text-align: center;
|
||||||
|
padding: 10pt;
|
||||||
|
top: 0;
|
||||||
|
position: sticky;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
div {
|
||||||
|
padding: 0 5pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
font-family: "Roboto Condensed";
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.realname {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.username {
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
padding: 0 15pt;
|
||||||
|
margin: 5pt 0 15pt 0;
|
||||||
|
font-size: 11pt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.channelList {
|
||||||
|
flex: 0 200px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
|
||||||
|
.workspace {
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10pt;
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-height: 2em;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chats {
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
padding: 4pt 5pt;
|
||||||
|
font-size: 10pt;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: blue;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,25 +0,0 @@
|
||||||
.channelList {
|
|
||||||
.workspace {
|
|
||||||
.title {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
img {
|
|
||||||
max-height: 2em;
|
|
||||||
margin-right: 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.chats {
|
|
||||||
ul {
|
|
||||||
list-style-type: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
padding: 2pt 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Reference in a new issue