Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(WIP) Michael/add meet page #31

Draft
wants to merge 8 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions src/components/MeetingNavbar/InviteButtons.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<script lang="ts">
import { copyToClipboard } from '$lib/util';
// import { PROJECT_EMOJI, PROJECT_NAME } from '$lib/constants';
// import * as routes from '$lib/routes';

export let href: string;

let isCopying = false;

function handleInvite(): void {
copyToClipboard(href);
isCopying = true;
setTimeout(() => {
isCopying = false;
}, 1500);
}
</script>

<div class="buttons has-addons">
<button
class="button is-small is-info is-light"
class:is-success={isCopying}
on:click={handleInvite}
title="Copy share link"
>
{#if isCopying}
Copied link
{:else}
<span class="has-text-weight-bold">+ Invite</span>
{/if}
</button>
<button
class="button is-small is-info"
class:is-success={isCopying}
title="Copy share link"
on:click={handleInvite}
>
{#if isCopying}
<span>✔️</span>
{:else}
<span>🔗</span>
{/if}
</button>
</div>
62 changes: 62 additions & 0 deletions src/components/MeetingNavbar/MeetingNavbar.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<script lang="ts">
import { PROJECT_EMOJI, PROJECT_NAME } from '$lib/constants';
import * as routes from '$lib/routes';
import InviteButtons from './InviteButtons.svelte';

export let slug: string;
export let href: string;

let isActive = false;
</script>

<nav class="navbar" aria-label="main navigation">
<div class="navbar-brand">
<a class="navbar-item" href={routes.BASE} title={`${PROJECT_NAME} home`}>
{PROJECT_EMOJI}
</a>
<a
role="button"
class="navbar-burger"
class:is-active={isActive}
aria-label="menu"
aria-expanded="false"
data-target="navbarBasicExample"
{href}
on:click|preventDefault={() => {
isActive = !isActive;
}}
>
<span aria-hidden="true" />
<span aria-hidden="true" />
<span aria-hidden="true" />
</a>
</div>

<div id="navbarBasicExample" class="navbar-menu" class:is-active={isActive}>
<div class="navbar-start">
<a
class="navbar-item"
{href}
title="Meeting settings"
on:click|preventDefault={() => alert('To do: Add meeting settings')}
>
meet: <span class="ml-2 has-font-monospace has-text-weight-bold">{slug}</span>
</a>
<a
class="navbar-item"
title="Meeting settings"
on:click|preventDefault={() => alert('To do: Add meeting settings')}
{href}
>
⚙️
</a>
</div>

<div class="navbar-end">
<!-- TODO #30 Add list of meeting participants in meeting navbar -->
<div class="navbar-item">
<InviteButtons {href} />
</div>
</div>
</div>
</nav>
3 changes: 2 additions & 1 deletion src/containers/CodeEditor/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { IndexeddbPersistence } from 'y-indexeddb';
import { WebrtcProvider } from 'y-webrtc';
import { YJS_WEBRTC_SIGNALLING_SERVERS } from '$lib/constants';
import * as awarenessProtocol from 'y-protocols/awareness.js';
import { randomColor } from '$lib/util';

type TExtendedSelf = typeof globalThis & {
MonacoEnvironment: {
Expand Down Expand Up @@ -89,6 +88,8 @@ export const initEditorTracking = async (
// A Yjs document holds the shared data
const ydoc = new Y.Doc();
const type = ydoc.getText('monaco'); // TODO Understand better...
const undoManager = new Y.UndoManager(type);
console.debug(undoManager);

// TODO #22 Handle doc persistence when starting a new webrtc conference.
// We persist the document content across sessions
Expand Down
4 changes: 4 additions & 0 deletions src/lib/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@ const _BASE = '';

export const BASE = `${_BASE}/`;
export const ABOUT = `${_BASE}/about`;

export const MEET = `${_BASE}/meet`;
export const MEET_CREATE = `${MEET}/create`;
export const MEET_SLUG = (s: string): string => `${MEET}/${s}`;
67 changes: 67 additions & 0 deletions src/lib/util/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { browser } from '$app/env';

// TODO #23 Pretty colors w/ golden ratio
const _USER_COLORS = [
'#30bced',
Expand All @@ -11,3 +13,68 @@ const _USER_COLORS = [
];

export const randomColor = () => _USER_COLORS[Math.floor(Math.random() * _USER_COLORS.length)];

export function copyToClipboard(text: string): void {
if (!browser) {
console.error('Cannot copy: Not in browser.');
return;
}

const textArea = document.createElement('textarea');

//
// *** This styling is an extra step which is likely not required. ***
//
// Why is it here? To ensure:
// 1. the element is able to have focus and selection.
// 2. if the element was to flash render it has minimal visual impact.
// 3. less flakyness with selection and copying which **might** occur if
// the textarea element is not visible.
//
// The likelihood is the element won't even render, not even a
// flash, so some of these are just precautions. However in
// Internet Explorer the element is visible whilst the popup
// box asking the user for permission for the web page to
// copy to the clipboard.
//

// Place in the top-left corner of screen regardless of scroll position.
textArea.style.position = 'fixed';
textArea.style.top = '0';
textArea.style.left = '0';

// Ensure it has a small width and height. Setting to 1px / 1em
// doesn't work as this gives a negative w/h on some browsers.
textArea.style.width = '2em';
textArea.style.height = '2em';

// We don't need padding, reducing the size if it does flash render.
textArea.style.padding = '0';

// Clean up any borders.
textArea.style.border = 'none';
textArea.style.outline = 'none';
textArea.style.boxShadow = 'none';

// Avoid flash of the white box if rendered for any reason.
textArea.style.background = 'transparent';

textArea.value = text;

document.body.appendChild(textArea);
textArea.focus();
textArea.select();

try {
if (!document.execCommand('copy')) {
throw new Error('Could not copy');
}
// var msg = successful ? 'successful' : 'unsuccessful';
// console.log('Copying text command was ' + msg);
} catch (err) {
console.error(`Unable to copy: ${text}`);
alert(`Unable to copy: ${text}`);
}

document.body.removeChild(textArea);
}
18 changes: 18 additions & 0 deletions src/lib/util/naming.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ export const randomAnimal = () => _ANIMALS[Math.floor(Math.random() * _ANIMALS_L
export const randomName = (machine = false): string =>
`${randomDescriptor()} ${randomAnimal()}`.replace(' ', machine ? '-' : ' ');

export const randomMeetingName = () =>
`${randomAnimal().toLowerCase().replace(' ', '-')}-${makeid(10)}`;

export const emojiFromName = (name: string): string => {
if (_NAME_TO_EMOJI[name]) {
return _NAME_TO_EMOJI[name];
Expand All @@ -17,6 +20,21 @@ export const emojiFromName = (name: string): string => {
return v;
};

/**
* h/t https://stackoverflow.com/a/1349426/3422060
* @param length Length of ID
* @returns an ID
*/
function makeid(length: number): string {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}

const _NAME_TO_EMOJI = { Monkey: '🐒', Gorilla: '🦍', Orangutan: '🦧', 'Dog Face': '🐶', Dog: '🐕', 'Guide Dog': '🦮', 'Service Dog': '🐕‍🦺', Poodle: '🐩', Wolf: '🐺', Fox: '🦊', Raccoon: '🦝', Cat: '🐈', 'Black Cat': '🐈‍⬛', Lion: '🦁', Tiger: '🐅', Leopard: '🐆', Horse: '🐎', Unicorn: '🦄', Zebra: '🦓', Deer: '🦌', Ox: '🐂', 'Water Buffalo': '🐃', Cow: '🐄', Pig: '🐖', Boar: '🐗', 'Pig Nose': '🐽', Ram: '🐏', Ewe: '🐑', Goat: '🐐', Camel: '🐪', 'Two-hump Camel': '🐫', Llama: '🦙', Giraffe: '🦒', Elephant: '🐘', Mammoth: '🦣', Rhinoceros: '🦏', Hippopotamus: '🦛', Mouse: '🐁', Rat: '🐀', Hamster: '🐹', Rabbit: '🐇', Chipmunk: '🐿️', Beaver: '🦫', Hedgehog: '🦔', Bat: '🦇', Bear: '🐻', 'Polar Bear': '🐻‍❄️', Koala: '🐨', Panda: '🐼', Sloth: '🦥', Otter: '🦦', Skunk: '🦨', Kangaroo: '🦘', Badger: '🦡', 'Paw Prints': '🐾', Turkey: '🦃', Chicken: '🐔', Rooster: '🐓', 'Hatching Chick': '🐣', 'Baby Chick': '🐤', Bird: '🐦', Penguin: '🐧', Dove: '🕊️', Eagle: '🦅', Duck: '🦆', Swan: '🦢', Owl: '🦉', Dodo: '🦤', Feather: '🪶', Flamingo: '🦩', Peacock: '🦚', Parrot: '🦜', Frog: '🐸', Crocodile: '🐊', Turtle: '🐢', Lizard: '🦎', Snake: '🐍', Dragon: '🐉', Sauropod: '🦕', 'T-Rex': '🦖', Whale: '🐋', Dolphin: '🐬', Seal: '🦭', Fish: '🐟', 'Tropical Fish': '🐠', Blowfish: '🐡', Shark: '🦈', Octopus: '🐙', 'Spiral Shell': '🐚', Coral: '🪸', Snail: '🐌', Butterfly: '🦋', Bug: '🐛', Ant: '🐜', Honeybee: '🐝', Beetle: '🪲', 'Lady Beetle': '🐞', Cricket: '🦗', Cockroach: '🪳', Spider: '🕷️', 'Spider Web': '🕸️', Scorpion: '🦂', Mosquito: '🦟', Fly: '🪰', Worm: '🪱', Microbe: '🦠' } as Record<string,string>; // prettier-ignore
// Not included:
// "Tiger Face": "🐯", "Cat Face": "🐱", "Horse Face": "🐴", "Bison": "🦬", "Cow Face": "🐮", "Pig Face": "🐷", "Mouse Face": "🐭", "Rabbit Face": "🐰", "Cat Face": "🐱", "Front-facing Baby Chick": "🐥", "Dragon Face": "🐲", "Spouting Whale": "🐳", "Monkey Face": "🐵",
Expand Down
12 changes: 12 additions & 0 deletions src/routes/__layout-root.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script lang="ts">
import PersistentSession from '$containers/PersistentSession.svelte';
import { PROJECT_NAME } from '$lib/constants';
import '../app.scss';
</script>

<svelte:head>
<title>{PROJECT_NAME}</title>
</svelte:head>

<slot />
<PersistentSession />
2 changes: 0 additions & 2 deletions src/routes/__layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
<title>{PROJECT_NAME}</title>
</svelte:head>

<header />

<main id="svelte">
<slot />
</main>
Expand Down
12 changes: 12 additions & 0 deletions src/routes/meet/[slug]/[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script lang="ts">
import { page } from '$app/stores';
import MeetingNavbar from '$components/MeetingNavbar/MeetingNavbar.svelte';
import { PROJECT_NAME } from '$lib/constants';
</script>

<svelte:head>
<title>Meet {$page.params.slug} | {PROJECT_NAME}</title>
</svelte:head>

<MeetingNavbar slug={$page.params.slug} href={$page.url.href} />
<slot />
3 changes: 3 additions & 0 deletions src/routes/meet/[slug]/index.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<h1 class="title is-1">Meeting</h1>

<p>TODO: Carry out actual meeting here.</p>
3 changes: 3 additions & 0 deletions src/routes/meet/create.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<h1 class="title is-1">Create a new meeting</h1>

<p>TODO: Create a new meeting here</p>
3 changes: 3 additions & 0 deletions src/routes/meet/index.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<h1 class="title is-1">Meetings</h1>
<!-- TODO #29 List all pre-existing meetings in /meet/index.svelte -->
<p>TODO: List all previous sessions here.</p>