mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-19 11:43:35 +00:00
Fix a few bugs
This commit is contained in:
parent
5b548cccab
commit
879ece60a9
1
.env
1
.env
@ -1,4 +1,3 @@
|
||||
VITE_THEME_DARK=transparent:transparent,black:#0f0f0e,white:#FFFFFF,accent:#EB5E28,accent-light:#FB652C,gray-1:#FFFFFF,gray-2:#FAF6F1,gray-3:#F2EBE1,gray-4:#E9E0D3,gray-5:#B3AA98,gray-6:#565249,gray-7:#393530,gray-8:#252422,danger:#ff0000,warning:#ebd112,success:#37ab51,input:#FAF6F1,input-hover:#F2EBE1
|
||||
VITE_THEME_LIGHT=transparent:transparent,black:#0f0f0e,white:#FFFFFF,accent:#EB5E28,accent-light:#FB652C,gray-8:#FFFFFF,gray-7:#FAF6F1,gray-6:#F2EBE1,gray-5:#E9E0D3,gray-4:#B3AA98,gray-3:#565249,gray-2:#393530,gray-1:#252422,danger:#ff0000,warning:#ebd112,success:#37ab51,input:#FAF6F1,input-hover:#F2EBE1
|
||||
VITE_DUFFLEPUD_URL=https://dufflepud.onrender.com
|
||||
VITE_SHOW_DEBUG_ROUTE=false
|
||||
|
11
ROADMAP.md
11
ROADMAP.md
@ -1,14 +1,7 @@
|
||||
# Current
|
||||
|
||||
- [ ] Topics
|
||||
- [x] Improve topic suggestions and rendering
|
||||
- [x] Add topic search, keep cache of topics
|
||||
- [x] Ability to create custom feeds
|
||||
- [x] Bookmark icon opens "create feed" dialog with form pre-filled
|
||||
- [ ] Replace some modals instead of pushing
|
||||
- [ ] Test anonymous with lists
|
||||
- [ ] Test hardcoded relay, currently you get asked to pick a relay if not logged in
|
||||
- [ ] Claim relays bounty
|
||||
- [ ] Claim relays bounty
|
||||
- [ ] Add real search, it's a big hurdle for first-timers/anons
|
||||
- [ ] Fix notifications
|
||||
- [ ] Queue context requests to avoid having too many concurrent subscriptions
|
||||
- [ ] Advanced search
|
||||
|
@ -41,7 +41,7 @@ const profile = synced("agent/user/profile", {
|
||||
})
|
||||
|
||||
const settings = derived(profile, prop("settings"))
|
||||
const petnames = derived(profile, prop("petnames"))
|
||||
const petnames = derived(profile, prop("petnames")) as Readable<Array<Array<string>>>
|
||||
const relays = derived(profile, prop("relays")) as Readable<Array<Relay>>
|
||||
const mutes = derived(profile, prop("mutes")) as Readable<Array<[string, string]>>
|
||||
const lists = derived(profile, prop("lists")) as Readable<Array<MyEvent>>
|
||||
|
@ -8,8 +8,9 @@
|
||||
import PersonSearch from "src/app/shared/PersonSearch.svelte"
|
||||
import {getPersonWithFallback} from "src/agent/db"
|
||||
import user from "src/agent/user"
|
||||
import pool from "src/agent/pool"
|
||||
|
||||
export let enforceRelays = true
|
||||
export let enforceRelays = pool.forceUrls.length === 0
|
||||
export let enforcePeople = true
|
||||
|
||||
const {petnamePubkeys, relays} = user
|
||||
@ -29,8 +30,9 @@
|
||||
{#if $relays.length > 0}
|
||||
<h1 class="text-2xl">Your Relays</h1>
|
||||
{/if}
|
||||
<div class="flex flex-col gap-2">
|
||||
{#each $relays as relay (relay.url)}
|
||||
<RelayCard showControls {relay} />
|
||||
<RelayCard showActions {relay} />
|
||||
{:else}
|
||||
<div class="flex flex-col items-center gap-4 my-8">
|
||||
<div class="text-xl flex gap-2 items-center">
|
||||
@ -40,7 +42,12 @@
|
||||
<div>Search below to find one to join.</div>
|
||||
</div>
|
||||
{/each}
|
||||
<RelaySearch />
|
||||
</div>
|
||||
<RelaySearch>
|
||||
<div slot="item" let:relay>
|
||||
<RelayCard showActions {relay} />
|
||||
</div>
|
||||
</RelaySearch>
|
||||
</Content>
|
||||
</Modal>
|
||||
{:else if needsRelays()}
|
||||
@ -72,7 +79,7 @@
|
||||
<div>Search below to find some interesting people.</div>
|
||||
</div>
|
||||
{/each}
|
||||
<PersonSearch />
|
||||
<PersonSearch hideFollows />
|
||||
</Content>
|
||||
</Modal>
|
||||
{:else if needsPeople()}
|
||||
@ -83,7 +90,7 @@
|
||||
You aren't yet following anyone.
|
||||
</div>
|
||||
<div>
|
||||
Click <Anchor href="/search/people">here</Anchor> to find some interesting people.
|
||||
Click <Anchor href="/search">here</Anchor> to find some interesting people.
|
||||
</div>
|
||||
</div>
|
||||
</Content>
|
||||
|
@ -121,13 +121,6 @@
|
||||
</a>
|
||||
</li>
|
||||
{/if}
|
||||
{#if import.meta.env.VITE_SHOW_DEBUG_ROUTE === "true"}
|
||||
<li class="cursor-pointer">
|
||||
<a class="block px-4 py-2 transition-all hover:bg-accent hover:text-white" href="/debug">
|
||||
<i class="fa fa-bug mr-2" /> Debug
|
||||
</a>
|
||||
</li>
|
||||
{/if}
|
||||
{#if $installPrompt}
|
||||
<li
|
||||
class="cursor-pointer px-4 py-2 transition-all hover:bg-accent hover:text-white"
|
||||
|
@ -23,11 +23,13 @@
|
||||
$: {
|
||||
actions = []
|
||||
|
||||
if ($canPublish) {
|
||||
actions.push({
|
||||
onClick: () => addToList("p", person.pubkey),
|
||||
label: "Add to list",
|
||||
icon: "scroll",
|
||||
})
|
||||
}
|
||||
|
||||
actions.push({onClick: share, label: "Share", icon: "share-nodes"})
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
class={cx(
|
||||
$$props.class,
|
||||
`relative overflow-hidden w-${size} h-${size} inline-block shrink-0 rounded-full border border-solid
|
||||
border-white bg-cover bg-center`
|
||||
border-gray-1 bg-cover bg-center`
|
||||
)}
|
||||
style="--logo-color: {primary}; --logo-bg-color: {secondary}; background-color: var(--logo-bg-color);">
|
||||
<LogoSvg
|
||||
|
@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import {last, nth} from "ramda"
|
||||
import {fly} from "svelte/transition"
|
||||
import {noEvent} from "src/util/html"
|
||||
import {displayPerson} from "src/util/nostr"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import PersonCircle from "src/app/shared/PersonCircle.svelte"
|
||||
@ -10,9 +9,10 @@
|
||||
import user from "src/agent/user"
|
||||
import {routes} from "src/app/state"
|
||||
|
||||
export let person
|
||||
const {petnames} = user
|
||||
|
||||
export let hasPetname = pubkey => user.getPetnames().map(nth(1)).includes(pubkey)
|
||||
export let person
|
||||
export let hasPetname = null
|
||||
|
||||
export let removePetname = ({pubkey}) => user.removePetname(pubkey)
|
||||
|
||||
@ -21,10 +21,15 @@
|
||||
|
||||
user.addPetname(pubkey, url, displayPerson(person))
|
||||
}
|
||||
|
||||
$: isFollowing = hasPetname
|
||||
? hasPetname(person.pubkey)
|
||||
: $petnames.map(nth(1)).includes(person.pubkey)
|
||||
</script>
|
||||
|
||||
<a
|
||||
in:fly={{y: 20}}
|
||||
<div in:fly={{y: 20}}>
|
||||
<Anchor
|
||||
type="unstyled"
|
||||
href={routes.person(person.pubkey)}
|
||||
class="flex gap-4 overflow-hidden border-l-2 border-solid border-gray-7 py-3 px-4
|
||||
transition-all hover:border-accent hover:bg-gray-8">
|
||||
@ -40,16 +45,17 @@
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if hasPetname(person.pubkey)}
|
||||
<Anchor type="button-accent" on:click={noEvent(() => removePetname(person))}>
|
||||
{#if isFollowing}
|
||||
<Anchor type="button-accent" stopPropagation on:click={() => removePetname(person)}>
|
||||
Following
|
||||
</Anchor>
|
||||
{:else}
|
||||
<Anchor type="button" on:click={noEvent(() => addPetname(person))}>Follow</Anchor>
|
||||
<Anchor type="button" stopPropagation on:click={() => addPetname(person)}>Follow</Anchor>
|
||||
{/if}
|
||||
</div>
|
||||
<p class="overflow-hidden text-ellipsis">
|
||||
<PersonAbout truncate {person} />
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
</Anchor>
|
||||
</div>
|
||||
|
@ -1,4 +1,5 @@
|
||||
<script>
|
||||
import {nth} from "ramda"
|
||||
import Input from "src/partials/Input.svelte"
|
||||
import Spinner from "src/partials/Spinner.svelte"
|
||||
import PersonInfo from "src/app/shared/PersonInfo.svelte"
|
||||
@ -7,9 +8,25 @@
|
||||
import network from "src/agent/network"
|
||||
import user from "src/agent/user"
|
||||
|
||||
export let hideFollows = false
|
||||
|
||||
let q
|
||||
|
||||
$: results = $searchPeople(q).slice(0, 50)
|
||||
$: results = $searchPeople(q)
|
||||
.filter(person => {
|
||||
if (person.pubkey === user.getPubkey()) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (hideFollows && $petnames.map(nth(1)).includes(person.pubkey)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
.slice(0, 50)
|
||||
|
||||
const {petnames} = user
|
||||
|
||||
// Prime our database, in case we don't have any people stored yet
|
||||
network.load({
|
||||
@ -22,9 +39,7 @@
|
||||
<i slot="before" class="fa-solid fa-search" />
|
||||
</Input>
|
||||
{#each results as person (person.pubkey)}
|
||||
{#if person.pubkey !== user.getPubkey()}
|
||||
<PersonInfo {person} />
|
||||
{/if}
|
||||
{:else}
|
||||
<Spinner />
|
||||
{/each}
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
relay = getRelayWithFallback(relay.url)
|
||||
|
||||
const {relays: userRelays} = user
|
||||
const {relays: userRelays, canPublish} = user
|
||||
|
||||
let actions = []
|
||||
|
||||
@ -31,11 +31,13 @@
|
||||
})
|
||||
}
|
||||
|
||||
if ($canPublish) {
|
||||
actions.push({
|
||||
onClick: () => addToList("r", relay.url),
|
||||
label: "Add to list",
|
||||
icon: "scroll",
|
||||
})
|
||||
}
|
||||
|
||||
if (relay.contact) {
|
||||
actions.push({
|
||||
|
@ -28,14 +28,14 @@
|
||||
export let removeRelay = r => user.removeRelay(r.url)
|
||||
|
||||
export let addRelay = r => {
|
||||
user.addRelay(r.url).then(() => {
|
||||
user.addRelay(r.url)
|
||||
|
||||
const pubkey = user.getPubkey()
|
||||
const profile = user.getProfile()
|
||||
|
||||
if (pubkey && !profile?.kind0) {
|
||||
loadAppData(pubkey)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
@ -79,7 +79,7 @@
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
{#if $canPublish && showActions}
|
||||
{#if showActions}
|
||||
<slot name="actions">
|
||||
{#if hasRelay(relay) && $relays.length > 1}
|
||||
<button class="flex items-center gap-3 text-gray-1" on:click={() => removeRelay(relay)}>
|
||||
|
@ -1,18 +1,25 @@
|
||||
<script lang="ts">
|
||||
import OverflowMenu from "src/partials/OverflowMenu.svelte"
|
||||
import {addToList} from "src/app/state"
|
||||
import user from "src/agent/user"
|
||||
|
||||
export let topic
|
||||
|
||||
const {canPublish} = user
|
||||
|
||||
let actions = []
|
||||
|
||||
$: {
|
||||
actions = []
|
||||
|
||||
if ($canPublish) {
|
||||
actions.push({
|
||||
onClick: () => addToList("t", topic),
|
||||
label: "Add to list",
|
||||
icon: "scroll",
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<OverflowMenu {actions} />
|
||||
|
@ -1,8 +1,9 @@
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import {prop, uniq, indexBy, objOf, filter as _filter} from "ramda"
|
||||
import {shuffle, synced} from "src/util/misc"
|
||||
import {Tags} from "src/util/nostr"
|
||||
import {modal} from "src/partials/state"
|
||||
import {modal, theme} from "src/partials/state"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import Content from "src/partials/Content.svelte"
|
||||
import Tabs from "src/partials/Tabs.svelte"
|
||||
@ -12,7 +13,7 @@
|
||||
import {sampleRelays, getAllPubkeyWriteRelays, getUserReadRelays} from "src/agent/relays"
|
||||
import user from "src/agent/user"
|
||||
|
||||
const {lists} = user
|
||||
const {lists, canPublish} = user
|
||||
const activeTab = synced("views/Feeds/activeTab", "Follows")
|
||||
|
||||
let relays, filter, tabs
|
||||
@ -79,17 +80,21 @@
|
||||
{/if}
|
||||
<div>
|
||||
<Tabs {tabs} activeTab={$activeTab} {setActiveTab}>
|
||||
{#if $canPublish}
|
||||
{#if $lists.length > 1}
|
||||
<Popover placement="bottom" opts={{hideOnClick: true}} theme="transparent">
|
||||
<i slot="trigger" class="fa fa-ellipsis-v cursor-pointer p-2" />
|
||||
<div
|
||||
slot="tooltip"
|
||||
class="flex flex-col items-start rounded border border-solid border-gray-8 bg-black">
|
||||
class="flex flex-col items-start overflow-hidden rounded border border-solid border-gray-8 bg-black">
|
||||
{#each $lists as e (e.id)}
|
||||
{@const meta = Tags.from(e).asMeta()}
|
||||
{#if meta.d !== $activeTab}
|
||||
<button
|
||||
class="w-full py-2 px-3 text-left hover:bg-gray-7"
|
||||
class={cx("w-full py-2 px-3 text-left transition-colors", {
|
||||
"hover:bg-gray-7": $theme === "dark",
|
||||
"hover:bg-gray-1": $theme === "light",
|
||||
})}
|
||||
on:click={() => {
|
||||
$activeTab = meta.d
|
||||
}}>
|
||||
@ -98,7 +103,12 @@
|
||||
</button>
|
||||
{/if}
|
||||
{/each}
|
||||
<button on:click={showLists} class="w-full py-2 px-3 text-left hover:bg-gray-7">
|
||||
<button
|
||||
on:click={showLists}
|
||||
class={cx("w-full py-2 px-3 text-left transition-colors", {
|
||||
"hover:bg-gray-7": $theme === "dark",
|
||||
"hover:bg-gray-1": $theme === "light",
|
||||
})}>
|
||||
<i class="fa fa-cog fa-sm mr-1" /> Customize
|
||||
</button>
|
||||
</div>
|
||||
@ -106,6 +116,7 @@
|
||||
{:else}
|
||||
<i class="fa fa-ellipsis-v cursor-pointer p-1" on:click={showLists} />
|
||||
{/if}
|
||||
{/if}
|
||||
</Tabs>
|
||||
{#key $activeTab}
|
||||
<Feed {relays} {filter} />
|
||||
|
@ -3,5 +3,5 @@
|
||||
import {navigate} from "svelte-routing"
|
||||
import user from "src/agent/user"
|
||||
|
||||
onMount(() => navigate(user.getProfile() ? "/notes" : "/login"))
|
||||
onMount(() => navigate(user.getPubkey() ? "/notes" : "/login"))
|
||||
</script>
|
||||
|
@ -1,5 +1,7 @@
|
||||
<script>
|
||||
import cx from "classnames"
|
||||
import {omit} from "ramda"
|
||||
import {navigate} from "svelte-routing"
|
||||
import {switcher} from "hurdak/lib/hurdak"
|
||||
import {createEventDispatcher} from "svelte"
|
||||
|
||||
@ -35,10 +37,19 @@
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
if (href && !external) {
|
||||
navigate(href)
|
||||
}
|
||||
|
||||
dispatch("click", e)
|
||||
}
|
||||
</script>
|
||||
|
||||
<a on:click={onClick} {...$$props} {href} class={className} target={external ? "_blank" : null}>
|
||||
<a
|
||||
on:click={onClick}
|
||||
{...omit(["href"], $$props)}
|
||||
href={external ? $$props.href : null}
|
||||
class={className}
|
||||
target={external ? "_blank" : null}>
|
||||
<slot />
|
||||
</a>
|
||||
|
@ -9,7 +9,7 @@
|
||||
class={cx(
|
||||
$$props.class,
|
||||
`overflow-hidden w-${size} h-${size} inline-block shrink-0 rounded-full border border-solid
|
||||
border-white bg-cover bg-center`
|
||||
border-gray-1 bg-cover bg-center`
|
||||
)}
|
||||
style="background-image: url({src}); {$$props.style || ''}">
|
||||
<slot />
|
||||
|
@ -24,7 +24,7 @@
|
||||
}} />
|
||||
|
||||
<div class="modal fixed inset-0 z-30" bind:this={root} transition:fade>
|
||||
<div class="fixed inset-0 cursor-pointer bg-black opacity-75" on:click={onEscape} />
|
||||
<div class="fixed inset-0 cursor-pointer bg-black opacity-50" on:click={onEscape} />
|
||||
<div
|
||||
class="modal-content h-full overflow-auto"
|
||||
bind:this={content}
|
||||
|
@ -26,11 +26,10 @@
|
||||
class="relative flex flex-col gap-2"
|
||||
on:click={() => instance.hide()}>
|
||||
<div
|
||||
class="absolute top-0 right-0 bottom-0 w-32 rounded-full bg-gray-8"
|
||||
class="absolute top-0 right-0 bottom-0 w-32 rounded-3xl bg-gray-8"
|
||||
style="filter: blur(15px) opacity(0.75)" />
|
||||
|
||||
{#each actions as { label, icon, onClick }}
|
||||
<div class="relative z-10 cursor-pointer" on:click={onClick}>
|
||||
<div class="relative z-10 cursor-pointer text-gray-3" on:click={onClick}>
|
||||
<span class="absolute right-0 mr-12 mt-2 whitespace-nowrap">{label}</span>
|
||||
<Anchor type="button-circle"><i class={`fa fa-${icon}`} /></Anchor>
|
||||
</div>
|
||||
|
@ -48,7 +48,7 @@ export const openModals = writable(0)
|
||||
|
||||
export const modal = {
|
||||
stack: new WritableList([]) as WritableList<any>,
|
||||
sync: ($stack, opts) => {
|
||||
sync: ($stack, opts = null) => {
|
||||
const hash = $stack.length > 0 ? `#m=${$stack.length}` : ""
|
||||
|
||||
navigate(window.location.pathname + hash, opts)
|
||||
|
@ -92,14 +92,6 @@ export const killEvent = e => {
|
||||
e.stopImmediatePropagation()
|
||||
}
|
||||
|
||||
export const noEvent = f => e => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
e.stopImmediatePropagation()
|
||||
|
||||
f()
|
||||
}
|
||||
|
||||
export const isMobile = localStorage.mobile || window.navigator.maxTouchPoints > 1
|
||||
|
||||
export const parseHex = hex => {
|
||||
|
Loading…
Reference in New Issue
Block a user