summaryrefslogtreecommitdiff
path: root/hi-ui/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'hi-ui/src/lib')
-rw-r--r--hi-ui/src/lib/apiServer.js76
-rw-r--r--hi-ui/src/lib/components/ActiveChannel.svelte (renamed from hi-ui/src/lib/ActiveChannel.svelte)2
-rw-r--r--hi-ui/src/lib/components/Channel.svelte (renamed from hi-ui/src/lib/Channel.svelte)9
-rw-r--r--hi-ui/src/lib/components/ChannelList.svelte (renamed from hi-ui/src/lib/ChannelList.svelte)2
-rw-r--r--hi-ui/src/lib/components/CreateChannelForm.svelte (renamed from hi-ui/src/lib/CreateChannelForm.svelte)2
-rw-r--r--hi-ui/src/lib/components/LogIn.svelte (renamed from hi-ui/src/lib/LogIn.svelte)4
-rw-r--r--hi-ui/src/lib/components/LogOut.svelte (renamed from hi-ui/src/lib/LogOut.svelte)4
-rw-r--r--hi-ui/src/lib/components/Message.svelte (renamed from hi-ui/src/lib/Message.svelte)4
-rw-r--r--hi-ui/src/lib/components/MessageInput.svelte (renamed from hi-ui/src/lib/MessageInput.svelte)4
-rw-r--r--hi-ui/src/lib/store.js8
-rw-r--r--hi-ui/src/lib/store/channels.js71
-rw-r--r--hi-ui/src/lib/store/messages.js41
12 files changed, 209 insertions, 18 deletions
diff --git a/hi-ui/src/lib/apiServer.js b/hi-ui/src/lib/apiServer.js
new file mode 100644
index 0000000..9a51715
--- /dev/null
+++ b/hi-ui/src/lib/apiServer.js
@@ -0,0 +1,76 @@
+import axios from 'axios';
+import { activeChannel, channelsList, messages } from '$lib/store';
+
+export const apiServer = axios.create({
+ baseURL: '/api/',
+});
+
+export async function boot() {
+ return apiServer.get('/boot');
+}
+
+export async function logIn(username, password) {
+ const data = {
+ name: username,
+ password,
+ };
+ return apiServer.post('/auth/login', data);
+}
+
+export async function logOut() {
+ return apiServer.post('/auth/logout', {});
+}
+
+export async function createChannel(name) {
+ return apiServer.post('/channels', { name });
+}
+
+export async function postToChannel(channelId, message) {
+ return apiServer.post(`/channels/${channelId}`, { message });
+}
+
+export async function deleteMessage(messageId) {
+ // TODO
+}
+
+export function subscribeToEvents(resume_point) {
+ const eventsUrl = new URL('/api/events', window.location);
+ eventsUrl.searchParams.append('resume_point', resume_point);
+ const evtSource = new EventSource(eventsUrl.toString());
+ // TODO: this should process all incoming events and store them.
+ // TODO: eventually we'll need to handle expiring old info, so as not to use
+ // infinite browser memory.
+ /*
+ * Known message types as of now:
+ * - created: a channel is created.
+ * - action: ignore.
+ * - message: a message is created.
+ * - action: display message in channel.
+ * - message_deleted: a message is deleted.
+ * - action: replace message with <...>.
+ * - deleted: a channel is deleted.
+ * - action: remove channel from sidebar.
+ */
+ evtSource.onmessage = (evt) => {
+ const data = JSON.parse(evt.data);
+
+ switch (data.type) {
+ case 'created':
+ channelsList.update((value) => value.addChannel(data.channel))
+ break;
+ case 'message':
+ messages.update((value) => value.addMessage(data));
+ break;
+ case 'message_deleted':
+ messages.update((value) => value.deleteMessage(data.channel.id, data.message));
+ break;
+ case 'deleted':
+ activeChannel.update((value) => value.deleteChannel(data.channel));
+ channelsList.update((value) => value.deleteChannel(data.channel));
+ messages.update((value) => value.deleteChannel(data.channel));
+ break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/hi-ui/src/lib/ActiveChannel.svelte b/hi-ui/src/lib/components/ActiveChannel.svelte
index d2d92fb..978e952 100644
--- a/hi-ui/src/lib/ActiveChannel.svelte
+++ b/hi-ui/src/lib/components/ActiveChannel.svelte
@@ -1,5 +1,5 @@
<script>
- import { activeChannel, messages } from '../store';
+ import { activeChannel, messages } from '$lib/store';
import Message from './Message.svelte';
let container;
diff --git a/hi-ui/src/lib/Channel.svelte b/hi-ui/src/lib/components/Channel.svelte
index 9922af6..97fea1f 100644
--- a/hi-ui/src/lib/Channel.svelte
+++ b/hi-ui/src/lib/components/Channel.svelte
@@ -1,5 +1,5 @@
<script>
- import { activeChannel } from '../store';
+ import { activeChannel } from '$lib/store';
export let id;
export let name;
@@ -8,18 +8,13 @@
activeChannel.subscribe((value) => {
active = value.is(id);
});
-
- function activate() {
- activeChannel.update((value) => value.set(id));
- }
</script>
<li
class="rounded-full"
class:bg-slate-400={active}
- on:click={activate}
>
-<a href="">
+<a href="/ch/{id}">
<span class="badge bg-primary-500">#</span>
<span class="flex-auto">{name}</span>
</a>
diff --git a/hi-ui/src/lib/ChannelList.svelte b/hi-ui/src/lib/components/ChannelList.svelte
index 80d903e..e0e5f06 100644
--- a/hi-ui/src/lib/ChannelList.svelte
+++ b/hi-ui/src/lib/components/ChannelList.svelte
@@ -1,5 +1,5 @@
<script>
- import { channelsList } from '../store';
+ import { channelsList } from '$lib/store';
import Channel from './Channel.svelte';
let channels;
diff --git a/hi-ui/src/lib/CreateChannelForm.svelte b/hi-ui/src/lib/components/CreateChannelForm.svelte
index 8910b4d..ddcf486 100644
--- a/hi-ui/src/lib/CreateChannelForm.svelte
+++ b/hi-ui/src/lib/components/CreateChannelForm.svelte
@@ -1,5 +1,5 @@
<script>
- import { createChannel } from '../apiServer';
+ import { createChannel } from '$lib/apiServer';
let name = '';
let disabled = false;
diff --git a/hi-ui/src/lib/LogIn.svelte b/hi-ui/src/lib/components/LogIn.svelte
index 4ffcdab..2836e6d 100644
--- a/hi-ui/src/lib/LogIn.svelte
+++ b/hi-ui/src/lib/components/LogIn.svelte
@@ -1,6 +1,6 @@
<script>
- import { logIn } from '../apiServer';
- import { currentUser } from '../store';
+ import { logIn } from '$lib/apiServer';
+ import { currentUser } from '$lib/store';
let disabled = false;
let username = '';
diff --git a/hi-ui/src/lib/LogOut.svelte b/hi-ui/src/lib/components/LogOut.svelte
index 0f0bb13..01bef1b 100644
--- a/hi-ui/src/lib/LogOut.svelte
+++ b/hi-ui/src/lib/components/LogOut.svelte
@@ -1,6 +1,6 @@
<script>
- import { logOut} from '../apiServer';
- import { currentUser } from '../store';
+ import { logOut} from '$lib/apiServer';
+ import { currentUser } from '$lib/store';
async function handleLogout(event) {
const response = await logOut();
diff --git a/hi-ui/src/lib/Message.svelte b/hi-ui/src/lib/components/Message.svelte
index efc6641..5b51492 100644
--- a/hi-ui/src/lib/Message.svelte
+++ b/hi-ui/src/lib/components/Message.svelte
@@ -1,7 +1,7 @@
<script>
import SvelteMarkdown from 'svelte-markdown';
- import { currentUser } from '../store';
- import { deleteMessage } from '../apiServer';
+ import { currentUser } from '$lib/store';
+ import { deleteMessage } from '$lib/apiServer';
export let at; // XXX: Omitted for now.
export let sender;
diff --git a/hi-ui/src/lib/MessageInput.svelte b/hi-ui/src/lib/components/MessageInput.svelte
index 2e81ee2..b33574b 100644
--- a/hi-ui/src/lib/MessageInput.svelte
+++ b/hi-ui/src/lib/components/MessageInput.svelte
@@ -1,7 +1,7 @@
<script>
import { tick } from 'svelte';
- import { postToChannel } from '../apiServer';
- import { activeChannel } from '../store';
+ import { postToChannel } from '$lib/apiServer';
+ import { activeChannel } from '$lib/store';
let input;
let value;
diff --git a/hi-ui/src/lib/store.js b/hi-ui/src/lib/store.js
new file mode 100644
index 0000000..5e28195
--- /dev/null
+++ b/hi-ui/src/lib/store.js
@@ -0,0 +1,8 @@
+import { writable } from 'svelte/store';
+import { ActiveChannel, Channels } from '$lib/store/channels';
+import { Messages } from '$lib/store/messages';
+
+export const currentUser = writable(null);
+export const activeChannel = writable(new ActiveChannel());
+export const channelsList = writable(new Channels());
+export const messages = writable(new Messages());
diff --git a/hi-ui/src/lib/store/channels.js b/hi-ui/src/lib/store/channels.js
new file mode 100644
index 0000000..20702cc
--- /dev/null
+++ b/hi-ui/src/lib/store/channels.js
@@ -0,0 +1,71 @@
+export class Channels {
+ constructor() {
+ this.channels = [];
+ }
+
+ setChannels(channels) {
+ this.channels = [...channels];
+ this.sort();
+ return this;
+ }
+
+ addChannel(channel) {
+ this.channels = [...this.channels, channel];
+ this.sort();
+ return this;
+ }
+
+ deleteChannel(id) {
+ const channelIndex = this.channels.map((e) => e.id).indexOf(id);
+ if (channelIndex !== -1) {
+ this.channels.splice(channelIndex, 1);
+ }
+ return this;
+ }
+
+ sort() {
+ this.channels.sort((a, b) => {
+ if (a.name < b.name) {
+ return -1;
+ } else if (a.name > b.name) {
+ return 1;
+ }
+ return 0;
+ });
+ }
+}
+
+export class ActiveChannel {
+ constructor() {
+ this.channel = null;
+ }
+
+ isSet() {
+ return this.channel !== null;
+ }
+
+ get() {
+ return this.channel;
+ }
+
+ is(id) {
+ return this.channel === id;
+ }
+
+ set(id) {
+ this.channel = id;
+ return this;
+ }
+
+ deleteChannel(id) {
+ if (this.is(id)) {
+ return this.clear();
+ }
+ return this;
+ }
+
+ clear() {
+ this.channel = null;
+ return this;
+ }
+}
diff --git a/hi-ui/src/lib/store/messages.js b/hi-ui/src/lib/store/messages.js
new file mode 100644
index 0000000..560b9e1
--- /dev/null
+++ b/hi-ui/src/lib/store/messages.js
@@ -0,0 +1,41 @@
+export class Messages {
+ constructor() {
+ this.channels = {};
+ }
+
+ inChannel(channel) {
+ return this.channels[channel] || [];
+ }
+
+ addMessage(message) {
+ let {
+ channel,
+ ...payload
+ } = message;
+ let channel_id = channel.id;
+ this.updateChannel(channel_id, (messages) => [...messages, payload]);
+ return this;
+ }
+
+ addMessages(channel, payloads) {
+ this.updateChannel(channel, (messages) => [...messages, ...payloads]);
+ return this;
+ }
+
+
+ deleteMessage(channel, message) {
+ let messages = this.messages(channel).filter((msg) => msg.message.id != message);
+ this.channels[channel] = messages;
+ }
+
+ deleteChannel(id) {
+ delete this.channels[id];
+ return this;
+ }
+
+ updateChannel(channel, callback) {
+ let messages = callback(this.inChannel(channel));
+ messages.sort((a, b) => a.at - b.at);
+ this.channels[channel] = messages;
+ }
+}