mirror of
https://github.com/supabase/supabase.git
synced 2026-10-16 22:59:11 +03:00
fix: update slot syntax and runes implementation
Co-Authored-By: charis@supabase.io <charis@supabase.io>
This commit is contained in:
1 parent
86eb85ebf2
commit
ffd64ca486
4 files changed
+78
-74
No files matched your search
@@ -2,19 +2,19 @@
|
||||
<script lang="ts">
|
||||
import '../styles.css'
|
||||
import { invalidate } from '$app/navigation'
|
||||
import { state, effect, props } from 'svelte'
|
||||
|
||||
let $data;
|
||||
let $supabase;
|
||||
let $session;
|
||||
let { data } = props()
|
||||
let { supabase, session } = data
|
||||
|
||||
$effect(() => {
|
||||
const { data } = $supabase.auth.onAuthStateChange((event, _session) => {
|
||||
if (_session?.expires_at !== $session?.expires_at) {
|
||||
effect(() => {
|
||||
const { data: authData } = supabase.auth.onAuthStateChange((event, _session) => {
|
||||
if (_session?.expires_at !== session?.expires_at) {
|
||||
invalidate('supabase:auth')
|
||||
}
|
||||
})
|
||||
|
||||
return () => data.subscription.unsubscribe()
|
||||
return () => authData.subscription.unsubscribe()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -23,5 +23,5 @@
|
||||
</svelte:head>
|
||||
|
||||
<div class="container" style="padding: 50px 0 100px 0">
|
||||
{@render $$slots.default()}
|
||||
<slot />
|
||||
</div>
|
||||
@@ -1,16 +1,17 @@
|
||||
<!-- src/routes/+page.svelte -->
|
||||
<script lang="ts">
|
||||
import { enhance } from '$app/forms'
|
||||
import { state, props } from 'svelte'
|
||||
import type { ActionData, SubmitFunction } from './$types.js'
|
||||
|
||||
let $form: ActionData;
|
||||
let $loading = $state(false);
|
||||
let { form } = props<{ form: ActionData }>()
|
||||
let loading = state(false)
|
||||
|
||||
const handleSubmit: SubmitFunction = () => {
|
||||
$loading = true;
|
||||
loading = true
|
||||
return async ({ update }) => {
|
||||
update();
|
||||
$loading = false;
|
||||
update()
|
||||
loading = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -23,9 +24,9 @@
|
||||
<div class="col-6 form-widget">
|
||||
<h1 class="header">Supabase + SvelteKit</h1>
|
||||
<p class="description">Sign in via magic link with your email below</p>
|
||||
{#if $form?.message !== undefined}
|
||||
<div class="success {$form?.success ? '' : 'fail'}">
|
||||
{$form?.message}
|
||||
{#if form?.message !== undefined}
|
||||
<div class="success {form?.success ? '' : 'fail'}">
|
||||
{form?.message}
|
||||
</div>
|
||||
{/if}
|
||||
<div>
|
||||
@@ -36,17 +37,17 @@
|
||||
class="inputField"
|
||||
type="email"
|
||||
placeholder="Your email"
|
||||
value={$form?.email ?? ''}
|
||||
value={form?.email ?? ''}
|
||||
/>
|
||||
</div>
|
||||
{#if $form?.errors?.email}
|
||||
{#if form?.errors?.email}
|
||||
<span class="flex items-center text-sm error">
|
||||
{$form?.errors?.email}
|
||||
{form?.errors?.email}
|
||||
</span>
|
||||
{/if}
|
||||
<div>
|
||||
<button class="button primary block">
|
||||
{ $loading ? 'Loading' : 'Send magic link' }
|
||||
{ loading ? 'Loading' : 'Send magic link' }
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+26
-26
@@ -1,32 +1,32 @@
|
||||
<!-- src/routes/account/+page.svelte -->
|
||||
<script lang="ts">
|
||||
import { enhance } from '$app/forms';
|
||||
import type { SubmitFunction } from '@sveltejs/kit';
|
||||
import Avatar from './Avatar.svelte'
|
||||
import { enhance } from '$app/forms'
|
||||
import { state, props } from 'svelte'
|
||||
import type { SubmitFunction } from '@sveltejs/kit'
|
||||
import Avatar from './Avatar.svelte'
|
||||
|
||||
let $data;
|
||||
let $form;
|
||||
let { session, supabase, profile } = $data;
|
||||
let { data, form } = $props()
|
||||
let { session, supabase, profile } = data
|
||||
|
||||
let $profileForm = $state<HTMLFormElement | null>(null);
|
||||
let $loading = $state(false);
|
||||
let $fullName = $state(profile?.full_name ?? '');
|
||||
let $username = $state(profile?.username ?? '');
|
||||
let $website = $state(profile?.website ?? '');
|
||||
let $avatarUrl = $state(profile?.avatar_url ?? '');
|
||||
let profileForm = $state<HTMLFormElement | null>(null)
|
||||
let loading = $state(false)
|
||||
let fullName = $state(profile?.full_name ?? '')
|
||||
let username = $state(profile?.username ?? '')
|
||||
let website = $state(profile?.website ?? '')
|
||||
let avatarUrl = $state(profile?.avatar_url ?? '')
|
||||
|
||||
const handleSubmit: SubmitFunction = () => {
|
||||
$loading = true;
|
||||
loading = true
|
||||
return async () => {
|
||||
$loading = false;
|
||||
loading = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleSignOut: SubmitFunction = () => {
|
||||
$loading = true;
|
||||
loading = true
|
||||
return async ({ update }) => {
|
||||
$loading = false;
|
||||
update();
|
||||
loading = false
|
||||
update()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -37,14 +37,14 @@
|
||||
method="post"
|
||||
action="?/update"
|
||||
use:enhance={handleSubmit}
|
||||
bind:this={$profileForm}
|
||||
bind:this={profileForm}
|
||||
>
|
||||
<Avatar
|
||||
{supabase}
|
||||
bind:url={$avatarUrl}
|
||||
bind:url={avatarUrl}
|
||||
size={10}
|
||||
on:upload={() => {
|
||||
$profileForm.requestSubmit();
|
||||
profileForm.requestSubmit();
|
||||
}}
|
||||
/>
|
||||
<div>
|
||||
@@ -54,32 +54,32 @@
|
||||
|
||||
<div>
|
||||
<label for="fullName">Full Name</label>
|
||||
<input id="fullName" name="fullName" type="text" value={$form?.fullName ?? $fullName} />
|
||||
<input id="fullName" name="fullName" type="text" value={form?.fullName ?? fullName} />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="username">Username</label>
|
||||
<input id="username" name="username" type="text" value={$form?.username ?? $username} />
|
||||
<input id="username" name="username" type="text" value={form?.username ?? username} />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="website">Website</label>
|
||||
<input id="website" name="website" type="url" value={$form?.website ?? $website} />
|
||||
<input id="website" name="website" type="url" value={form?.website ?? website} />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<input
|
||||
type="submit"
|
||||
class="button block primary"
|
||||
value={$loading ? 'Loading...' : 'Update'}
|
||||
disabled={$loading}
|
||||
value={loading ? 'Loading...' : 'Update'}
|
||||
disabled={loading}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form method="post" action="?/signout" use:enhance={handleSignOut}>
|
||||
<div>
|
||||
<button class="button block" disabled={$loading}>Sign Out</button>
|
||||
<button class="button block" disabled={loading}>Sign Out</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
+31
-28
@@ -2,27 +2,30 @@
|
||||
<script lang="ts">
|
||||
import type { SupabaseClient } from '@supabase/supabase-js'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { state, effect, props } from 'svelte'
|
||||
|
||||
let $size = $state(10);
|
||||
let $url = $state('');
|
||||
let $supabase: SupabaseClient;
|
||||
let { size = 10, url = '', supabase } = props<{
|
||||
size?: number
|
||||
url: string
|
||||
supabase: SupabaseClient
|
||||
}>()
|
||||
|
||||
let $avatarUrl = $state<string | null>(null);
|
||||
let $uploading = $state(false);
|
||||
let $files = $state<FileList | null>(null);
|
||||
let avatarUrl = state<string | null>(null)
|
||||
let uploading = state(false)
|
||||
let files = state<FileList | null>(null)
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
const downloadImage = async (path: string) => {
|
||||
try {
|
||||
const { data, error } = await $supabase.storage.from('avatars').download(path)
|
||||
const { data: imageData, error } = await supabase.storage.from('avatars').download(path)
|
||||
|
||||
if (error) {
|
||||
throw error
|
||||
}
|
||||
|
||||
const url = URL.createObjectURL(data)
|
||||
$avatarUrl = url
|
||||
const imageUrl = URL.createObjectURL(imageData)
|
||||
avatarUrl = imageUrl
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
console.log('Error downloading image: ', error.message)
|
||||
@@ -32,23 +35,23 @@
|
||||
|
||||
const uploadAvatar = async () => {
|
||||
try {
|
||||
$uploading = true
|
||||
uploading = true
|
||||
|
||||
if (!$files || $files.length === 0) {
|
||||
if (!files || files.length === 0) {
|
||||
throw new Error('You must select an image to upload.')
|
||||
}
|
||||
|
||||
const file = $files[0]
|
||||
const file = files[0]
|
||||
const fileExt = file.name.split('.').pop()
|
||||
const filePath = `${Math.random()}.${fileExt}`
|
||||
|
||||
const { error } = await $supabase.storage.from('avatars').upload(filePath, file)
|
||||
const { error } = await supabase.storage.from('avatars').upload(filePath, file)
|
||||
|
||||
if (error) {
|
||||
throw error
|
||||
}
|
||||
|
||||
$url = filePath
|
||||
url = filePath
|
||||
setTimeout(() => {
|
||||
dispatch('upload')
|
||||
}, 100)
|
||||
@@ -57,31 +60,31 @@
|
||||
alert(error.message)
|
||||
}
|
||||
} finally {
|
||||
$uploading = false
|
||||
uploading = false
|
||||
}
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
if ($url) downloadImage($url);
|
||||
});
|
||||
effect(() => {
|
||||
if (url) downloadImage(url)
|
||||
})
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{#if $avatarUrl}
|
||||
{#if avatarUrl}
|
||||
<img
|
||||
src={$avatarUrl}
|
||||
alt={$avatarUrl ? 'Avatar' : 'No image'}
|
||||
src={avatarUrl}
|
||||
alt={avatarUrl ? 'Avatar' : 'No image'}
|
||||
class="avatar image"
|
||||
style="height: {$size}em; width: {$size}em;"
|
||||
style="height: {size}em; width: {size}em;"
|
||||
/>
|
||||
{:else}
|
||||
<div class="avatar no-image" style="height: {$size}em; width: {$size}em;"></div>
|
||||
<div class="avatar no-image" style="height: {size}em; width: {size}em;"></div>
|
||||
{/if}
|
||||
<input type="hidden" name="avatarUrl" value={$url} />
|
||||
<input type="hidden" name="avatarUrl" value={url} />
|
||||
|
||||
<div style="width: {$size}em;">
|
||||
<div style="width: {size}em;">
|
||||
<label class="button primary block" for="single">
|
||||
{$uploading ? 'Uploading ...' : 'Upload'}
|
||||
{uploading ? 'Uploading ...' : 'Upload'}
|
||||
</label>
|
||||
<input
|
||||
style="visibility: hidden; position:absolute;"
|
||||
@@ -90,7 +93,7 @@
|
||||
accept="image/*"
|
||||
bind:files
|
||||
on:change={uploadAvatar}
|
||||
disabled={$uploading}
|
||||
disabled={uploading}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
Reference in new issue
Block a user