Browse Source

Add a lot of styling

master
Hamcha 2 years ago
parent
commit
4872eee4ed
Signed by: Hamcha GPG Key ID: 44AD3571EB09A39E
  1. 2
      frontend/index.html
  2. 19
      frontend/src/ChannelList.tsx
  3. 72
      frontend/src/Chatroom.tsx
  4. 2
      frontend/src/gql-types.ts
  5. 97
      frontend/style/layout.scss
  6. 25
      frontend/style/sidebar.scss

2
frontend/index.html

@ -3,6 +3,8 @@
<head>
<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" />
</head>

19
frontend/src/ChannelList.tsx

@ -11,6 +11,13 @@ function channelsFirst(a: GQLChannel, b: GQLChannel): number {
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() {
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) {
return <div>Loading</div>;
}
@ -51,6 +67,9 @@ export default function ChannelList() {
{ws.channels.sort(channelsFirst).map(ch => (
<li
key={ch.name}
className={
isActive(currentChatData, ws.name, ch.name) ? "active" : ""
}
onClick={a =>
gotoChat({
variables: { workspace: ws.name, channel: ch.name }

72
frontend/src/Chatroom.tsx

@ -1,8 +1,40 @@
import React from "react";
import React, { useEffect, useRef } from "react";
import { useQuery } from "@apollo/react-hooks";
import { gql } from "apollo-boost";
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() {
const {
loading: localLoading,
@ -47,6 +79,11 @@ export default function Chatroom() {
}
);
const lastMessage = useRef(null);
useEffect(() => {
lastMessage.current?.scrollIntoView();
});
if (localLoading || remoteLoading) {
return <div>Loading</div>;
}
@ -64,17 +101,34 @@ export default function Chatroom() {
return (
<div>
<ul className="chatlog">
{remoteData.messages.messages.map((msg: GQLMessage) => (
<li key={msg.messageId}>
<article className="message">
<header>
{msg.userRealname} ({msg.username}) ({msg.messageId})
</header>
<p>{msg.content}</p>
</article>
{perDay(remoteData.messages.messages).map(([day, messages]) => (
<li>
<div className="day">{day}</div>
<ul>
{messages.map((msg: GQLMessage) => (
<li key={msg.messageId}>
<article className="message">
<header>
<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>
<p>{msg.content}</p>
</article>
</li>
))}
</ul>
</li>
))}
</ul>
<div ref={lastMessage}></div>
</div>
);
}

2
frontend/src/gql-types.ts

@ -4,7 +4,7 @@ export interface GQLMessageList {
}
export interface GQLMessage {
time: Date;
time: string;
content: string;
username: string;
userRealname: string;

97
frontend/style/layout.scss

@ -3,10 +3,103 @@
flex: 1;
}
body,
.main {
@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;
}
}
}
}
}

25
frontend/style/sidebar.scss

@ -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;
}
}
}
}
Loading…
Cancel
Save