Commit ea6f8ac0 authored by Aral Balkan's avatar Aral Balkan
Browse files

Sign in and sign out now working properly

(And the web socket has been pulled out to the main app and exposed via a store.)
parent 4b828ee3
......@@ -4,19 +4,46 @@
import { routes } from './sections'
import { onMount, getContext } from 'svelte'
import { get } from 'svelte/store'
// Initialise context.
import { initialiseContext, state } from './state.js'
import { initialiseContext, state, signedIn} from './state.js'
initialiseContext()
const { publicSocket } = getContext(state)
const { publicSocket, privateToken, privateSocket, privateMessages } = getContext(state)
// Normal closure code for web sockets.
const NORMAL_CLOSURE = 1000
onMount(() => {
// Make the public socket connection.
$publicSocket = new WebSocket(`wss://${location.hostname}/public`)
$publicSocket.onmessage = message => {
console.log(message.data)
console.log(`Public message: ${message.data}`)
}
// When signed in, make the private socket connection.
signedIn.subscribe(isSignedIn => {
if (isSignedIn) {
console.log('Attempting to connect using private token', get(privateToken))
// Create a web socket connection.
$privateSocket = new WebSocket(`wss://${location.hostname}/private/${get(privateToken)}`)
$privateSocket.onmessage = message => {
$privateMessages = [...$privateMessages, message]
}
} else {
if ($privateSocket !== null) {
if ($privateSocket.readyState === 0 || $privateSocket.readyState === 1) {
console.log('Signed out, closing private socket.')
$privateSocket.send('Client is about to close.')
$privateSocket.close(NORMAL_CLOSURE, 'Person signed out.')
$privateToken = null
$privateMessages = []
}
}
}
})
})
</script>
......
<script>
import { getContext } from 'svelte'
import { state } from './state.js'
import { signedIn } from './state.js'
import sections from './sections.js'
let { signedIn} = getContext(state)
function shouldDisplay(path) {
function shouldDisplay(section, isSignedIn) {
// Display either the Sign In or Private section based on sign in status.
return !(!$signedIn && path === '/private') && !($signedIn && path === '/sign-in') && !(!$signedIn && path === '/sign-out')
const isInNavigation = !section.notInNavigation
const isPublic = !section.isPrivate
const isPrivateAndPersonIsSignedIn = section.isPrivate && isSignedIn
const isNotSignInLinkWhenAlreadySignedIn = !(section.path == '/sign-in' && isSignedIn)
return isInNavigation && (isPublic || isPrivateAndPersonIsSignedIn) && isNotSignInLinkWhenAlreadySignedIn
}
</script>
......@@ -22,8 +23,8 @@
<nav>
<ul>
{#each sections as section}
<!-- Including $currentSection here to trigger reactivity. -->
{#if !section.notInNavigation && shouldDisplay(section.path)}
<!-- Including $signedIn here to trigger reactivity. -->
{#if !section.notInNavigation && shouldDisplay(section, $signedIn)}
<li>
<a href='/#{section.path}'>{section.title}</a>
</li>
......
body {
font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
input, button, label {
font-size: 1.25em;
}
input, button {
background: white;
color: black;
border: 2px solid grey;
border-radius: 0.25em;
padding: 0.5em;
}
input:focus, button:focus {
outline: none;
box-shadow: 0px 0px 2px #0066ff;
}
......@@ -3,6 +3,7 @@
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<link rel='icon' href='data:,'> <!-- no favicon request -->
<title>Henry: Small Web Reference Client</title>
<script src='./index.js' type='module'></script>
</head>
......
......@@ -15,6 +15,7 @@ import { signedIn } from './state.js'
let isSignedIn
signedIn.subscribe(value => {
console.log(`Sections: signed in changed to ${value}`)
isSignedIn = value
})
......@@ -35,7 +36,7 @@ const isPrivate = () => {
if (!isSignedIn) {
replace('/sign-in')
}
return false
return isSignedIn
}
// Create the routes map.
......
......@@ -2,36 +2,15 @@
import Section from './Section.svelte'
import { getContext } from 'svelte'
import { get } from 'svelte/store'
import { state } from '../state.js'
const { privateToken, privateSocket } = getContext(state)
// NOTE: All this socket-related code should be taken out of the view.
let messages = []
function onShow() {
if ($privateSocket === null || $privateSocket.readyState !== 1) {
console.log('Attempting to connect using private token', get(privateToken))
// Create a web socket connection.
$privateSocket = new WebSocket(`wss://${location.hostname}/private/${get(privateToken)}`)
$privateSocket.onmessage = message => {
messages = [...messages, message]
}
} else {
console.log('Socket is open, not creating a new one.')
}
// Return an empty string so nothing is rendered as this is called from the view.
return ''
}
const { privateMessages } = getContext(state)
</script>
<Section path='/private' title='Private'>
{ onShow() }
<Section title='Private'>
<p>This is private.</p>
<ul>
{#each messages as message}
{#each $privateMessages as message}
<li>{message.data}</li>
{/each}
</ul>
......
<script>
import { getContext } from 'svelte'
import { state } from '../state.js'
import { state, signedIn } from '../state.js'
import Section from './Section.svelte'
import { authenticate } from '../authentication.js'
import { BarLoader } from 'svelte-loading-spinners'
import { push } from 'svelte-spa-router'
const path = '/sign-in'
let { signedIn, privateToken, currentSection } = getContext(state)
let { privateToken } = getContext(state)
let passphraseField
let _privateToken = undefined
......@@ -24,8 +24,9 @@
// it will return here and find the successful sign in.)
_privateToken = undefined
$signedIn = true
$currentSection = '/private'
location.hash = '/private'
// Navigate to the private route.
push('/private')
// Returning an empty string as we’re called
// from within the template’s await.
......@@ -37,7 +38,7 @@
}
</script>
<Section {path} title='Sign in'>
<Section title='Sign in'>
<form on:submit|preventDefault={handleSignIn} id='signInForm' name='signInForm'>
<label for='passphrase'>Password</label>
<input bind:this={passphraseField} name='passphrase' type='password'/>
......@@ -58,5 +59,4 @@
{:catch error}
<p style='color: red'>{error.message}</p>
{/await}
</Section>
<script>
import { getContext, tick } from 'svelte'
import { state } from '../state.js'
import { getContext } from 'svelte'
import { state, signedIn } from '../state.js'
import Section from './Section.svelte'
const NORMAL_CLOSURE = 1000
let { signedIn, privateToken, privateSocket, currentSection } = getContext(state)
import { push } from 'svelte-spa-router'
async function handleSignOut () {
console.log('private socket', $privateSocket)
$privateSocket.send('about to close')
$privateSocket.close(NORMAL_CLOSURE, 'Person signed out.')
$privateToken = null
$signedIn = false
$currentSection = '/sign-in'
location.hash = '/sign-in'
push('/sign-in')
}
</script>
<Section path='/sign-out' title='Sign out'>
<Section title='Sign out'>
<p>Are you sure?</p>
<button on:click|preventDefault={handleSignOut}>Yes, sign me out.</button>
</Section>
......@@ -5,11 +5,12 @@ import { writable } from 'svelte/store'
export const state = {}
export const signedIn = writable(false)
const privateToken = writable(null)
const privateSocket = writable(null)
const publicSocket = writable(null)
export const privateMessages = writable([])
export const privateToken = writable(null)
export const privateSocket = writable(null)
export const publicSocket = writable(null)
// Set initial application state, including the current section based on the hash.
export function initialiseContext () {
setContext(state, { signedIn, publicSocket, privateToken, privateSocket })
setContext(state, { signedIn, publicSocket, privateToken, privateSocket, privateMessages })
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment