feat: conversation switcher

This commit is contained in:
ktyl 2024-10-05 18:35:24 +01:00 committed by Cat Flynn
parent 023b8fe55f
commit 08a15b9c95
4 changed files with 168 additions and 61 deletions

View File

@ -6,26 +6,12 @@
</head> </head>
<body> <body>
<div id="side-panel"> <div id="side-panel"></div>
<div class="conversation">
<h2>Lorem</h2>
<span>Lorem ipsum blah-de-fuck</span>
</div>
<div class="conversation">
<h2>Caesar</h2>
<span>Heyy Markus-chan uwu xoxo. i heard u was in town maybe stop by</span>
</div>
<!--
TODO: other conversations to fill out the panel! filler stuff!
-->
</div>
<div id="main-panel"> <div id="main-panel">
<div id="header"> <div id="header">
<button class="rounded-rectangle" onclick="console.log('back')"><- back</button> <button id="conversation-list-button" class="rounded-rectangle" onclick="showSidePanel()"><- back</button>
<h1 id="header-title">NAME</h1> <h1 id="header-title">NAME</h1>
</div> </div>
@ -37,6 +23,7 @@ TODO: other conversations to fill out the panel! filler stuff!
<input id="textbox-input" class="rounded-rectangle" type="text" onkeydown="pressSendButton()"></input> <input id="textbox-input" class="rounded-rectangle" type="text" onkeydown="pressSendButton()"></input>
<button class="rounded-rectangle" onclick="pressSendButton()">send</button> <button class="rounded-rectangle" onclick="pressSendButton()">send</button>
</div> </div>
</div> </div>
<script src="main.js"></script> <script src="main.js"></script>

12
lucius.json Normal file
View File

@ -0,0 +1,12 @@
[
{ "character": 0, "text": "Hows everything in Rome, Lucius?" },
{ "character": 1, "text": "Same old chaos. Senates split on everything." },
{ "character": 0, "text": "Let them bicker. Youre holding up, right?" },
{ "character": 1, "text": "Barely. Could use more allies here." },
{ "character": 0, "text": "Ill see what I can do. Dont let them push you around." },
{ "character": 1, "text": "Not worried about that. Just tired of their nonsense." },
{ "character": 0, "text": "Hang in there. Ill be back soon." },
{ "character": 1, "text": "You better. You owe me a break." },
{ "character": 0, "text": "Its coming, trust me." }
]

102
main.js
View File

@ -177,13 +177,61 @@ function onMessageSent(message) {
updateChat(message); updateChat(message);
} }
function init(messagesData) { // probably a bit hacky! but this saves having to do like, state or something in CSS?
conversation = new Conversation("Caesar"); // which probably is possible and probably would be the better way to do it, but that
// sounds like a bunch of learning i'm not SUPER in the mood for
function setVisibleOnMobile(element, isVisible) {
let classes = element.className.split().filter(c => c != "");
const invisibleClass = "invisible-on-mobile";
const visibleClass = "visible";
if (isVisible && !classes.includes(visibleClass)) {
const idx = classes.indexOf(invisibleClass);
if (idx != -1) {
classes.splice(idx, 1);
}
classes.push(visibleClass);
} else if (!classes.includes(invisibleClass)) {
const idx = classes.indexOf(visibleClass);
if (idx != -1) {
classes.splice(idx, 1);
}
classes.push(invisibleClass);
}
element.className = classes.join(" ");
}
function showSidePanel() {
// this function can only be called on mobile. the main conversation should be
// hidden and the side conversations panel should take up the whole screen.
const mainPanel = document.getElementById("main-panel");
const conversationListElem = document.getElementById("side-panel");
setVisibleOnMobile(mainPanel, false);
setVisibleOnMobile(conversationListElem, true);
}
function showConversation(path) {
const mainPanel = document.getElementById("main-panel");
const conversationListElem = document.getElementById("side-panel");
setVisibleOnMobile(mainPanel, true);
setVisibleOnMobile(conversationListElem, false);
const title = path.split(".")[0];
fetch(path)
.then(response => response.json())
.then(json => {
conversation = new Conversation(title);
let initialMessages = []; let initialMessages = [];
for (let i = 0; i < messagesData.length; i++) { for (let i = 0; i < json.length; i++) {
const data = messagesData[i]; const data = json[i];
const text = data.text; const text = data.text;
if (data.character == 0) { if (data.character == 0) {
const message = new UserMessage(text); const message = new UserMessage(text);
@ -197,11 +245,47 @@ function init(messagesData) {
conversation.initialize(initialMessages); conversation.initialize(initialMessages);
conversation.render(); conversation.render();
});
setTypingIndicator(false);
} }
fetch("lorem.json") function addConversationPreview(path) {
.then(response => response.json()) const title = path.split(".")[0];
.then(json => init(json)); const listRoot = document.getElementById("side-panel");
fetch(path)
.then(response => response.json())
.then(json => {
const elem = document.createElement("div");
elem.onclick = () => showConversation(path);
elem.className = "conversation";
const headerElem = document.createElement("h2");
headerElem.innerHTML = title;
elem.appendChild(headerElem);
const previewElem = document.createElement("span");
previewElem.innerHTML = json[json.length - 1].text;
elem.appendChild(previewElem);
listRoot.appendChild(elem);
});
}
function populateConversationList() {
const conversationFiles = [
"caesar.json",
"lucius.json",
"ides-of-march.json"
];
for (let i = 0; i < conversationFiles.length; i++) {
const path = conversationFiles[i];
addConversationPreview(path);
}
}
setTypingIndicator(false);
populateConversationList();
showConversation("lucius.json");

View File

@ -19,16 +19,56 @@ body {
#side-panel { #side-panel {
height: 100%; height: 100%;
background-color: red; background-color: var(--dark-purple);
display: none;
}
#header button {
transform: translateY(-.3em);
width: auto;
visibility: visible;
}
#side-panel {
display: block;
width: 100%;
}
#side-panel.invisible-on-mobile {
display: none;
}
/* on desktop only */
@media only screen and (min-width: 768px) {
#side-panel {
display: block;
width: auto;
visibility: visible;
border-right: 3px solid var(--eggshell);
}
#side-panel.invisible-on-mobile {
display: block;
}
#header button {
width: 0; width: 0;
margin: 0;
padding: 0;
visibility: hidden; visibility: hidden;
} }
#side-panel .conversation { #side-panel .conversation {
width: 300px; max-width: 300px;
}
}
#side-panel .conversation {
width: 100%;
height: 70px; height: 70px;
border: solid black 3px; border-bottom: solid var(--eggshell) 3px;
color: var(--eggshell);
padding: .5em;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
@ -36,7 +76,8 @@ body {
} }
#side-panel .conversation:hover { #side-panel .conversation:hover {
background-color: pink; background-color: var(--eggshell);
color: var(--dark-purple);
} }
#side-panel h2 { #side-panel h2 {
@ -46,7 +87,6 @@ body {
#header { #header {
position: sticky; position: sticky;
top: 0; top: 0;
background-color: red;
} }
#main-panel { #main-panel {
@ -63,9 +103,6 @@ body {
} }
h1 { h1 {
transform: translateY(.3rem);
height: 100%;
margin: 0;
display: inline-block; display: inline-block;
color: var(--eggshell); color: var(--eggshell);
@ -114,6 +151,7 @@ h1 {
ul { ul {
overflow: scroll; overflow: scroll;
/*height:100%;*/
flex-grow: 1; flex-grow: 1;
margin: .5em; margin: .5em;
padding: 0; padding: 0;
@ -185,16 +223,6 @@ button:hover {
background-color: var(--eggshell); background-color: var(--eggshell);
} }
@media only screen and (min-width: 768px) {
button {
width: 10%;
}
#textbox input {
width: 85%;
}
}
.progress-bar { .progress-bar {
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -222,7 +250,3 @@ button:hover {
right: 1em; right: 1em;
font-size: .8em; font-size: .8em;
} }
.conversations {
}