Give a space with no icon a colored tile with its initials (#428)
This commit is contained in:
parent
3bd821efc1
commit
7b145c525d
7 changed files with 60 additions and 30 deletions
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import {hash, formatTimestampAsTime} from "@welshman/lib"
|
||||
import {formatTimestampAsTime} from "@welshman/lib"
|
||||
import type {Maybe} from "@welshman/lib"
|
||||
import type {TrustedEvent, EventContent} from "@welshman/util"
|
||||
import {Thunks} from "@welshman/app"
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
import ChatMessageMenu from "@app/components/ChatMessageMenu.svelte"
|
||||
import ChatMessageMenuMobile from "@app/components/ChatMessageMenuMobile.svelte"
|
||||
import {app, profiles, user} from "@app/core"
|
||||
import {colors} from "@app/theme"
|
||||
import {colorFor} from "@app/theme"
|
||||
import {pushModal} from "@app/modal"
|
||||
|
||||
interface Props {
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
const profileDisplay = $profiles.display(event.pubkey).$
|
||||
const thunks = $app.use(Thunks).history
|
||||
const thunk = $app.use(Thunks).merge($thunks.filter(t => t.event.id === event.id))
|
||||
const [_, colorValue] = colors[hash(event.pubkey) % colors.length]
|
||||
const colorValue = colorFor(event.pubkey)
|
||||
|
||||
const reply = () => replyTo(event)
|
||||
const edit = canEdit?.(event) ? () => onEdit?.(event) : undefined
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import Server from "@assets/icons/server.svg?dataurl"
|
||||
import ImageIcon from "@lib/components/ImageIcon.svelte"
|
||||
import {relays} from "@app/core"
|
||||
import {relayIconColor, relayIconInitials} from "@app/relays"
|
||||
|
||||
type Props = {
|
||||
url: string
|
||||
|
|
@ -12,10 +12,20 @@
|
|||
const {url, size = 7, ...props}: Props = $props()
|
||||
|
||||
const relay = $relays.one(url)
|
||||
|
||||
const rem = $derived(size * 0.25)
|
||||
|
||||
const fallbackStyle = $derived(
|
||||
`width: ${rem}rem; height: ${rem}rem; min-width: ${rem}rem; min-height: ${rem}rem; font-size: ${rem * 0.4}rem; background-color: ${relayIconColor(url)}; color: white`,
|
||||
)
|
||||
</script>
|
||||
|
||||
{#if $relay?.icon}
|
||||
<ImageIcon {size} alt="" src={$relay?.icon} class="rounded-full {props.class}" />
|
||||
{:else}
|
||||
<ImageIcon size={size - 2} alt="" src={Server} class={props.class} />
|
||||
<div
|
||||
class="flex select-none items-center justify-center rounded-full font-bold {props.class}"
|
||||
style={fallbackStyle}>
|
||||
{relayIconInitials(url)}
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
<div class="relative">
|
||||
<div
|
||||
class="flex justify-center items-center h-12 w-12 min-w-12 rounded-full border-2 border-solid bg-surface-more border-line">
|
||||
<RelayIcon {url} size={10} class="rounded-full" />
|
||||
<RelayIcon {url} size={10} />
|
||||
</div>
|
||||
</div>
|
||||
{#if !hideFavorites && $userSpaceUrls.includes(url)}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
import cx from "classnames"
|
||||
import {readable} from "svelte/store"
|
||||
import {
|
||||
hash,
|
||||
gte,
|
||||
now,
|
||||
uniq,
|
||||
|
|
@ -40,7 +39,7 @@
|
|||
import RoomItemContent from "@app/components/RoomItemContent.svelte"
|
||||
import {profiles, thunks, user} from "@app/core"
|
||||
import {noThunks, thunksByEventId} from "@app/thunks"
|
||||
import {colors} from "@app/theme"
|
||||
import {colorFor} from "@app/theme"
|
||||
import {ENABLE_ZAPS} from "@app/env"
|
||||
import type {FeedContext} from "@app/feeds"
|
||||
import {deriveEvent, deriveEventsForUrl} from "@app/repository"
|
||||
|
|
@ -71,7 +70,7 @@
|
|||
const today = formatTimestampAsDate(now())
|
||||
const profileDisplay = $profiles.display(event.pubkey, [url]).$
|
||||
const thunk = $derived($thunks.merge($thunksByEventId.get(event.id) ?? noThunks))
|
||||
const [_, colorValue] = colors[hash(event.pubkey) % colors.length]
|
||||
const colorValue = colorFor(event.pubkey)
|
||||
|
||||
const qTag = matchTag(tagSpec("q"), event.tags)
|
||||
const isQuoteOnly = Boolean(
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import {throttled} from "@welshman/store"
|
|||
import {checkRelayHasLivekit} from "$lib/livekit"
|
||||
import {app} from "@app/core"
|
||||
import {relaysMostlyRestricted} from "@app/policies"
|
||||
import {colorFor} from "@app/theme"
|
||||
|
||||
export const encodeRelay = (url: string) =>
|
||||
encodeURIComponent(
|
||||
|
|
@ -16,6 +17,23 @@ export const encodeRelay = (url: string) =>
|
|||
|
||||
export const decodeRelay = (url: string) => normalizeRelayUrl(decodeURIComponent(url))
|
||||
|
||||
const relayIconHost = (url: string) =>
|
||||
normalizeRelayUrl(url)
|
||||
.replace(/^wss?:\/\//, "")
|
||||
.replace(/[:/].*$/, "")
|
||||
|
||||
// Darkened so white initials clear 4.5:1 on every color in the palette.
|
||||
export const relayIconColor = (url: string) =>
|
||||
`color-mix(in oklab, ${colorFor(relayIconHost(url))} 80%, black)`
|
||||
|
||||
export const relayIconInitials = (url: string) => {
|
||||
const parts = relayIconHost(url).split(".")
|
||||
const hasSubdomain = parts.length > 2
|
||||
const [first = "", second = ""] = parts
|
||||
|
||||
return (hasSubdomain ? first.slice(0, 1) + second.slice(0, 1) : first.slice(0, 2)).toUpperCase()
|
||||
}
|
||||
|
||||
export const deriveSocket = (url: string) => {
|
||||
const socket = app.get().pool.get(url)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,31 +1,34 @@
|
|||
import twColors from "tailwindcss/colors"
|
||||
import {derived, readable} from "svelte/store"
|
||||
import {hash} from "@welshman/lib"
|
||||
import {synced} from "@welshman/store"
|
||||
import {FL_THEME} from "@app/env"
|
||||
import {kv} from "@app/storage"
|
||||
|
||||
export const colors = [
|
||||
["amber", twColors.amber[600]],
|
||||
["blue", twColors.blue[600]],
|
||||
["cyan", twColors.cyan[600]],
|
||||
["emerald", twColors.emerald[600]],
|
||||
["fuchsia", twColors.fuchsia[600]],
|
||||
["green", twColors.green[600]],
|
||||
["indigo", twColors.indigo[600]],
|
||||
["sky", twColors.sky[600]],
|
||||
["lime", twColors.lime[600]],
|
||||
["orange", twColors.orange[600]],
|
||||
["pink", twColors.pink[600]],
|
||||
["purple", twColors.purple[600]],
|
||||
["red", twColors.red[600]],
|
||||
["rose", twColors.rose[600]],
|
||||
["sky", twColors.sky[600]],
|
||||
["teal", twColors.teal[600]],
|
||||
["violet", twColors.violet[600]],
|
||||
["yellow", twColors.yellow[600]],
|
||||
["zinc", twColors.zinc[600]],
|
||||
const colors = [
|
||||
twColors.amber[600],
|
||||
twColors.blue[600],
|
||||
twColors.cyan[600],
|
||||
twColors.emerald[600],
|
||||
twColors.fuchsia[600],
|
||||
twColors.green[600],
|
||||
twColors.indigo[600],
|
||||
twColors.sky[600],
|
||||
twColors.lime[600],
|
||||
twColors.orange[600],
|
||||
twColors.pink[600],
|
||||
twColors.purple[600],
|
||||
twColors.red[600],
|
||||
twColors.rose[600],
|
||||
twColors.sky[600],
|
||||
twColors.teal[600],
|
||||
twColors.violet[600],
|
||||
twColors.yellow[600],
|
||||
twColors.zinc[600],
|
||||
]
|
||||
|
||||
export const colorFor = (value: string) => colors[hash(value) % colors.length]
|
||||
|
||||
// Every theme with token values in lib/components/theme.css
|
||||
export const flThemes = ["clay", "flat", "navy"]
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
<div class="card flex flex-col gap-4">
|
||||
<div class="relative flex gap-4">
|
||||
<div class="relative">
|
||||
<RelayIcon {url} size={14} class="rounded-full" />
|
||||
<RelayIcon {url} size={14} />
|
||||
</div>
|
||||
<div class="flex min-w-0 flex-col">
|
||||
<h1 class="truncate min-w-0 whitespace-nowrap">
|
||||
|
|
|
|||
Loading…
Reference in a new issue