diff options
Diffstat (limited to 'hi-ui/src/lib')
| -rw-r--r-- | hi-ui/src/lib/apiServer.js | 76 | ||||
| -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.js | 8 | ||||
| -rw-r--r-- | hi-ui/src/lib/store/channels.js | 71 | ||||
| -rw-r--r-- | hi-ui/src/lib/store/messages.js | 41 |
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; + } +} |
