Compare commits

..

3 Commits

Author SHA1 Message Date
priyanshu_bharti fdb604e350 Use type=email for signup/login email inputs (#225) (#228)
Co-authored-by: Priyanshubhartistm <bhartipriyanshustm@gmail.com>
Co-committed-by: Priyanshubhartistm <bhartipriyanshustm@gmail.com>
2026-04-17 18:55:04 +00:00
deveshanim3 3c66dfd83c fix/wrong-message-offline (#222)
Co-authored-by: deveshanim3 <deveshsingh6986@gmail.com>
Co-committed-by: deveshanim3 <deveshsingh6986@gmail.com>
2026-04-17 18:24:55 +00:00
userAdityaa 81633b0a1e fix: vertical alignment of emoji and overflow buttons in shared event action row (#219)
Co-authored-by: userAdityaa <aditya.chaudhary1558@gmail.com>
Co-committed-by: userAdityaa <aditya.chaudhary1558@gmail.com>
2026-04-17 15:22:40 +00:00
11 changed files with 107 additions and 148 deletions
+3 -2
View File
@@ -42,7 +42,7 @@
let popover: Instance | undefined = $state() let popover: Instance | undefined = $state()
</script> </script>
<Button class="join rounded-full"> <div class="join items-center rounded-full">
{#if ENABLE_ZAPS && !hideZap} {#if ENABLE_ZAPS && !hideZap}
<ZapButton {url} {event} class="btn join-item btn-neutral btn-xs"> <ZapButton {url} {event} class="btn join-item btn-neutral btn-xs">
<Icon icon={Bolt} size={4} /> <Icon icon={Bolt} size={4} />
@@ -52,6 +52,7 @@
<Icon icon={SmileCircle} size={4} /> <Icon icon={SmileCircle} size={4} />
</EmojiButton> </EmojiButton>
<Tippy <Tippy
class="flex"
bind:popover bind:popover
component={EventMenu} component={EventMenu}
props={{url, noun, event, customActions, onClick: hidePopover}} props={{url, noun, event, customActions, onClick: hidePopover}}
@@ -60,4 +61,4 @@
<Icon icon={MenuDots} size={4} /> <Icon icon={MenuDots} size={4} />
</Button> </Button>
</Tippy> </Tippy>
</Button> </div>
+1 -1
View File
@@ -90,7 +90,7 @@
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input input-bordered flex w-full items-center gap-2">
<Icon icon={Letter} /> <Icon icon={Letter} />
<input bind:value={email} /> <input type="email" bind:value={email} />
</label> </label>
{/snippet} {/snippet}
</FieldInline> </FieldInline>
+1 -1
View File
@@ -61,7 +61,7 @@
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input input-bordered flex w-full items-center gap-2">
<Icon icon={Letter} /> <Icon icon={Letter} />
<input bind:value={email} /> <input type="email" bind:value={email} />
</label> </label>
{/snippet} {/snippet}
</FieldInline> </FieldInline>
+1 -1
View File
@@ -120,7 +120,7 @@
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input input-bordered flex w-full items-center gap-2">
<Icon icon={Letter} /> <Icon icon={Letter} />
<input bind:value={email} /> <input type="email" bind:value={email} />
</label> </label>
{/snippet} {/snippet}
</FieldInline> </FieldInline>
+22 -2
View File
@@ -25,6 +25,16 @@
const {url} = $props() const {url} = $props()
const authError = deriveRelayAuthError(url) const authError = deriveRelayAuthError(url)
let networkError = $state(false)
const isExplicitAuthError = $derived(
$authError &&
!(
$authError.toLowerCase().includes("failed") ||
$authError.toLowerCase().includes("timeout") ||
$authError.toLowerCase().includes("network")
),
)
const isGenericError = $derived(networkError || ($authError && !isExplicitAuthError))
const back = () => history.back() const back = () => history.back()
const copyInvite = () => clip(invite) const copyInvite = () => clip(invite)
@@ -70,8 +80,14 @@
]) ])
claim = getTagValue("claim", event?.tags || []) || "" claim = getTagValue("claim", event?.tags || []) || ""
} catch { } catch (err) {
claim = "" claim = ""
if (
(err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) ||
!navigator.onLine
) {
networkError = true
}
} finally { } finally {
loading = false loading = false
} }
@@ -92,7 +108,11 @@
<p class="center"> <p class="center">
<Spinner {loading}>Requesting an invite link...</Spinner> <Spinner {loading}>Requesting an invite link...</Spinner>
</p> </p>
{:else if $authError} {:else if isGenericError}
<p class="center text-center">
Unable to reach the relay. Please check your connection and try again.
</p>
{:else if isExplicitAuthError}
<p class="center">Oops! It looks like you're not a member of this relay.</p> <p class="center">Oops! It looks like you're not a member of this relay.</p>
{:else} {:else}
<div class="flex flex-col items-center gap-6"> <div class="flex flex-col items-center gap-6">
+1
View File
@@ -31,6 +31,7 @@
<svelte:document onmousemove={onMouseMove} /> <svelte:document onmousemove={onMouseMove} />
<Tippy <Tippy
class="flex"
bind:popover bind:popover
component={EmojiPicker} component={EmojiPicker}
props={{onClick}} props={{onClick}}
+11 -17
View File
@@ -9,22 +9,16 @@
const {...props}: Props = $props() const {...props}: Props = $props()
</script> </script>
<div class="flex flex-col gap-2 {props.class}"> <div class="grid grid-cols-1 gap-2 lg:gap-6 lg:grid-cols-3 {props.class}">
<div class="flex items-center justify-between w-full gap-2"> <label class="flex items-center gap-2 font-bold">
{#if props.label} {@render props.label?.()}
<label class="flex items-center gap-2 max-w-[80%] md:max-w-none"> </label>
{@render props.label()} <div class="col-span-2 flex items-center gap-2">
</label> {@render props.input?.()}
{/if}
<div class="flex items-center gap-2 justify-end shrink-0">
{#if props.input}
{@render props.input()}
{/if}
</div>
</div> </div>
{#if props.info} <p class="flex-end text-sm opacity-50 lg:col-span-3">
<p class="text-sm opacity-50"> {#if props.info}
{@render props.info()} {@render props.info?.()}
</p> {/if}
{/if} </p>
</div> </div>
+9 -16
View File
@@ -13,12 +13,7 @@
placeholder?: string placeholder?: string
} }
let { let {value = $bindable(), addLabel, placeholder = "Enter text..."}: Props = $props()
value = $bindable(),
addLabel,
placeholder = "Enter text...",
allowAdd = true,
}: Props & {allowAdd?: boolean} = $props()
let draggedIndex: number | null = $state(null) let draggedIndex: number | null = $state(null)
const onChange = (newValue: string[]) => { const onChange = (newValue: string[]) => {
@@ -77,14 +72,12 @@
</div> </div>
</div> </div>
{/each} {/each}
{#if allowAdd} <Button onclick={addItem} class="btn btn-link w-fit px-0">
<Button onclick={addItem} class="btn btn-link w-fit px-0"> <Icon icon={AddCircle} size={5} />
<Icon icon={AddCircle} size={5} /> {#if addLabel}
{#if addLabel} {@render addLabel?.()}
{@render addLabel?.()} {:else}
{:else} Add Item
Add Item {/if}
{/if} </Button>
</Button>
{/if}
</div> </div>
+24 -49
View File
@@ -5,7 +5,6 @@
import {Badge} from "@capawesome/capacitor-badge" import {Badge} from "@capawesome/capacitor-badge"
import Bell from "@assets/icons/bell.svg?dataurl" import Bell from "@assets/icons/bell.svg?dataurl"
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import FieldInline from "@lib/components/FieldInline.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
@@ -64,64 +63,40 @@
<!-- pass --> <!-- pass -->
{:then { isSupported }} {:then { isSupported }}
{#if isSupported} {#if isSupported}
<FieldInline> <div class="flex justify-between">
{#snippet label()} <p>Show badge for unread alerts</p>
<p>Show badge for unread alerts</p> <input type="checkbox" class="toggle toggle-primary" bind:checked={settings.badge} />
{/snippet} </div>
{#snippet input()}
<input type="checkbox" class="toggle toggle-primary" bind:checked={settings.badge} />
{/snippet}
</FieldInline>
{/if} {/if}
{/await} {/await}
{#if !Capacitor.isNativePlatform()} {#if !Capacitor.isNativePlatform()}
<FieldInline> <div class="flex justify-between">
{#snippet label()} <p>Play sound for new activity</p>
<p>Play sound for new activity</p> <input type="checkbox" class="toggle toggle-primary" bind:checked={settings.sound} />
{/snippet} </div>
{#snippet input()}
<input type="checkbox" class="toggle toggle-primary" bind:checked={settings.sound} />
{/snippet}
</FieldInline>
{/if} {/if}
<FieldInline> <div class="flex justify-between">
{#snippet label()} <p>Enable push notifications</p>
<p>Enable push notifications</p> <input type="checkbox" class="toggle toggle-primary" bind:checked={settings.push} />
{/snippet} </div>
{#snippet input()}
<input type="checkbox" class="toggle toggle-primary" bind:checked={settings.push} />
{/snippet}
</FieldInline>
</div> </div>
<div <div
class={cx("card2 bg-alt col-4 shadow-md", { class={cx("card2 bg-alt col-4 shadow-md", {
"pointer-events-none opacity-50": !settings.badge && !settings.sound && !settings.push, "pointer-events-none opacity-50": !settings.badge && !settings.sound && !settings.push,
})}> })}>
<strong class="text-lg">Alert Types</strong> <strong class="text-lg">Alert Types</strong>
<FieldInline> <div class="flex justify-between">
{#snippet label()} <p>Notify me about new activity</p>
<p>Notify me about new activity</p> <input type="checkbox" class="toggle toggle-primary" bind:checked={settings.spaces} />
{/snippet} </div>
{#snippet input()} <div class="flex justify-between">
<input type="checkbox" class="toggle toggle-primary" bind:checked={settings.spaces} /> <p>Always notify me when mentioned</p>
{/snippet} <input type="checkbox" class="toggle toggle-primary" checked={settings.mentions} />
</FieldInline> </div>
<FieldInline> <div class="flex justify-between">
{#snippet label()} <p>Notify me about new messages</p>
<p>Always notify me when mentioned</p> <input type="checkbox" class="toggle toggle-primary" bind:checked={settings.messages} />
{/snippet} </div>
{#snippet input()}
<input type="checkbox" class="toggle toggle-primary" checked={settings.mentions} />
{/snippet}
</FieldInline>
<FieldInline>
{#snippet label()}
<p>Notify me about new messages</p>
{/snippet}
{#snippet input()}
<input type="checkbox" class="toggle toggle-primary" bind:checked={settings.messages} />
{/snippet}
</FieldInline>
</div> </div>
<div <div
class="card2 bg-alt sticky -bottom-3 shadow-md flex flex-row items-center justify-between gap-4"> class="card2 bg-alt sticky -bottom-3 shadow-md flex flex-row items-center justify-between gap-4">
+9 -18
View File
@@ -11,7 +11,6 @@
import {Router} from "@welshman/router" import {Router} from "@welshman/router"
import {userMuteList, tagPubkey, publishThunk, userBlossomServerList} from "@welshman/app" import {userMuteList, tagPubkey, publishThunk, userBlossomServerList} from "@welshman/app"
import NotesMinimalistic from "@assets/icons/notes-minimalistic.svg?dataurl" import NotesMinimalistic from "@assets/icons/notes-minimalistic.svg?dataurl"
import AddCircle from "@assets/icons/add-circle.svg?dataurl"
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import Field from "@lib/components/Field.svelte" import Field from "@lib/components/Field.svelte"
import FieldInline from "@lib/components/FieldInline.svelte" import FieldInline from "@lib/components/FieldInline.svelte"
@@ -29,10 +28,6 @@
blossomServers = getTagValues("server", getListTags($userBlossomServerList)) blossomServers = getTagValues("server", getListTags($userBlossomServerList))
} }
const addServer = () => {
blossomServers = [...blossomServers, ""]
}
const onsubmit = preventDefault(async () => { const onsubmit = preventDefault(async () => {
await publishSettings($state.snapshot(settings)) await publishSettings($state.snapshot(settings))
@@ -109,7 +104,7 @@
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<input <input
class="range range-primary w-full" class="range range-primary"
type="range" type="range"
min="0.8" min="0.8"
max="1.3" max="1.3"
@@ -120,13 +115,13 @@
</div> </div>
<div class="card2 bg-alt col-4 shadow-md"> <div class="card2 bg-alt col-4 shadow-md">
<strong class="text-lg">Editor Settings</strong> <strong class="text-lg">Editor Settings</strong>
<Field> <FieldInline>
{#snippet label()} {#snippet label()}
<p>Send Delay</p> <p>Send Delay</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<input <input
class="range range-primary w-full" class="range range-primary"
type="range" type="range"
min="0" min="0"
max="10000" max="10000"
@@ -139,21 +134,17 @@
{settings.send_delay === 1000 ? "second" : "seconds"}. {settings.send_delay === 1000 ? "second" : "seconds"}.
</p> </p>
{/snippet} {/snippet}
</Field> </FieldInline>
<Field> <Field>
{#snippet label()} {#snippet label()}
<p>Media Server</p> <p>Media Server</p>
{/snippet} {/snippet}
{#snippet secondary()}
<Button
class="btn btn-link w-fit px-0 decoration-solid underline text-[#7161ff] h-auto min-h-0 flex items-center gap-[5px]"
onclick={addServer}>
<Icon icon={AddCircle} size={4} />
Add Server
</Button>
{/snippet}
{#snippet input()} {#snippet input()}
<InputList allowAdd={false} bind:value={blossomServers} /> <InputList bind:value={blossomServers}>
{#snippet addLabel()}
Add Server
{/snippet}
</InputList>
{/snippet} {/snippet}
{#snippet info()} {#snippet info()}
<p>Choose a media server type and url for files you upload to {PLATFORM_NAME}.</p> <p>Choose a media server type and url for files you upload to {PLATFORM_NAME}.</p>
+25 -41
View File
@@ -1,7 +1,6 @@
<script lang="ts"> <script lang="ts">
import ShieldMinimalistic from "@assets/icons/shield-minimalistic.svg?dataurl" import ShieldMinimalistic from "@assets/icons/shield-minimalistic.svg?dataurl"
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import FieldInline from "@lib/components/FieldInline.svelte"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
@@ -31,46 +30,31 @@
<Icon icon={ShieldMinimalistic} /> <Icon icon={ShieldMinimalistic} />
Privacy Settings Privacy Settings
</strong> </strong>
<FieldInline> <div class="grid grid-cols-2 gap-2">
{#snippet label()} <p>Authenticate with unknown relays?</p>
<p>Authenticate with unknown relays?</p> <input
{/snippet} type="checkbox"
{#snippet input()} class="toggle toggle-primary"
<input onchange={onAuthModeChange}
type="checkbox" checked={settings.auth_mode === RelayAuthMode.Aggressive} />
class="toggle toggle-primary" <p class="col-span-2 text-sm opacity-70">
onchange={onAuthModeChange} Controls whether {PLATFORM_NAME} will identify you to relays not in your lists.
checked={settings.auth_mode === RelayAuthMode.Aggressive} /> </p>
{/snippet} </div>
{#snippet info()} <div class="grid grid-cols-2 gap-2">
<p>Controls whether {PLATFORM_NAME} will identify you to relays not in your lists.</p> <p>Report errors?</p>
{/snippet} <input type="checkbox" class="toggle toggle-primary" bind:checked={settings.report_errors} />
</FieldInline> <p class="col-span-2 text-sm opacity-70">
<FieldInline> Allow {PLATFORM_NAME} to send error reports to help improve the app.
{#snippet label()} </p>
<p>Report errors?</p> </div>
{/snippet} <div class="grid grid-cols-2 gap-2">
{#snippet input()} <p>Report usage?</p>
<input <input type="checkbox" class="toggle toggle-primary" bind:checked={settings.report_usage} />
type="checkbox" <p class="col-span-2 text-sm opacity-70">
class="toggle toggle-primary" Allow {PLATFORM_NAME} to collect anonymous usage data.
bind:checked={settings.report_errors} /> </p>
{/snippet} </div>
{#snippet info()}
<p>Allow {PLATFORM_NAME} to send error reports to help improve the app.</p>
{/snippet}
</FieldInline>
<FieldInline>
{#snippet label()}
<p>Report usage?</p>
{/snippet}
{#snippet input()}
<input type="checkbox" class="toggle toggle-primary" bind:checked={settings.report_usage} />
{/snippet}
{#snippet info()}
<p>Allow {PLATFORM_NAME} to collect anonymous usage data.</p>
{/snippet}
</FieldInline>
</div> </div>
<div <div
class="card2 bg-alt sticky -bottom-3 shadow-md flex flex-row items-center justify-between gap-4"> class="card2 bg-alt sticky -bottom-3 shadow-md flex flex-row items-center justify-between gap-4">