aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2023-01-27 09:30:52 -0800
committerAdam Soltys <[email protected]>2023-01-27 09:30:52 -0800
commit1ff3877220343972ba8e7008b7338b41cc4c876d (patch)
tree536c125fe89f92b93ba512f396c4b21cb8f22064 /src
parentd1216faac02e7c02c2f5783ba60c4b35775e5001 (diff)
downloadcoinos-ui-1ff3877220343972ba8e7008b7338b41cc4c876d.tar.gz
coinos-ui-1ff3877220343972ba8e7008b7338b41cc4c876d.zip
image previews
Diffstat (limited to 'src')
-rw-r--r--src/components/AppHeader.svelte4
-rw-r--r--src/components/Avatar.svelte6
-rw-r--r--src/lib/store.js4
-rw-r--r--src/lib/upload.js1
-rw-r--r--src/lib/utils.js2
-rw-r--r--src/routes/(app)/[username]/+layout.server.js3
-rw-r--r--src/routes/(app)/[username]/settings/[...tab]/+page.svelte26
-rw-r--r--src/routes/(app)/[username]/settings/[...tab]/_account.svelte103
8 files changed, 64 insertions, 85 deletions
diff --git a/src/components/AppHeader.svelte b/src/components/AppHeader.svelte
index 59537ffa..8d64e713 100644
--- a/src/components/AppHeader.svelte
+++ b/src/components/AppHeader.svelte
@@ -1,6 +1,6 @@
<script>
import OutClick from 'svelte-outclick';
- import { newPayment, colorTheme } from '$lib/store';
+ import { banner, newPayment, colorTheme } from '$lib/store';
import { goto } from '$app/navigation';
import { Avatar, Icon } from '$comp';
import { t } from '$lib/translations';
@@ -23,7 +23,7 @@
let showMenu = false;
- $: bg = subject?.banner ? `url(/api/public/${subject.id}-banner.webp)` : undefined;
+ $: bg = $banner?.id === subject.id ? `url(${$banner.src})` : subject?.banner ? `url(/api/public/${subject.id}-banner.webp)` : undefined;
$: $page && (showMenu = false);
</script>
diff --git a/src/components/Avatar.svelte b/src/components/Avatar.svelte
index 09161e01..43331c19 100644
--- a/src/components/Avatar.svelte
+++ b/src/components/Avatar.svelte
@@ -1,5 +1,5 @@
<script>
- import { colorTheme } from '$lib/store';
+ import { avatar, banner, colorTheme } from '$lib/store';
import { Icon } from '$comp';
import { punk } from '$lib/utils';
@@ -10,9 +10,9 @@
$: s = size.toString();
$: link = user.anon ? `/${user.pubkey}` : `/${user.username}`;
- $: src =
+ $: src = ($avatar?.id === user.id && $avatar.src) ||
'/api/public/' +
- (user?.profile ? user.id + '-profile.webp' : 'punks/' + punk(user?.pubkey || user?.id || 'aa'));
+ (user.profile ? user.id + '-profile.webp' : 'punks/' + punk(user.pubkey || user.id || 'aa'));
</script>
<a href={link} class:pointer-events-none={disabled}>
diff --git a/src/lib/store.js b/src/lib/store.js
index 5d83a74c..d38eb411 100644
--- a/src/lib/store.js
+++ b/src/lib/store.js
@@ -32,8 +32,8 @@ const persistLocal = (key, defaultValue) => {
return s;
};
-export const avatarUpload = writable();
-export const bannerUpload = writable();
+export const avatar = writable();
+export const banner = writable();
export const colorTheme = writable('from-primary to-gradient');
export const events = writable({});
export const invoice = writable();
diff --git a/src/lib/upload.js b/src/lib/upload.js
index 099e2f30..899dbb0c 100644
--- a/src/lib/upload.js
+++ b/src/lib/upload.js
@@ -1,4 +1,5 @@
export const upload = async (file, type, progress, token) => {
+ console.log("TYPE", type)
let url = `/api/upload/${type}`;
let formData = new FormData();
formData.append('file', file);
diff --git a/src/lib/utils.js b/src/lib/utils.js
index bb6b34fa..e4b1194f 100644
--- a/src/lib/utils.js
+++ b/src/lib/utils.js
@@ -171,7 +171,7 @@ export const sat = (s) => {
export const sats = 100000000;
export const back = () => browser && history.go(-1);
-export const focus = (el) => setTimeout(() => el.focus());
+export const focus = (el) => setTimeout(() => el.focus(), 1);
export const sleep = (n) => new Promise((r) => setTimeout(r, n));
export const wait = async (f, n = 100, s = 300) => {
diff --git a/src/routes/(app)/[username]/+layout.server.js b/src/routes/(app)/[username]/+layout.server.js
index d1b203d7..8279698a 100644
--- a/src/routes/(app)/[username]/+layout.server.js
+++ b/src/routes/(app)/[username]/+layout.server.js
@@ -5,7 +5,8 @@ export let load = async ({ depends, params: { username } }) => {
depends('app:user');
try {
- return { subject: await get(`/users/${username}`) };
+ let subject = await get(`/users/${username}`)
+ return { subject };
} catch (e) {
console.log(e);
throw error(500, 'Unable to retrieve user account data');
diff --git a/src/routes/(app)/[username]/settings/[...tab]/+page.svelte b/src/routes/(app)/[username]/settings/[...tab]/+page.svelte
index 94ca2223..e1555248 100644
--- a/src/routes/(app)/[username]/settings/[...tab]/+page.svelte
+++ b/src/routes/(app)/[username]/settings/[...tab]/+page.svelte
@@ -6,7 +6,7 @@
import { Icon, Spinner, Pin } from '$comp';
import { t } from '$lib/translations';
import { failure, post, success } from '$lib/utils';
- import { avatarUpload, bannerUpload, password, pin } from '$lib/store';
+ import { avatar, banner, password, pin } from '$lib/store';
import { upload } from '$lib/upload';
import { page } from '$app/stores';
import { sign, send, reEncryptEntropy } from '$lib/nostr';
@@ -46,7 +46,7 @@
$: ({ comp } = tabs.find((t) => t.name === tab));
- let { address, username } = user;
+ let { address, id, username } = user;
let loading;
async function handleSubmit() {
@@ -58,17 +58,14 @@
data.set('cipher', await reEncryptEntropy(user, data.get('password')));
}
- try {
- if ($avatarUpload) {
- await upload($avatarUpload.file, $avatarUpload.type, $avatarUpload.progress, token);
- }
+ if ($avatar) {
+ await upload($avatar.file, $avatar.type, $avatar.progress, token);
+ await fetch(`/api/public/${id}-profile.webp`, {cache: 'reload', mode: 'no-cors'})
+ }
- if ($bannerUpload) {
- await upload($bannerUpload.file, $bannerUpload.type, $bannerUpload.progress, token);
- }
- } catch (e) {
- console.log(e);
- failure('Something went wrong');
+ if ($banner) {
+ await upload($banner.file, $banner.type, $banner.progress, token);
+ await fetch(`/api/public/${id}-banner.webp`, {cache: 'reload', mode: 'no-cors'})
}
let event = {
@@ -99,11 +96,12 @@
}
applyAction(result);
- loading = false;
} catch (e) {
console.log(e);
- failure('Problem submitting form');
+ failure('Something went wrong');
}
+
+ loading = false;
}
let loaded;
diff --git a/src/routes/(app)/[username]/settings/[...tab]/_account.svelte b/src/routes/(app)/[username]/settings/[...tab]/_account.svelte
index 93b5442d..9b5af6d3 100644
--- a/src/routes/(app)/[username]/settings/[...tab]/_account.svelte
+++ b/src/routes/(app)/[username]/settings/[...tab]/_account.svelte
@@ -1,18 +1,14 @@
<script>
import { tick } from 'svelte';
- import { colorTheme, avatarUpload, bannerUpload } from '$lib/store';
+ import { colorTheme, avatar, banner } from '$lib/store';
import { Icon } from '$comp';
import { t } from '$lib/translations';
- import { upload } from '$lib/upload';
- export let user;
+ export let rates, user, submit;
+ let { id } = user;
let selectedTheme = 1;
- let profileFile;
- let select = (type) => files[type].el.click();
-
- $: profile = files.profile.src;
- $: banner = files.banner.src;
+ let avatarFile, avatarInput, bannerFile, bannerInput;
let colorThemes = [
{ theme: 1, color1: 'from-[#F5F7FA]', color2: 'to-[#C3CFE2]' },
@@ -28,6 +24,9 @@
$colorTheme = colors.color1 + ' ' + colors.color2;
};
+ let selectAvatar = () => avatarInput.click();
+ let selectBanner = () => bannerInput.click();
+
let percent;
let progress = async (event) => {
percent = Math.round((event.loaded / event.total) * 100);
@@ -35,23 +34,29 @@
let tooLarge = {};
- let files = { profile: {}, banner: {} };
let handleFile = async ({ target }, type) => {
tooLarge[type] = false;
let file = target.files[0];
+ if (!file) return;
+
if (file.size > 10000000) return (tooLarge[type] = true);
+
+ if(type === 'profile') {
+ $avatar = { id, file, type, progress };
+ } else if (type === 'banner') {
+ $banner = { id, file, type, progress };
+ }
+
var reader = new FileReader();
reader.onload = async (e) => {
- files[type].src = e.target.result;
+ if (type === 'profile') {
+ $avatar.src = e.target.result;
+ } else if (type === 'banner') {
+ $banner.src = e.target.result;
+ }
};
- reader.readAsDataURL(file);
- files[type].filename = file.name;
- if (type === 'profile') {
- $avatarUpload = { file, type, progress };
- } else if (type === 'banner') {
- $bannerUpload = { file, type, progress };
- }
+ reader.readAsDataURL(file);
};
if (!user.display) user.display = user.username;
@@ -78,26 +83,14 @@
<span class="font-bold">{$t('user.settings.profileImage')}</span>
<div class="flex">
- {#if profile}
- <div
- class="relative rounded-full overflow-hidden text-center w-20 h-20 my-auto hover:opacity-80 cursor-pointer"
- on:click={() => select('profile')}
- on:keydown={() => select('profile')}
- >
- <img
- src={profile}
- class="absolute w-full h-full object-cover object-center visible overflow-hidden"
- alt={user.username}
- />
- </div>
- {:else if user.profile}
+ {#if $avatar || user.profile}
<div
class="relative rounded-full overflow-hidden text-center w-20 h-20 my-auto hover:opacity-80 cursor-pointer"
- on:click={() => select('profile')}
- on:keydown={() => select('profile')}
+ on:click={selectAvatar}
+ on:keydown={selectAvatar}
>
<img
- src={`/api/public/${user.id}-profile.webp`}
+ src={$avatar?.src || `/api/public/${user.id}-profile.webp`}
class="absolute w-full h-full object-cover object-center visible overflow-hidden"
alt={user.username}
/>
@@ -105,8 +98,8 @@
{:else}
<div
class="rounded-full border-4 border-white p-4 bg-gradient-to-r {$colorTheme} w-24 my-auto hover:opacity-80 cursor-pointer"
- on:click={() => select('profile')}
- on:keydown={() => select('profile')}
+ on:click={selectAvatar}
+ on:keydown={selectAvatar}
>
<Icon icon="logo-symbol-white" style="mx-auto" />
</div>
@@ -116,22 +109,19 @@
<button
type="button"
class="border rounded-2xl font-bold w-24 text-center px-0 py-2 hover:opacity-80"
- on:click={() => select('profile')}
- on:keydown={() => select('profile')}>{$t('user.settings.select')}</button
+ on:click={selectAvatar}
+ on:keydown={selectAvatar}>{$t('user.settings.select')}</button
>
<input
type="file"
class="hidden"
- bind:this={files.profile.el}
+ bind:this={avatarInput}
on:change={(e) => handleFile(e, 'profile')}
/>
- {#if files.profile.filename}
- <div class="mt-2 text-sm">{files.profile.filename}</div>
- {/if}
</div>
</div>
- {#if tooLarge['profile']}
+ {#if tooLarge['avatar']}
<div class="text-red-600">Max file size 10MB</div>
{/if}
</div>
@@ -141,27 +131,19 @@
<span class="font-bold">{$t('user.settings.bannerImage')}</span>
</div>
- {#if banner}
- <img
- src={banner}
- class="w-full object-cover object-center visible overflow-hidden h-48 mb-4 hover:opacity-80"
- on:click={() => select('banner')}
- on:keydown={() => select('banner')}
- alt="Banner"
- />
- {:else if user.banner}
+ {#if $banner || user.banner}
<img
- src={`/api/public/${user.id}-banner.webp`}
+ src={$banner ? $banner.src : `/api/public/${user.id}-banner.webp`}
class="w-full object-cover object-center visible overflow-hidden h-48 mb-4 hover:opacity-80"
- on:click={() => select('banner')}
- on:keydown={() => select('banner')}
+ on:click={selectBanner}
+ on:keydown={selectBanner}
alt="Banner"
/>
{:else}
<div
class="bg-gradient-to-r {$colorTheme} w-full h-48 mb-4 cursor-pointer hover:opacity-80"
- on:click={() => select('banner')}
- on:keydown={() => select('banner')}
+ on:click={selectBanner}
+ on:keydown={selectBanner}
alt="Banner"
/>
{/if}
@@ -169,18 +151,15 @@
<button
type="button"
class="border rounded-2xl font-bold w-24 text-center px-0 py-2 hover:opacity-80"
- on:click={() => select('banner')}
- on:keydown={() => select('banner')}>{$t('user.settings.select')}</button
+ on:click={selectBanner}
+ on:keydown={selectBanner}>{$t('user.settings.select')}</button
>
<input
type="file"
class="hidden"
- bind:this={files.banner.el}
+ bind:this={bannerInput}
on:change={(e) => handleFile(e, 'banner')}
/>
- {#if files.banner.filename}
- <div class="mt-2 text-sm">{files.banner.filename}</div>
- {/if}
{#if tooLarge['banner']}
<div class="text-red-600">Max file size 10MB</div>