detached ac75bce

feat: Enhance chat room registration flow and message visibility

- Increase public message limit from 10 to 50 for better context
- Add registration prompt for users after viewing 50 messages
- Implement dynamic signup modal trigger in chat room
- Update language meta tags and HTML lang attribute to French
- Modify aim-login component to support initial tab state
commit
ac75bce1324602fb6ee82e54704b876ba5c02349
author
Kit · · 2025-02-17 07:26 UTC
parent
596c40c
signature
SSH UnverifiedSHA256:H91DFuEG4jpk5edzLA4aUKkpv4zv9Q339ipRmkph6Tk The key is unknown
5 files · +78 -8
M src/app.html +1 -1
@@ -1,5 +1,5 @@
11 <!doctype html>
2-<html lang="en">
2+<html lang="fr">
33 <head>
44 <meta charset="utf-8" />
55 <link rel="icon" href="%sveltekit.assets%/favicon.png" />
@@ -1,5 +1,5 @@
1 <!doctype html>1 <!doctype html>
2-<html lang="en">2+<html lang="fr">
3 <head>3 <head>
4 <meta charset="utf-8" />4 <meta charset="utf-8" />
5 <link rel="icon" href="%sveltekit.assets%/favicon.png" />5 <link rel="icon" href="%sveltekit.assets%/favicon.png" />
M src/lib/components/aim-login.svelte +10 -2
@@ -7,9 +7,17 @@
77 import { chatState } from '$lib/states/chat.svelte';
88 import Turnstile from './turnstile.svelte';
99
10- let { onLoginSuccess, showAuth = $bindable() }: { onLoginSuccess?: (user: User) => void, showAuth:Boolean } = $props();
10+ let {
11+ onLoginSuccess,
12+ showAuth = $bindable(),
13+ activeTab: initialTab = 'signin'
14+ }: {
15+ onLoginSuccess?: (user: User) => void,
16+ showAuth: Boolean,
17+ activeTab?: 'signin' | 'signup'
18+ } = $props();
1119
12- let activeTab = $state('signin');
20+ let activeTab = $state(initialTab);
1321
1422 // Sign In state
1523 let siUsername = $state('');
@@ -7,9 +7,17 @@
7 import { chatState } from '$lib/states/chat.svelte';7 import { chatState } from '$lib/states/chat.svelte';
8 import Turnstile from './turnstile.svelte';8 import Turnstile from './turnstile.svelte';
9 9
10- let { onLoginSuccess, showAuth = $bindable() }: { onLoginSuccess?: (user: User) => void, showAuth:Boolean } = $props();10+ let {
11+ onLoginSuccess,
12+ showAuth = $bindable(),
13+ activeTab: initialTab = 'signin'
14+ }: {
15+ onLoginSuccess?: (user: User) => void,
16+ showAuth: Boolean,
17+ activeTab?: 'signin' | 'signup'
18+ } = $props();
11 19
12- let activeTab = $state('signin');20+ let activeTab = $state(initialTab);
13 21
14 // Sign In state22 // Sign In state
15 let siUsername = $state('');23 let siUsername = $state('');
M src/lib/components/chat-room.svelte +64 -1
@@ -9,6 +9,7 @@ import { maximizable } from '$lib/actions/maximizable';
99 import LoadingButton from './ui/button-loading.svelte';
1010 import Tooltip from './ui/tooltip.svelte';
1111 import LoadingDots from './ui/loading-dots.svelte';
12+import AimLogin from './aim-login.svelte';
1213 import { formatFrenchDateTime, formatFrenchRelativeTimeSafe } from '$lib/utils/date-format';
1314
1415 // Initialize with default values for SSR
@@ -21,6 +22,7 @@ let currentMessage = $state('');
2122 let showUserList = $state(false);
2223 let isMaximized = $state(false);
2324 let isInitialLoading = $state(true);
25+let showAuth = $state(false);
2426
2527 // Rate limiting state
2628 let cooldownEndTime = $state<number | null>(null);
@@ -74,10 +76,13 @@ let visibleMessages = $derived((() => {
7476 const messageCount = messages.length;
7577 const result: EnrichedMessage[] = isLoggedIn
7678 ? messages
77- : messages.slice(Math.max(0, messageCount - 10));
79+ : messages.slice(Math.max(0, messageCount - 50));
7880 return result;
7981 })());
8082
83+// Add a derived state to check if we're showing the registration prompt
84+let showRegistrationPrompt = $derived(!currentUser && messages.length > 50);
85+
8186 // Add SSE error state
8287 let sseError = $state<string | null>(null);
8388 let sseRetryAfter = $state<number | null>(null);
@@ -372,6 +377,10 @@ $effect(() => {
372377
373378 // Add derived state for total users count
374379 let totalUsers = $derived(onlineUsers.length);
380+
381+function openSignup() {
382+ showAuth = true;
383+}
375384 </script>
376385
377386 {#if showChatRoom}
@@ -454,6 +463,11 @@ let totalUsers = $derived(onlineUsers.length);
454463 <LoadingDots text="Chargement" />
455464 </div>
456465 {/if}
466+ {#if showRegistrationPrompt}
467+ <div class="registration-prompt">
468+ <p>👋 <button class="link-button" onclick={openSignup}>Inscris-toi</button> pour lire le reste du chat !</p>
469+ </div>
470+ {/if}
457471 {#each visibleMessages as message (message.id)}
458472 <div class="message {message.type} text">
459473 {#if message.type === 'emote'}
@@ -521,6 +535,13 @@ let totalUsers = $derived(onlineUsers.length);
521535 </div>
522536 {/if}
523537
538+{#if showAuth}
539+ <AimLogin
540+ bind:showAuth
541+ activeTab={'signup' as const}
542+ />
543+{/if}
544+
524545 <style>
525546 .chat-area, .users-list, input {
526547 font-size: 1rem;
@@ -806,4 +827,46 @@ let totalUsers = $derived(onlineUsers.length);
806827 margin-bottom: 1rem;
807828 border-radius: 4px;
808829 }
830+
831+ .registration-prompt {
832+ background: #fff3e0;
833+ color: #e65100;
834+ padding: 1rem;
835+ margin-bottom: 1rem;
836+ border-radius: 4px;
837+ text-align: center;
838+ font-size: 0.95rem;
839+ border: 1px solid #ffe0b2;
840+ animation: fadeIn 0.3s ease-out;
841+ }
842+
843+ .registration-prompt p {
844+ margin: 0;
845+ }
846+
847+ @keyframes fadeIn {
848+ from {
849+ opacity: 0;
850+ transform: translateY(-10px);
851+ }
852+ to {
853+ opacity: 1;
854+ transform: translateY(0);
855+ }
856+ }
857+
858+ .registration-prompt .link-button {
859+ color: #e65100;
860+ text-decoration: underline;
861+ cursor: pointer;
862+ background: none;
863+ border: none;
864+ padding: 0;
865+ font: inherit;
866+ }
867+
868+ .registration-prompt .link-button:hover {
869+ color: #ef6c00;
870+ text-decoration: none;
871+ }
809872 </style>⏎̸
@@ -9,6 +9,7 @@ import { maximizable } from '$lib/actions/maximizable';
9 import LoadingButton from './ui/button-loading.svelte';9 import LoadingButton from './ui/button-loading.svelte';
10 import Tooltip from './ui/tooltip.svelte';10 import Tooltip from './ui/tooltip.svelte';
11 import LoadingDots from './ui/loading-dots.svelte';11 import LoadingDots from './ui/loading-dots.svelte';
12+import AimLogin from './aim-login.svelte';
12 import { formatFrenchDateTime, formatFrenchRelativeTimeSafe } from '$lib/utils/date-format';13 import { formatFrenchDateTime, formatFrenchRelativeTimeSafe } from '$lib/utils/date-format';
13 14
14 // Initialize with default values for SSR15 // Initialize with default values for SSR
@@ -21,6 +22,7 @@ let currentMessage = $state('');
21 let showUserList = $state(false);22 let showUserList = $state(false);
22 let isMaximized = $state(false);23 let isMaximized = $state(false);
23 let isInitialLoading = $state(true);24 let isInitialLoading = $state(true);
25+let showAuth = $state(false);
24 26
25 // Rate limiting state27 // Rate limiting state
26 let cooldownEndTime = $state<number | null>(null);28 let cooldownEndTime = $state<number | null>(null);
@@ -74,10 +76,13 @@ let visibleMessages = $derived((() => {
74 const messageCount = messages.length;76 const messageCount = messages.length;
75 const result: EnrichedMessage[] = isLoggedIn 77 const result: EnrichedMessage[] = isLoggedIn
76 ? messages 78 ? messages
77- : messages.slice(Math.max(0, messageCount - 10));79+ : messages.slice(Math.max(0, messageCount - 50));
78 return result;80 return result;
79 })());81 })());
80 82
83+// Add a derived state to check if we're showing the registration prompt
84+let showRegistrationPrompt = $derived(!currentUser && messages.length > 50);
85+
81 // Add SSE error state86 // Add SSE error state
82 let sseError = $state<string | null>(null);87 let sseError = $state<string | null>(null);
83 let sseRetryAfter = $state<number | null>(null);88 let sseRetryAfter = $state<number | null>(null);
@@ -372,6 +377,10 @@ $effect(() => {
372 377
373 // Add derived state for total users count378 // Add derived state for total users count
374 let totalUsers = $derived(onlineUsers.length);379 let totalUsers = $derived(onlineUsers.length);
380+
381+function openSignup() {
382+ showAuth = true;
383+}
375 </script>384 </script>
376 385
377 {#if showChatRoom}386 {#if showChatRoom}
@@ -454,6 +463,11 @@ let totalUsers = $derived(onlineUsers.length);
454 <LoadingDots text="Chargement" />463 <LoadingDots text="Chargement" />
455 </div>464 </div>
456 {/if}465 {/if}
466+ {#if showRegistrationPrompt}
467+ <div class="registration-prompt">
468+ <p>👋 <button class="link-button" onclick={openSignup}>Inscris-toi</button> pour lire le reste du chat !</p>
469+ </div>
470+ {/if}
457 {#each visibleMessages as message (message.id)}471 {#each visibleMessages as message (message.id)}
458 <div class="message {message.type} text">472 <div class="message {message.type} text">
459 {#if message.type === 'emote'}473 {#if message.type === 'emote'}
@@ -521,6 +535,13 @@ let totalUsers = $derived(onlineUsers.length);
521 </div>535 </div>
522 {/if}536 {/if}
523 537
538+{#if showAuth}
539+ <AimLogin
540+ bind:showAuth
541+ activeTab={'signup' as const}
542+ />
543+{/if}
544+
524 <style>545 <style>
525 .chat-area, .users-list, input {546 .chat-area, .users-list, input {
526 font-size: 1rem;547 font-size: 1rem;
@@ -806,4 +827,46 @@ let totalUsers = $derived(onlineUsers.length);
806 margin-bottom: 1rem;827 margin-bottom: 1rem;
807 border-radius: 4px;828 border-radius: 4px;
808 }829 }
830+
831+ .registration-prompt {
832+ background: #fff3e0;
833+ color: #e65100;
834+ padding: 1rem;
835+ margin-bottom: 1rem;
836+ border-radius: 4px;
837+ text-align: center;
838+ font-size: 0.95rem;
839+ border: 1px solid #ffe0b2;
840+ animation: fadeIn 0.3s ease-out;
841+ }
842+
843+ .registration-prompt p {
844+ margin: 0;
845+ }
846+
847+ @keyframes fadeIn {
848+ from {
849+ opacity: 0;
850+ transform: translateY(-10px);
851+ }
852+ to {
853+ opacity: 1;
854+ transform: translateY(0);
855+ }
856+ }
857+
858+ .registration-prompt .link-button {
859+ color: #e65100;
860+ text-decoration: underline;
861+ cursor: pointer;
862+ background: none;
863+ border: none;
864+ padding: 0;
865+ font: inherit;
866+ }
867+
868+ .registration-prompt .link-button:hover {
869+ color: #ef6c00;
870+ text-decoration: none;
871+ }
809 </style>⏎̸872 </style>⏎̸
M src/routes/+layout.svelte +1 -2
@@ -226,8 +226,7 @@
226226 <title>{data.meta.title}</title>
227227 <meta name="description" content={data.meta.description} />
228228 <meta name="keywords" content={data.meta.keywords} />
229- <meta name="language" content="French" />
230- <html lang="fr" />
229+ <meta name="language" content="fr" />
231230
232231 <!-- Open Graph / Facebook -->
233232 <meta property="og:locale" content={data.meta.locale} />
@@ -226,8 +226,7 @@
226 <title>{data.meta.title}</title>226 <title>{data.meta.title}</title>
227 <meta name="description" content={data.meta.description} />227 <meta name="description" content={data.meta.description} />
228 <meta name="keywords" content={data.meta.keywords} />228 <meta name="keywords" content={data.meta.keywords} />
229- <meta name="language" content="French" />229+ <meta name="language" content="fr" />
230- <html lang="fr" />
231 230
232 <!-- Open Graph / Facebook -->231 <!-- Open Graph / Facebook -->
233 <meta property="og:locale" content={data.meta.locale} />232 <meta property="og:locale" content={data.meta.locale} />
M src/routes/api/chat/messages/+server.ts +2 -2
@@ -75,9 +75,9 @@ export async function GET({ request, locals }) {
7575 }
7676
7777 // Fetch messages with a limit based on authentication status
78- // Public requests are always limited to 10 messages
78+ // Public requests are limited to 50 messages
7979 // Authenticated users get 100 messages per request
80- const fetchLimit = (isPublic || !locals.session) ? 10 : 100;
80+ const fetchLimit = (isPublic || !locals.session) ? 50 : 100;
8181
8282 const fetchedMessages = await db.select()
8383 .from(messages)
@@ -75,9 +75,9 @@ export async function GET({ request, locals }) {
75 }75 }
76 76
77 // Fetch messages with a limit based on authentication status77 // Fetch messages with a limit based on authentication status
78- // Public requests are always limited to 10 messages78+ // Public requests are limited to 50 messages
79 // Authenticated users get 100 messages per request79 // Authenticated users get 100 messages per request
80- const fetchLimit = (isPublic || !locals.session) ? 10 : 100;80+ const fetchLimit = (isPublic || !locals.session) ? 50 : 100;
81 81
82 const fetchedMessages = await db.select()82 const fetchedMessages = await db.select()
83 .from(messages)83 .from(messages)

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 8

↑↓ moveenter openesc close