[READ-ONLY] Mirror of https://github.com/mrgnw/ananas. learn multiple languages at once ananas.xcc.es
0

Configure Feed

Select the types of activity you want to include in your feed.

Squashed commit of the following:

commit d590ed7db81dd385aec67da163015ce75ffca8d8
Author: Morgan Williams <2504532+mrgnw@users.noreply.github.com>
Date: Wed Jun 18 01:12:38 2025 +0200

Update +page.server.ts

commit c936a2af39317659982c12ed5053183148fbaae5
Author: Morgan <2504532+mrgnw@users.noreply.github.com>
Date: Tue Jun 17 22:40:31 2025 +0200

Update +page.svelte

commit 6145372bd4d82010d877b4657cc0674f1d113ede
Author: Morgan <2504532+mrgnw@users.noreply.github.com>
Date: Tue Jun 17 22:36:40 2025 +0200

WIP highlighting

commit aca063a79b1bb32875f828ec16bf9ed633a27b55
Author: Morgan <2504532+mrgnw@users.noreply.github.com>
Date: Tue Jun 17 22:24:40 2025 +0200

wip YES minimalism

commit 809025b13a01915970c856e9d95962c1adb606e8
Author: Morgan <2504532+mrgnw@users.noreply.github.com>
Date: Tue Jun 17 22:23:35 2025 +0200

wip simpler

commit 792fdad91546d99c6a13ebd0fc380b257fbec5ec
Author: Morgan <2504532+mrgnw@users.noreply.github.com>
Date: Tue Jun 17 22:19:32 2025 +0200

wip debug

commit 1ac6985a27b45717b4c3b021f4bd8e72a592f2a5
Author: Morgan <2504532+mrgnw@users.noreply.github.com>
Date: Tue Jun 17 22:06:02 2025 +0200

better /debug

commit b318d14cb46414edaba22f5b8d11d8ac051cde1f
Author: Morgan <2504532+mrgnw@users.noreply.github.com>
Date: Tue Jun 17 21:52:41 2025 +0200

/debug

commit 89d5e0a8994c40c2c509463de28e80bb745b9ec0
Author: Morgan <2504532+mrgnw@users.noreply.github.com>
Date: Tue Jun 17 21:46:40 2025 +0200

WIP no settings button - movce to acct

+174 -35
bun.lockb

This is a binary file and will not be displayed.

+1
package.json
··· 54 54 "drizzle-orm": "^0.43.1", 55 55 "kit-monorepo": "sveltejs/kit", 56 56 "lucide-svelte": "^0.344.0", 57 + "shiki": "^3.6.0", 57 58 "svelte": "^5.10.1", 58 59 "svelte-dnd-action": "^0.9.52", 59 60 "svelte-inspect-value": "^0.4.0",
-35
src/routes/+layout.svelte
··· 1 1 <script> 2 2 import "../app.pcss"; 3 - import SettingsButton from "$lib/components/SettingsButton.svelte"; 4 3 import { Languages } from 'lucide-svelte'; 5 4 import { Button } from "$lib/components/ui/button"; 6 5 import { page } from "$app/stores"; ··· 92 91 93 92 {@render children?.()} 94 93 95 - {#if browser} 96 - <div class="debug-controls"> 97 - <!-- Future feature: country detection / language suggestion --> 98 - <!-- {#if hasCountryCode && countryFlag} 99 - <Button 100 - variant="outline" 101 - size="icon" 102 - class="rounded-full shadow-lg hover:shadow-xl transition-all duration-200" 103 - title={countryInfo?.name || countryCode} 104 - > 105 - <span class="text-lg">{countryFlag}</span> 106 - </Button> 107 - {/if} --> 108 - <SettingsButton {...allProps} /> 109 - </div> 110 - {/if} 111 94 112 95 <style> 113 96 .main-navbar { ··· 171 154 } 172 155 } 173 156 174 - .debug-controls { 175 - position: fixed; 176 - bottom: 1rem; 177 - right: 1rem; 178 - display: flex; 179 - gap: 0.5rem; 180 - z-index: 60; 181 - background: rgba(255, 255, 255, 0.5); 182 - padding: 0.5rem; 183 - border-radius: 0.5rem; 184 - } 185 - 186 - /* Hide debug controls on mobile to prevent input overlap */ 187 - @media (max-width: 767px) { 188 - .debug-controls { 189 - display: none; 190 - } 191 - } 192 157 </style>
+31
src/routes/debug/+page.server.ts
··· 1 + import { codeToHtml } from 'shiki'; 2 + import type { PageServerLoad } from './$types'; 3 + 4 + export const load: PageServerLoad = async ({ url, request, locals, params }) => { 5 + // Get all the data we want to highlight 6 + const props = { 7 + ip_country: locals.ip_country || null, 8 + accept_language: request.headers.get('accept-language'), 9 + countryInfo: locals.countryInfo || null, 10 + allHeaders: Object.fromEntries(request.headers.entries()), 11 + testQueryResult: { 12 + fruit: url.searchParams.get('fruit') || 'banana' 13 + }, 14 + user: locals.user || null, 15 + userPreferences: locals.userPreferences || null 16 + }; 17 + 18 + // Highlight the JSON with Catppuccin Latte 19 + const highlightedPropsJson = await codeToHtml( 20 + JSON.stringify(props, null, 2), 21 + { 22 + lang: 'json', 23 + theme: 'catppuccin-latte' 24 + } 25 + ); 26 + 27 + return { 28 + ...props, 29 + highlightedPropsJson 30 + }; 31 + };
+138
src/routes/debug/+page.svelte
··· 1 + <script> 2 + import { getContext } from 'svelte'; 3 + import { toast } from "svelte-sonner"; 4 + import { defaultLanguages } from '$lib/utils/languages.js'; 5 + import { getLanguageSuggestions } from '$lib/utils/languageSuggestions.ts'; 6 + import { Copy } from 'lucide-svelte'; 7 + 8 + const userStore = getContext('user'); 9 + let { data } = $props(); 10 + 11 + // Raw JSON for copying 12 + let rawJson = $derived.by(() => { 13 + const { highlightedPropsJson, ...propsData } = data; 14 + return JSON.stringify(propsData, null, 2); 15 + }); 16 + 17 + function copyToClipboard() { 18 + navigator.clipboard.writeText(rawJson); 19 + toast.success("Props copied"); 20 + } 21 + 22 + function clearCache() { 23 + localStorage.clear(); 24 + toast.success("Cache cleared"); 25 + window.location.reload(); 26 + } 27 + 28 + function addSuggested() { 29 + const suggestions = getLanguageSuggestions(data.ip_country); 30 + suggestions.forEach(suggestion => userStore.addLanguage(suggestion.code)); 31 + toast.success("Added suggested"); 32 + } 33 + 34 + function addExamples() { 35 + Object.keys(defaultLanguages).forEach(code => userStore.addLanguage(code)); 36 + toast.success("Added examples"); 37 + } 38 + 39 + function clearAllLanguages() { 40 + userStore.user.selectedLanguages.slice().forEach(code => userStore.removeLanguage(code)); 41 + toast.success("Cleared languages"); 42 + } 43 + </script> 44 + 45 + <svelte:head> 46 + <title>Debug</title> 47 + </svelte:head> 48 + 49 + <div class="debug"> 50 + <div class="info"> 51 + <div><b>languages</b> {data.user?.selectedLanguages?.join(' ') || userStore.user.selectedLanguages?.join(' ') || 'none'}</div> 52 + </div> 53 + 54 + <div class="actions"> 55 + + <a href="#" onclick={addSuggested}>suggested</a> <a href="#" onclick={addExamples}>examples</a> <a href="#" onclick={clearAllLanguages}>clear</a> 56 + <br> 57 + <a href="#" onclick={clearCache}>clear cache</a> 58 + </div> 59 + 60 + <div class="props-container"> 61 + <div class="props">{@html data.highlightedPropsJson}</div> 62 + <button class="copy-btn" onclick={copyToClipboard} title="Copy"> 63 + <Copy size={16} /> 64 + </button> 65 + </div> 66 + </div> 67 + 68 + <style> 69 + .debug { 70 + max-width: 800px; 71 + margin: 2rem auto; 72 + padding: 2rem; 73 + font-family: monospace; 74 + line-height: 1.5; 75 + } 76 + 77 + .actions a { 78 + color: #3730a3; 79 + text-decoration: none; 80 + border-bottom: 1px solid transparent; 81 + } 82 + 83 + .actions a:hover { 84 + border-bottom-color: #3730a3; 85 + } 86 + 87 + .info { 88 + color: #666; 89 + } 90 + 91 + .props-container { 92 + position: relative; 93 + } 94 + 95 + .props { 96 + border-radius: 4px; 97 + overflow-x: auto; 98 + } 99 + 100 + .props :global(pre) { 101 + margin: 0; 102 + padding: 1rem; 103 + font-size: 0.875rem; 104 + overflow-x: auto; 105 + white-space: pre-wrap; 106 + } 107 + 108 + .copy-btn { 109 + position: absolute; 110 + top: 0.5rem; 111 + right: 0.5rem; 112 + background: none; 113 + border: none; 114 + cursor: pointer; 115 + opacity: 0.7; 116 + transition: opacity 0.15s; 117 + display: flex; 118 + align-items: center; 119 + justify-content: center; 120 + color: #666; 121 + } 122 + 123 + .copy-btn:hover { 124 + opacity: 1; 125 + } 126 + 127 + @media (max-width: 600px) { 128 + .debug { 129 + margin: 1rem; 130 + padding: 1rem; 131 + } 132 + 133 + .actions { 134 + flex-direction: column; 135 + gap: 0.5rem; 136 + } 137 + } 138 + </style>
+4
src/routes/user/+page.svelte
··· 25 25 isLoggingOut = false; 26 26 } 27 27 } 28 + 28 29 </script> 29 30 30 31 <section class="user-info"> ··· 67 68 <p class="empty">No languages selected.</p> 68 69 {/if} 69 70 </div> 71 + 70 72 </section> 73 + 71 74 72 75 <style> 73 76 .user-info { ··· 225 228 padding: 1em 0.5em 1em 0.5em; 226 229 } 227 230 } 231 + 228 232 </style>