Compare commits
No commits in common. "24fb9feead2af236e4629822e13023608ff8f592" and "2847cfcebcd6b0a4bdecac6ef5a16609295d1059" have entirely different histories.
24fb9feead
...
2847cfcebc
8 changed files with 31 additions and 60 deletions
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
<div class="top-bar">
|
<div class="top-bar">
|
||||||
{#if !$showSidebar}
|
{#if !$showSidebar}
|
||||||
<button class="icon-button menu-button" on:click="{ () => showSidebar.set(true) }">
|
<button class="icon-button menu-button" on:click="{ () => selectedChannel.set({ id: -1, name: "none", creator_id: -1 }) }">
|
||||||
<MenuIcon />
|
<MenuIcon />
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<script>
|
<script>
|
||||||
import { showChannelView } from "../stores";
|
|
||||||
import ChannelTopBar from "./ChannelTopBar.svelte";
|
import ChannelTopBar from "./ChannelTopBar.svelte";
|
||||||
import MessageInput from "./MessageInput.svelte";
|
import MessageInput from "./MessageInput.svelte";
|
||||||
import Messages from "./Messages.svelte";
|
import Messages from "./Messages.svelte";
|
||||||
|
@ -16,13 +15,9 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="main-container" class:hidden={ !$showChannelView }>
|
<div class="main-container">
|
||||||
<ChannelTopBar channel={ channel } />
|
<ChannelTopBar channel={ channel } />
|
||||||
<Messages channelId="{ channel.id }" />
|
<Messages channelId="{ channel.id }" />
|
||||||
<MessageInput channel={ channel } />
|
<MessageInput channel={ channel } />
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { CloudIcon } from "svelte-feather-icons";
|
import { CloudIcon } from "svelte-feather-icons";
|
||||||
import { gatewayStatus, showSidebar, selectedChannel, smallViewport, showChannelView } from "../stores";
|
import { gatewayStatus, showSidebar, selectedChannel } from "../stores";
|
||||||
import ChannelView from "./ChannelView.svelte";
|
import ChannelView from "./ChannelView.svelte";
|
||||||
import OverlayProvider from "./overlays/OverlayProvider.svelte";
|
import OverlayProvider from "./overlays/OverlayProvider.svelte";
|
||||||
import Sidebar from "./Sidebar.svelte";
|
import Sidebar from "./Sidebar.svelte";
|
||||||
|
@ -26,10 +26,17 @@
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="flex-container">
|
<div class="flex-container">
|
||||||
{#if $showSidebar}
|
{#if $selectedChannel.id === -1}
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
{/if}
|
{#if $showSidebar}
|
||||||
{#if !($smallViewport && $showSidebar)}
|
<div class="fullscreen-message">
|
||||||
|
no channel selected.
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{:else}
|
||||||
|
{#if $showSidebar}
|
||||||
|
<Sidebar />
|
||||||
|
{/if}
|
||||||
<ChannelView channel={$selectedChannel} />
|
<ChannelView channel={$selectedChannel} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import request from "../request";
|
import request from "../request";
|
||||||
import { apiRoute } from "../storage";
|
import { apiRoute } from "../storage";
|
||||||
import { messagesStoreProvider, overlayStore, userInfoStore } from "../stores";
|
import { messageInputFocusStatus, messagesStoreProvider, overlayStore, userInfoStore } from "../stores";
|
||||||
|
|
||||||
export let channel;
|
export let channel;
|
||||||
let messageInput = "";
|
let messageInput = "";
|
||||||
|
@ -76,5 +76,7 @@
|
||||||
class="message-input"
|
class="message-input"
|
||||||
on:keydown={ onKeydown }
|
on:keydown={ onKeydown }
|
||||||
bind:value={ messageInput }
|
bind:value={ messageInput }
|
||||||
|
on:focus="{ () => messageInputFocusStatus.set(true) }"
|
||||||
|
on:blur="{ () => messageInputFocusStatus.set(false) }"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { afterUpdate, beforeUpdate, onMount } from "svelte";
|
import { afterUpdate, beforeUpdate, onMount } from "svelte";
|
||||||
import { messagesStoreProvider, showSidebar } from "../stores.js";
|
import { messageInputFocusStatus, messagesStoreProvider } from "../stores.js";
|
||||||
import Message from "./Message.svelte";
|
import Message from "./Message.svelte";
|
||||||
|
|
||||||
export let channelId;
|
export let channelId;
|
||||||
|
@ -8,9 +8,17 @@
|
||||||
let scrollAnchor;
|
let scrollAnchor;
|
||||||
let shouldAutoscroll = true;
|
let shouldAutoscroll = true;
|
||||||
let lastScrollHeight = null;
|
let lastScrollHeight = null;
|
||||||
let isScrolledToBottom = true;
|
let isScrolledToBottom = false;
|
||||||
|
|
||||||
$: messages = messagesStoreProvider.getStore(channelId);
|
$: messages = messagesStoreProvider.getStore(channelId);
|
||||||
|
$: {
|
||||||
|
console.log($messageInputFocusStatus, isScrolledToBottom);
|
||||||
|
if ($messageInputFocusStatus && isScrolledToBottom) {
|
||||||
|
setTimeout(() => {
|
||||||
|
scrollTarget.scrollTop = scrollTarget.scrollHeight;
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
afterUpdate(() => {
|
afterUpdate(() => {
|
||||||
// hacky way to preserve scroll position when messages are pushed back
|
// hacky way to preserve scroll position when messages are pushed back
|
||||||
|
@ -47,19 +55,8 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const windowDidResize = () => {
|
|
||||||
// TODO: hack
|
|
||||||
// showSidebar is false on small viewports
|
|
||||||
// scrolling to bottom when the virtual keyboard pops up does not work on chromium purely based on isScrolledToBottom for some reason
|
|
||||||
const isSmallViewport = !$showSidebar;
|
|
||||||
if (isScrolledToBottom || isSmallViewport) {
|
|
||||||
scrollAnchor.scrollIntoView(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window on:resize={ windowDidResize } />
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.messages-container {
|
.messages-container {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -1,41 +1,14 @@
|
||||||
<script>
|
<script>
|
||||||
import { HashIcon, PlusIcon, MoreVerticalIcon } from "svelte-feather-icons";
|
import { HashIcon, PlusIcon, MoreVerticalIcon } from "svelte-feather-icons";
|
||||||
import { quadInOut } from "svelte/easing";
|
import { channels, overlayStore, selectedChannel } from "../stores";
|
||||||
import { fly } from "svelte/transition";
|
|
||||||
import { channels, overlayStore, selectedChannel, showChannelView, showSidebar, smallViewport } from "../stores";
|
|
||||||
import UserTopBar from "./UserTopBar.svelte";
|
import UserTopBar from "./UserTopBar.svelte";
|
||||||
|
|
||||||
let pendingSelectChannel = null;
|
|
||||||
|
|
||||||
const selectChannel = (channel) => $selectedChannel = channel;
|
|
||||||
|
|
||||||
// janky code to hide the channel view during animation
|
|
||||||
// this will make a smooth sidebar animation on smaller viewports (such as a phone, where you switch between sidebar being active)
|
|
||||||
|
|
||||||
const scheduleSelectChannel = (channel) => {
|
|
||||||
if ($smallViewport) {
|
|
||||||
$showChannelView = false;
|
|
||||||
pendingSelectChannel = channel;
|
|
||||||
$showSidebar = false;
|
|
||||||
} else {
|
|
||||||
selectChannel(channel);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const outroEnd = () => {
|
|
||||||
if (pendingSelectChannel) {
|
|
||||||
selectChannel(pendingSelectChannel);
|
|
||||||
pendingSelectChannel = null;
|
|
||||||
$showChannelView = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="sidebar-container" transition:fly="{{ duration: 200, easing: quadInOut, x: -10 }}" on:outroend="{ outroEnd }">
|
<div class="sidebar-container">
|
||||||
<UserTopBar />
|
<UserTopBar />
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
{#each $channels as channel (channel.id)}
|
{#each $channels as channel (channel.id)}
|
||||||
<button on:click="{ scheduleSelectChannel(channel) }" class="sidebar-button" class:selected={ channel.id === $selectedChannel.id }>
|
<button on:click="{ () => $selectedChannel = channel }" class="sidebar-button" class:selected={ channel.id === $selectedChannel.id }>
|
||||||
<div>
|
<div>
|
||||||
<HashIcon />
|
<HashIcon />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import { showSidebar, smallViewport } from "./stores";
|
import { showSidebar } from "./stores";
|
||||||
|
|
||||||
export function initResponsiveHandlers() {
|
export function initResponsiveHandlers() {
|
||||||
const mediaQuery = window.matchMedia('(min-width: 768px)');
|
const mediaQuery = window.matchMedia('(min-width: 768px)');
|
||||||
|
|
||||||
const update = ({ matches }) => {
|
const update = ({ matches }) => {
|
||||||
showSidebar.set(matches);
|
showSidebar.set(matches);
|
||||||
smallViewport.set(!matches);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mediaQuery.addEventListener("change", update);
|
mediaQuery.addEventListener("change", update);
|
||||||
|
|
|
@ -36,7 +36,6 @@ class ChannelsStore extends Store {
|
||||||
|
|
||||||
gateway.subscribe(GatewayEventType.Ready, ({ channels }) => {
|
gateway.subscribe(GatewayEventType.Ready, ({ channels }) => {
|
||||||
this.value = channels;
|
this.value = channels;
|
||||||
selectedChannel.set(channels.length ? channels[0] : null);
|
|
||||||
this.updated();
|
this.updated();
|
||||||
});
|
});
|
||||||
gateway.subscribe(GatewayEventType.ChannelCreate, (channel) => {
|
gateway.subscribe(GatewayEventType.ChannelCreate, (channel) => {
|
||||||
|
@ -266,5 +265,4 @@ export const userInfoStore = new UserInfoStore();
|
||||||
export const overlayStore = new OverlayStore();
|
export const overlayStore = new OverlayStore();
|
||||||
export const selectedChannel = writable({ id: -1, name: "none", creator_id: -1 });
|
export const selectedChannel = writable({ id: -1, name: "none", creator_id: -1 });
|
||||||
export const showSidebar = writable(false);
|
export const showSidebar = writable(false);
|
||||||
export const showChannelView = writable(true);
|
export const messageInputFocusStatus = writable(false);
|
||||||
export const smallViewport = writable(false);
|
|
||||||
|
|
Loading…
Reference in a new issue