main fe6ee00

new-room-window.svelte RawHistoryFolder

1<script lang="ts">
2	import XpWindow from './xp-window.svelte';
3	import { desktop } from '$lib/states/desktop.svelte';
4	import { chatState } from '$lib/states/chat.svelte';
5	import { useAimClient } from '$lib/aim/client';
6
7	const client = useAimClient();
8	const signedIn = $derived(Boolean(chatState.getCurrentUser()));
9	let name = $state('');
10	let topic = $state('');
11	let pending = $state(false);
12	let error = $state('');
13
14	async function create() {
15		const trimmedName = name.trim();
16		const trimmedTopic = topic.trim();
17		if (trimmedName.length < 2 || trimmedName.length > 40) {
18			error = 'Le nom du salon doit contenir entre 2 et 40 caractères.';
19			return;
20		}
21		if (trimmedTopic.length > 120) {
22			error = 'Le sujet ne peut pas dépasser 120 caractères.';
23			return;
24		}
25		pending = true;
26		error = '';
27		try {
28			const room = await client.createGroupRoom(trimmedName, trimmedTopic || undefined);
29			desktop.openChatRoom(room.id, trimmedName);
30			desktop.close('new-room');
31		} catch (err) {
32			error = err instanceof Error ? err.message : 'Impossible de créer le salon.';
33		} finally {
34			pending = false;
35		}
36	}
37</script>
38
39<XpWindow id="new-room" width={340} height={220} resizableWindow={false}>
40	<div class="content">
41		{#if signedIn}
42			<label for="room-name">Nom du salon</label>
43			<input
44				id="room-name"
45				type="text"
46				maxlength="40"
47				minlength="2"
48				bind:value={name}
49				oninput={() => (error = '')}
50			/>
51			<label for="room-topic">Sujet (facultatif)</label>
52			<input
53				id="room-topic"
54				type="text"
55				maxlength="120"
56				bind:value={topic}
57				oninput={() => (error = '')}
58			/>
59			{#if error}<span role="alert">{error}</span>{/if}
60		{:else}
61			<p>Connectez-vous pour créer un salon.</p>
62		{/if}
63		<div class="actions">
64			{#if signedIn}<button disabled={pending} onclick={create}>Créer</button>{:else}<button
65					onclick={() => desktop.openLogin('signin')}>Se connecter</button
66				>{/if}
67			<button onclick={() => desktop.close('new-room')}>Annuler</button>
68		</div>
69	</div>
70</XpWindow>
71
72<style>
73	.content {
74		display: flex;
75		flex-direction: column;
76		gap: 7px;
77		height: 100%;
78		font:
79			11px Tahoma,
80			'Pixelated MS Sans Serif',
81			sans-serif;
82	}
83	input {
84		width: 100%;
85		box-sizing: border-box;
86		font: inherit;
87	}
88	.actions {
89		display: flex;
90		justify-content: flex-end;
91		gap: 6px;
92		margin-top: auto;
93	}
94	[role='alert'] {
95		color: #a00;
96	}
97</style>

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 3

Tags 9

↑↓ moveenter openesc close