Change case on engine components

This commit is contained in:
Jonathan Staab 2023-07-21 15:44:23 -07:00
parent 4dd45cf45e
commit 47ff35bd42
66 changed files with 321 additions and 368 deletions

View File

@ -1,7 +1,9 @@
# Current
- [ ] Refactor
- [ ] Get rid of User.getPubkey
- [ ] Move pubkey loader to utils
- [ ] Rename content to nipxx
- [ ] Have meta intercept subscribe/publish rather than listen to specific events
- [ ] Speed up note detail
- [ ] Fix feed control state

View File

@ -9,9 +9,9 @@
"preview": "vite preview",
"check:es": "eslint src/*/** --quiet",
"check:ts": "svelte-check --tsconfig ./tsconfig.json --threshold error",
"check:fmt": "prettier --check $(git diff head --name-only --diff-filter d | grep -E 'js|ts|svelte$' | xargs)",
"check:fmt": "prettier --check $(git diff head --name-only --diff-filter d | grep -E '(js|ts|svelte)$' | xargs)",
"check": "run-p check:*",
"format": "prettier --write $(git diff head --name-only --diff-filter d | grep -E 'js|ts|svelte$' | xargs)",
"format": "prettier --write $(git diff head --name-only --diff-filter d | grep -E '(js|ts|svelte)$' | xargs)",
"watch": "find src -type f | entr -r"
},
"devDependencies": {

View File

@ -11,7 +11,8 @@
import {Storage, seconds, Fetch, shuffle, tryFunc} from "hurdak"
import {tryFetch, hexToBech32, bech32ToHex, now} from "src/util/misc"
import {userKinds} from "src/util/nostr"
import engine from "src/app/engine"
import {default as engine} from "src/app/engine"
import {Keys, Nip65, PubkeyLoader, User, Env, Network, Builder, Outbox} from "src/app/engine"
import {listenForNotifications} from "src/app/state"
import {theme, getThemeVariables, appName, modal} from "src/partials/state"
import {logUsage} from "src/app/state"
@ -24,25 +25,25 @@
// Migration from 0.2.34
if (Object.hasOwn(localStorage, "agent/keys/pubkey")) {
engine.Keys.setKeyState({
Keys.setKeyState({
method: Storage.getJson("agent/keys/method"),
pubkey: Storage.getJson("agent/keys/pubkey"),
privkey: Storage.getJson("agent/keys/privkey"),
bunkerKey: Storage.getJson("agent/keys/bunkerKey"),
})
engine.Keys.pubkey.set(Storage.getJson("agent/keys/pubkey"))
Keys.pubkey.set(Storage.getJson("agent/keys/pubkey"))
const {settings} = JSON.parse(localStorage.getItem("agent/user/profile"))
engine.User.setSettings({
User.setSettings({
last_updated: settings.lastUpdated || 0,
relay_limit: settings.relayLimit || 10,
default_zap: settings.defaultZap || 21,
show_media: settings.showMedia || true,
report_analytics: settings.reportAnalytics || true,
dufflepud_url: settings.dufflepudUrl || engine.Env.DUFFLEPUD_URL,
multiplextr_url: settings.multiplextrUrl || engine.Env.MULTIPLEXTR_URL,
dufflepud_url: settings.dufflepudUrl || Env.DUFFLEPUD_URL,
multiplextr_url: settings.multiplextrUrl || Env.MULTIPLEXTR_URL,
})
localStorage.removeItem("agent/keys/method")
@ -53,7 +54,7 @@
const TypedRouter = Router as ComponentType<SvelteComponentTyped>
Object.assign(window, {engine, bech32ToHex, hexToBech32})
Object.assign(window, {...engine, bech32ToHex, hexToBech32})
export let pathname = location.pathname
export let hash = location.hash
@ -80,12 +81,12 @@
const seenChallenges = new Set()
// When we get an AUTH challenge from our pool, attempt to authenticate
engine.Network.authHandler = async (url, challenge) => {
if (engine.Keys.canSign.get() && !seenChallenges.has(challenge)) {
Network.authHandler = async (url, challenge) => {
if (Keys.canSign.get() && !seenChallenges.has(challenge)) {
seenChallenges.add(challenge)
const rawEvent = engine.Builder.authenticate(url, challenge)
const [event] = await engine.Outbox.publish(rawEvent, [url], null, "AUTH")
const rawEvent = Builder.authenticate(url, challenge)
const [event] = await Outbox.publish(rawEvent, [url], null, "AUTH")
return event
}
@ -148,31 +149,29 @@
})
engine.Storage.ready.then(() => {
const pubkey = engine.Keys.pubkey.get()
const pubkey = Keys.pubkey.get()
// Make sure the user's stuff is loaded, but don't call loadAppData
// since that reloads messages and stuff
if (pubkey) {
engine.PubkeyLoader.load(pubkey, {force: true, kinds: userKinds})
PubkeyLoader.load(pubkey, {force: true, kinds: userKinds})
listenForNotifications()
}
const interval = setInterval(async () => {
if (!engine.User.getSetting("dufflepud_url")) {
if (!User.getSetting("dufflepud_url")) {
return
}
// Find relays with old/missing metadata and refresh them. Only pick a
// few so we're not sending too many concurrent http requests
const staleRelays = shuffle(
engine.Nip65.relays
.get()
.filter(r => (r.info?.last_checked || 0) < now() - seconds(7, "day"))
Nip65.relays.get().filter(r => (r.info?.last_checked || 0) < now() - seconds(7, "day"))
).slice(0, 10) as Relay[]
for (const relay of staleRelays) {
tryFetch(async () => {
const info = await Fetch.fetchJson(engine.User.dufflepud("relay/info"), {
const info = await Fetch.fetchJson(User.dufflepud("relay/info"), {
method: "POST",
body: JSON.stringify({url: relay.url}),
headers: {
@ -180,7 +179,7 @@
},
})
engine.Nip65.relays.key(relay.url).merge({...info, last_checked: now()})
Nip65.relays.key(relay.url).merge({...info, last_checked: now()})
})
}
}, 30_000)

View File

@ -3,15 +3,15 @@
import {nip19} from "nostr-tools"
import {navigate} from "svelte-routing"
import {fade} from "src/util/transition"
import {keys} from "src/app/engine"
import {modal, location} from "src/partials/state"
import {Keys} from "src/app/engine"
let scrollY = 0
$: showCreateNote = $location.pathname.match(/messages|chat|relays$|keys|settings|logout$/)
$: showLogin = !$location.pathname.match(/login$/)
const {canSign} = keys
const {canSign} = Keys
const scrollToTop = () => document.body.scrollIntoView({behavior: "smooth"})

View File

@ -20,13 +20,13 @@
import RelayList from "src/app/views/RelayList.svelte"
import UserProfile from "src/app/views/UserProfile.svelte"
import UserSettings from "src/app/views/UserSettings.svelte"
import {storage} from "src/app/engine"
import {Storage} from "src/app/engine"
const TypedRoute = Route as ComponentType<SvelteComponentTyped>
let ready = false
storage.ready.then(() => {
Storage.ready.then(() => {
ready = true
})
</script>

View File

@ -3,15 +3,15 @@
import {derived} from "svelte/store"
import {theme, installPrompt} from "src/partials/state"
import PersonCircle from "src/app/shared/PersonCircle.svelte"
import {FORCE_RELAYS, keys, directory, alerts, nip28, nip04} from "src/app/engine"
import {Env, Keys, Directory, Alerts, Nip28, Nip04} from "src/app/engine"
import {routes, slowConnections, menuIsOpen} from "src/app/state"
const {canSign, pubkey} = keys
const {hasNewNotfications} = alerts
const {hasNewMessages: hasNewChatMessages} = nip28
const {hasNewMessages: hasNewDirectMessages} = nip04
const profile = derived([pubkey, directory.profiles], () =>
$pubkey ? directory.getProfile($pubkey) : null
const {canSign, pubkey} = Keys
const {hasNewNotfications} = Alerts
const {hasNewMessages: hasNewChatMessages} = Nip28
const {hasNewMessages: hasNewDirectMessages} = Nip04
const profile = derived([pubkey, Directory.profiles], () =>
$pubkey ? Directory.getProfile($pubkey) : null
)
const toggleTheme = () => theme.update(t => (t === "dark" ? "light" : "dark"))
@ -39,7 +39,7 @@
<li>
<a href={routes.person($pubkey)} class="flex items-center gap-2 px-4 py-2 pb-6">
<PersonCircle size={6} pubkey={$pubkey} />
<span class="text-lg font-bold">{directory.displayProfile($profile)}</span>
<span class="text-lg font-bold">{Directory.displayProfile($profile)}</span>
</a>
</li>
<li class="relative cursor-pointer">
@ -89,7 +89,7 @@
</a>
</li>
<li class="mx-3 my-4 h-px bg-gray-6" />
{#if FORCE_RELAYS.length === 0}
{#if Env.FORCE_RELAYS.length === 0}
<li class="relative cursor-pointer">
<a class="block px-4 py-2 transition-all hover:bg-accent hover:text-white" href="/relays">
<i class="fa fa-server mr-2" /> Relays

View File

@ -2,12 +2,12 @@
import {onMount} from "svelte"
import {appName} from "src/partials/state"
import Anchor from "src/partials/Anchor.svelte"
import {alerts, nip04, nip28} from "src/app/engine"
import {menuIsOpen} from "src/app/state"
import {Alerts, Nip04, Nip28} from "src/app/engine"
const {hasNewNotfications} = alerts
const {hasNewMessages: hasNewChatMessages} = nip28
const {hasNewMessages: hasNewDirectMessages} = nip04
const {hasNewNotfications} = Alerts
const {hasNewMessages: hasNewChatMessages} = Nip28
const {hasNewMessages: hasNewDirectMessages} = Nip04
const logoUrl = import.meta.env.VITE_LOGO_URL || "/images/logo.png"
const toggleMenu = () => menuIsOpen.update(x => !x)

View File

@ -1,17 +1,17 @@
import {identity} from "ramda"
import {Engine} from "src/engine"
export const DUFFLEPUD_URL = import.meta.env.VITE_DUFFLEPUD_URL
const DUFFLEPUD_URL = import.meta.env.VITE_DUFFLEPUD_URL
export const MULTIPLEXTR_URL = import.meta.env.VITE_MULTIPLEXTR_URL
const MULTIPLEXTR_URL = import.meta.env.VITE_MULTIPLEXTR_URL
export const FORCE_RELAYS = (import.meta.env.VITE_FORCE_RELAYS || "").split(",").filter(identity)
const FORCE_RELAYS = (import.meta.env.VITE_FORCE_RELAYS || "").split(",").filter(identity)
export const COUNT_RELAYS = FORCE_RELAYS.length > 0 ? FORCE_RELAYS : ["wss://rbr.bio"]
const COUNT_RELAYS = FORCE_RELAYS.length > 0 ? FORCE_RELAYS : ["wss://rbr.bio"]
export const SEARCH_RELAYS = FORCE_RELAYS.length > 0 ? FORCE_RELAYS : ["wss://relay.nostr.band"]
const SEARCH_RELAYS = FORCE_RELAYS.length > 0 ? FORCE_RELAYS : ["wss://relay.nostr.band"]
export const DEFAULT_RELAYS =
const DEFAULT_RELAYS =
FORCE_RELAYS.length > 0
? FORCE_RELAYS
: [
@ -22,11 +22,9 @@ export const DEFAULT_RELAYS =
"wss://nostr.wine",
]
export const DEFAULT_FOLLOWS = (import.meta.env.VITE_DEFAULT_FOLLOWS || "")
.split(",")
.filter(identity)
const DEFAULT_FOLLOWS = (import.meta.env.VITE_DEFAULT_FOLLOWS || "").split(",").filter(identity)
export const ENABLE_ZAPS = JSON.parse(import.meta.env.VITE_ENABLE_ZAPS)
const ENABLE_ZAPS = JSON.parse(import.meta.env.VITE_ENABLE_ZAPS)
const engine = new Engine({
DUFFLEPUD_URL,
@ -39,7 +37,7 @@ const engine = new Engine({
})
export default engine
export const E = engine
export const Env = engine.Env
export const Alerts = engine.Alerts
export const Builder = engine.Builder
export const Content = engine.Content
@ -59,21 +57,3 @@ export const Outbox = engine.Outbox
export const PubkeyLoader = engine.PubkeyLoader
export const Storage = engine.Storage
export const User = engine.User
export const alerts = engine.Alerts
export const builder = engine.Builder
export const content = engine.Content
export const directory = engine.Directory
export const events = engine.Events
export const keys = engine.Keys
export const meta = engine.Meta
export const network = engine.Network
export const nip02 = engine.Nip02
export const nip04 = engine.Nip04
export const nip05 = engine.Nip05
export const nip28 = engine.Nip28
export const nip57 = engine.Nip57
export const nip65 = engine.Nip65
export const outbox = engine.Outbox
export const pubkeyLoader = engine.PubkeyLoader
export const storage = engine.Storage
export const user = engine.User

View File

@ -12,7 +12,7 @@
import FeedControls from "src/app/shared/FeedControls.svelte"
import RelayFeed from "src/app/shared/RelayFeed.svelte"
import Note from "src/app/shared/Note.svelte"
import {user, nip65, network} from "src/app/engine"
import {User, Nip65, Network} from "src/app/engine"
import {compileFilter} from "src/app/state"
export let relays = []
@ -55,14 +55,14 @@
// If we have a search term we need to use only relays that support search
if (filter.search) {
return nip65.getSearchRelays()
return Nip65.getSearchRelays()
}
const limit = user.getSetting("relay_limit")
const authors = (compileFilter(filter).authors || []).concat(user.getPubkey())
const hints = authors.map(pubkey => nip65.getPubkeyHints(limit, pubkey))
const limit = User.getSetting("relay_limit")
const authors = (compileFilter(filter).authors || []).concat(User.getPubkey())
const hints = authors.map(pubkey => Nip65.getPubkeyHints(limit, pubkey))
return nip65.mergeHints(limit, hints)
return Nip65.mergeHints(limit, hints)
}
const loadMore = () => {
@ -83,7 +83,7 @@
filter = newFilter
}
feed = network.feed({
feed = Network.feed({
depth: 2,
relays: getRelays(),
filter: compileFilter(filter),

View File

@ -13,16 +13,16 @@
import SelectButton from "src/partials/SelectButton.svelte"
import MultiSelect from "src/partials/MultiSelect.svelte"
import PersonBadge from "src/app/shared/PersonBadge.svelte"
import {directory, user, content} from "src/app/engine"
import {Directory, User, default as engine} from "src/app/engine"
export let filter
export let onChange
const {searchProfiles} = directory
const {searchTopics} = content
const {searchProfiles} = Directory
const {searchTopics} = engine.Content
const displayPeople = pubkeys =>
pubkeys.length === 1 ? directory.displayPubkey(pubkeys[0]) : `${pubkeys.length} people`
pubkeys.length === 1 ? Directory.displayPubkey(pubkeys[0]) : `${pubkeys.length} people`
const displayTopics = topics => (topics.length === 1 ? topics[0] : `${topics.length} topics`)
@ -128,17 +128,17 @@
until: filter.since,
search: filter.search || "",
authors: Array.isArray(filter.authors)
? filter.authors.map(directory.getProfile)
? filter.authors.map(Directory.getProfile)
: filter.authors || "network",
"#t": (filter["#t"] || []).map(objOf("name")),
"#p": (filter["#p"] || []).map(directory.getProfile),
"#p": (filter["#p"] || []).map(Directory.getProfile),
}
$: parts = getFilterParts(filter)
$: {
scopeOptions =
user.getFollows().length > 0
User.getFollows().length > 0
? ["follows", "network", "global", "custom"]
: ["network", "global", "custom"]
}

View File

@ -14,16 +14,7 @@
import CopyValue from "src/partials/CopyValue.svelte"
import PersonBadge from "src/app/shared/PersonBadge.svelte"
import RelayCard from "src/app/shared/RelayCard.svelte"
import {
ENABLE_ZAPS,
FORCE_RELAYS,
nip57,
builder,
nip65,
keys,
outbox,
user,
} from "src/app/engine"
import {Env, Nip57, Builder, Nip65, Keys, Outbox, User} from "src/app/engine"
export let note
export let reply
@ -43,20 +34,20 @@
const quote = () => modal.push({type: "note/create", quote: note})
const unmute = () => user.unmute(note.id)
const unmute = () => User.unmute(note.id)
const mute = () => user.mute("e", note.id)
const mute = () => User.mute("e", note.id)
const react = async content => {
const relays = nip65.getPublishHints(3, note, user.getRelayUrls("write"))
const relays = Nip65.getPublishHints(3, note, User.getRelayUrls("write"))
like = first(await outbox.publish(builder.createReaction(note, content), relays))
like = first(await Outbox.publish(Builder.createReaction(note, content), relays))
}
const deleteReaction = e => {
outbox.publish(
builder.deleteEvents([e.id]),
nip65.getPublishHints(3, note, user.getRelayUrls("write"))
Outbox.publish(
Builder.deleteEvents([e.id]),
Nip65.getPublishHints(3, note, User.getRelayUrls("write"))
)
like = null
@ -71,20 +62,20 @@
let actions = []
let showDetails = false
$: disableActions = !keys.canSign.get() || muted
$: disableActions = !Keys.canSign.get() || muted
$: likes = note.reactions.filter(n => isLike(n.content))
$: like = like || find(propEq("pubkey", user.getPubkey()), likes)
$: like = like || find(propEq("pubkey", User.getPubkey()), likes)
$: allLikes = like ? likes.filter(n => n.id !== like?.id).concat(like) : likes
$: $likesCount = allLikes.length
$: zaps = nip57.processZaps(note.zaps, note.pubkey)
$: zap = zap || find(pathEq(["request", "pubkey"], user.getPubkey()), zaps)
$: zaps = Nip57.processZaps(note.zaps, note.pubkey)
$: zap = zap || find(pathEq(["request", "pubkey"], User.getPubkey()), zaps)
$: allZaps = zap
? zaps.filter(n => n.id !== zap?.id).concat(nip57.processZaps([zap], note.pubkey))
? zaps.filter(n => n.id !== zap?.id).concat(Nip57.processZaps([zap], note.pubkey))
: zaps
$: $zapsTotal = sum(pluck("invoiceAmount", allZaps)) / 1000
$: canZap = $zapper && note.pubkey !== user.getPubkey()
$: canZap = $zapper && note.pubkey !== User.getPubkey()
$: $repliesCount = note.replies.length
$: {
@ -99,7 +90,7 @@
actions.push({label: "Mute", icon: "microphone-slash", onClick: mute})
}
if (FORCE_RELAYS.length === 0) {
if (Env.FORCE_RELAYS.length === 0) {
actions.push({
label: "Details",
icon: "info",
@ -123,7 +114,7 @@
</button>
<button
class={cx("w-16 text-left", {
"pointer-events-none opacity-50": disableActions || note.pubkey === user.getPubkey(),
"pointer-events-none opacity-50": disableActions || note.pubkey === User.getPubkey(),
"text-accent": like,
})}
on:click={() => (like ? deleteReaction(like) : react("+"))}>
@ -133,7 +124,7 @@
})} />
{$likesCount}
</button>
{#if ENABLE_ZAPS}
{#if Env.ENABLE_ZAPS}
<button
class={cx("w-20 text-left", {
"pointer-events-none opacity-50": disableActions || !canZap,
@ -146,7 +137,7 @@
{/if}
</div>
<div class="flex items-center">
{#if FORCE_RELAYS.length === 0}
{#if Env.FORCE_RELAYS.length === 0}
<!-- Mobile version -->
<div
style="transform: scale(-1, 1)"
@ -173,7 +164,7 @@
style={`background: ${hsl(stringToHue(url))}`}
on:click={() => setFeedRelay?.({url})} />
</div>
<div slot="tooltip">{nip65.displayRelay({url})}</div>
<div slot="tooltip">{Nip65.displayRelay({url})}</div>
</Popover>
{/each}
</div>

View File

@ -5,14 +5,14 @@
import NoteContentKind9802 from "src/app/shared/NoteContentKind9802.svelte"
import NoteContentKind1063 from "src/app/shared/NoteContentKind1063.svelte"
import NoteContentKind30023 from "src/app/shared/NoteContentKind30023.svelte"
import {user} from "src/app/engine"
import {User} from "src/app/engine"
export let note
export let anchorId = null
export let maxLength = 700
export let showEntire = false
export let expandable = true
export let showMedia = user.getSetting("show_media")
export let showMedia = User.getSetting("show_media")
</script>
{#if note.kind === 40}

View File

@ -6,12 +6,12 @@
import Card from "src/partials/Card.svelte"
import Content from "src/partials/Content.svelte"
import ImageCircle from "src/partials/ImageCircle.svelte"
import {nip28} from "src/app/engine"
import {Nip28} from "src/app/engine"
export let note
const {name, picture, about} = tryJson(() => JSON.parse(note.content))
const channel = nip28.channels
const channel = Nip28.channels
.key(note.id)
.derived(defaultTo({id: note.id, name, picture, about}))
const noteId = nip19.noteEncode(note.id)

View File

@ -2,15 +2,15 @@
import {defaultTo} from "ramda"
import {modal} from "src/partials/state"
import Anchor from "src/partials/Anchor.svelte"
import {directory} from "src/app/engine"
import {Directory} from "src/app/engine"
export let value
const {pubkey} = value
const profile = directory.profiles.key(pubkey).derived(defaultTo({pubkey}))
const profile = Directory.profiles.key(pubkey).derived(defaultTo({pubkey}))
const openPerson = () => modal.push({type: "person/feed", pubkey})
</script>
@<Anchor class="underline" killEvent on:click={openPerson}>
{directory.displayProfile($profile)}
{Directory.displayProfile($profile)}
</Anchor>

View File

@ -4,7 +4,7 @@
import {modal} from "src/partials/state"
import Anchor from "src/partials/Anchor.svelte"
import Rating from "src/partials/Rating.svelte"
import {directory, nip65} from "src/app/engine"
import {Directory, Nip65} from "src/app/engine"
export let note, rating
@ -19,8 +19,8 @@
})
const display = switcherFn(type, {
r: () => nip65.displayRelay({url: value}),
p: () => directory.displayProfile(value),
r: () => Nip65.displayRelay({url: value}),
p: () => Directory.displayProfile(value),
e: () => "a note",
default: "something",
})

View File

@ -9,7 +9,7 @@
import Chip from "src/partials/Chip.svelte"
import Media from "src/partials/Media.svelte"
import Compose from "src/partials/Compose.svelte"
import {directory, user, nip65, builder} from "src/app/engine"
import {Directory, User, Nip65, Builder} from "src/app/engine"
import {publishWithToast} from "src/app/state"
export let note
@ -27,7 +27,7 @@
data = {
image: null,
mentions: without(
[user.getPubkey()],
[User.getPubkey()],
uniq(Tags.from(note).type("p").values().all().concat(note.pubkey))
),
}
@ -52,8 +52,8 @@
}
if (content) {
const rawEvent = builder.createReply(note, content, data.mentions.map(builder.mention))
const relays = nip65.getPublishHints(3, note, user.getRelayUrls("write"))
const rawEvent = Builder.createReply(note, content, data.mentions.map(Builder.mention))
const relays = Nip65.getPublishHints(3, note, User.getRelayUrls("write"))
const [event, promise] = await publishWithToast(rawEvent, relays)
promise.then(({succeeded}) => {
@ -128,7 +128,7 @@
<div on:click|stopPropagation>
{#each data.mentions as pubkey}
<Chip class="mb-1 mr-1" theme="dark" onClick={() => removeMention(pubkey)}>
{directory.displayPubkey(pubkey)}
{Directory.displayPubkey(pubkey)}
</Chip>
{:else}
<div class="text-gray-2 inline-block py-2">No mentions</div>
@ -139,7 +139,7 @@
</div>
<div class="flex justify-end gap-2 text-sm text-gray-5">
<span>
Posting as @{directory.displayPubkey(user.getPubkey())}
Posting as @{Directory.displayPubkey(User.getPubkey())}
</span>
</div>
</div>

View File

@ -2,12 +2,12 @@
import {ellipsize} from "hurdak"
import {parseContent} from "src/util/notes"
import Anchor from "src/partials/Anchor.svelte"
import {directory} from "src/app/engine"
import {Directory} from "src/app/engine"
export let pubkey
export let truncate = false
const profile = directory.getProfile(pubkey)
const profile = Directory.getProfile(pubkey)
const about = profile.about || ""
const content = parseContent({content: truncate ? ellipsize(about, 140) : about})
</script>
@ -25,7 +25,7 @@
{:else if type.startsWith("nostr:")}
<Anchor class="underline" external href={"/" + value.entity}>
{#if value.pubkey}
{directory.displayProfile(profile)}
{Directory.displayProfile(profile)}
{:else if value.id}
event {value.id}
{:else}

View File

@ -4,22 +4,22 @@
import {modal} from "src/partials/state"
import Popover from "src/partials/Popover.svelte"
import OverflowMenu from "src/partials/OverflowMenu.svelte"
import {FORCE_RELAYS, keys, user, nip02} from "src/app/engine"
import {Env, Keys, User, Nip02} from "src/app/engine"
import {addToList} from "src/app/state"
export let pubkey
const npub = nip19.npubEncode(pubkey)
const graphEntry = nip02.graph.key(keys.pubkey.get())
const following = graphEntry.derived(() => user.isFollowing(pubkey))
const muted = graphEntry.derived(() => user.isIgnoring(pubkey))
const graphEntry = Nip02.graph.key(Keys.pubkey.get())
const following = graphEntry.derived(() => User.isFollowing(pubkey))
const muted = graphEntry.derived(() => User.isIgnoring(pubkey))
let actions = []
$: {
actions = []
if (keys.canSign.get()) {
if (Keys.canSign.get()) {
actions.push({
onClick: () => addToList("p", pubkey),
label: "Add to list",
@ -29,7 +29,7 @@
actions.push({onClick: share, label: "Share", icon: "share-nodes"})
if (user.getPubkey() !== pubkey && keys.canSign.get()) {
if (Keys.pubkey.get() !== pubkey && Keys.canSign.get()) {
actions.push({
onClick: () => navigate(`/messages/${npub}`),
label: "Message",
@ -38,16 +38,16 @@
if ($muted) {
actions.push({onClick: unmute, label: "Unmute", icon: "microphone"})
} else if (user.getPubkey() !== pubkey) {
} else if (Keys.pubkey.get() !== pubkey) {
actions.push({onClick: mute, label: "Mute", icon: "microphone-slash"})
}
}
if (FORCE_RELAYS.length === 0) {
if (Env.FORCE_RELAYS.length === 0) {
actions.push({onClick: openProfileInfo, label: "Details", icon: "info"})
}
if (user.getPubkey() === pubkey && keys.canSign.get()) {
if (Keys.pubkey.get() === pubkey && Keys.canSign.get()) {
actions.push({
onClick: () => navigate("/profile"),
label: "Edit",
@ -60,22 +60,22 @@
const share = () => modal.push({type: "person/share", pubkey})
const unfollow = () => user.unfollow(pubkey)
const unfollow = () => User.unfollow(pubkey)
const follow = () => user.follow(pubkey)
const follow = () => User.follow(pubkey)
const unmute = () => user.unmute(pubkey)
const unmute = () => User.unmute(pubkey)
const mute = () => user.mute("p", pubkey)
const mute = () => User.mute("p", pubkey)
</script>
<div class="flex items-center gap-3">
{#if keys.canSign.get()}
{#if Keys.canSign.get()}
<Popover triggerType="mouseenter">
<div slot="trigger">
{#if $following}
<i class="fa fa-user-minus cursor-pointer" on:click={unfollow} />
{:else if user.getPubkey() !== pubkey}
{:else if Keys.pubkey.get() !== pubkey}
<i class="fa fa-user-plus cursor-pointer" on:click={follow} />
{/if}
</div>

View File

@ -3,14 +3,14 @@
import {Link} from "svelte-routing"
import {killEvent} from "src/util/html"
import {routes} from "src/app/state"
import {directory} from "src/app/engine"
import {Directory} from "src/app/engine"
import PersonCircle from "src/app/shared/PersonCircle.svelte"
export let pubkey
export let inert = false
const profile = directory.getProfile(pubkey)
const display = directory.displayProfile(profile)
const profile = Directory.getProfile(pubkey)
const display = Directory.displayProfile(profile)
</script>
{#if inert}

View File

@ -4,7 +4,7 @@
import {stringToHue, hsl} from "src/util/misc"
import ImageCircle from "src/partials/ImageCircle.svelte"
import LogoSvg from "src/partials/LogoSvg.svelte"
import {directory} from "src/app/engine"
import {Directory} from "src/app/engine"
export let pubkey
export let size = 4
@ -12,7 +12,7 @@
const hue = stringToHue(pubkey)
const primary = hsl(hue, {lightness: 80})
const secondary = hsl(hue, {saturation: 30, lightness: 30})
const profile = directory.profiles.key(pubkey).derived(defaultTo({pubkey}))
const profile = Directory.profiles.key(pubkey).derived(defaultTo({pubkey}))
</script>
{#if $profile.picture}

View File

@ -4,28 +4,28 @@
import Anchor from "src/partials/Anchor.svelte"
import PersonCircle from "src/app/shared/PersonCircle.svelte"
import PersonAbout from "src/app/shared/PersonAbout.svelte"
import {user, directory, nip05} from "src/app/engine"
import {User, Directory, Nip05} from "src/app/engine"
export let pubkey
export let hasPetname = null
const profile = directory.getProfile(pubkey)
const handle = nip05.getHandle(pubkey)
const profile = Directory.getProfile(pubkey)
const handle = Nip05.getHandle(pubkey)
const unfollow = () => {
user.unfollow(pubkey)
User.unfollow(pubkey)
isFollowing = false
}
const follow = () => {
user.follow(pubkey)
User.follow(pubkey)
isFollowing = true
}
// Set this manually to avoid a million listeners
let isFollowing = hasPetname ? hasPetname(pubkey) : user.isFollowing(pubkey)
let isFollowing = hasPetname ? hasPetname(pubkey) : User.isFollowing(pubkey)
</script>
<div in:fly={{y: 20}}>
@ -38,11 +38,11 @@
<div class="flex min-w-0 flex-grow flex-col gap-4">
<div class="flex items-start justify-between gap-2">
<div class="flex flex-col gap-2">
<h1 class="text-xl">{directory.displayProfile(profile)}</h1>
<h1 class="text-xl">{Directory.displayProfile(profile)}</h1>
{#if handle}
<div class="flex gap-1 text-sm">
<i class="fa fa-user-check text-accent" />
<span class="text-gray-1">{nip05.displayHandle(handle)}</span>
<span class="text-gray-1">{Nip05.displayHandle(handle)}</span>
</div>
{/if}
</div>

View File

@ -5,7 +5,7 @@
import Content from "src/partials/Content.svelte"
import Spinner from "src/partials/Spinner.svelte"
import PersonInfo from "src/app/shared/PersonInfo.svelte"
import {nip02, nip65, user, network, pubkeyLoader} from "src/app/engine"
import {Nip02, Nip65, User, Network, PubkeyLoader} from "src/app/engine"
export let type
export let pubkey
@ -14,15 +14,15 @@
onMount(() => {
if (type === "follows") {
pubkeys = nip02.getFollows(pubkey)
pubkeys = Nip02.getFollows(pubkey)
} else {
const sub = network.subscribe({
relays: nip65.getPubkeyHints(user.getSetting("relay_limit"), pubkey, "read"),
const sub = Network.subscribe({
relays: Nip65.getPubkeyHints(User.getSetting("relay_limit"), pubkey, "read"),
filter: {kinds: [3], "#p": [pubkey]},
onEvent: batch(500, events => {
const newPubkeys = pluck("pubkey", events)
pubkeyLoader.load(newPubkeys)
PubkeyLoader.load(newPubkeys)
pubkeys = uniq(pubkeys.concat(newPubkeys))
}),

View File

@ -5,11 +5,11 @@
import {tweened} from "svelte/motion"
import {numberFmt} from "src/util/misc"
import {modal} from "src/partials/state"
import {nip02, user, nip65, network} from "src/app/engine"
import {Nip02, User, Nip65, Network} from "src/app/engine"
export let pubkey
const followsCount = nip02.graph.key(pubkey).derived(() => nip02.getFollowsSet(pubkey).size)
const followsCount = nip02.graph.key(pubkey).derived(() => Nip02.getFollowsSet(pubkey).size)
const interpolate = (a, b) => t => a + Math.round((b - a) * t)
let sub
@ -24,17 +24,17 @@
canLoadFollowers = false
// Get our followers count
const count = await network.count({kinds: [3], "#p": [pubkey]})
const count = await networK.count({kinds: [3], "#p": [pubkey]})
if (count) {
followersCount.set(count)
} else {
const followers = new Set()
sub = network.subscribe({
sub = Network.subscribe({
timeout: 30_000,
shouldProcess: false,
relays: nip65.getPubkeyHints(3, user.getPubkey(), "read"),
relays: Nip65.getPubkeyHints(3, User.getPubkey(), "read"),
filter: [{kinds: [3], "#p": [pubkey]}],
onEvent: batch(300, events => {
for (const e of events) {

View File

@ -4,20 +4,20 @@
import {directory, nip02, nip05} from "src/app/engine"
import PersonCircle from "src/app/shared/PersonCircle.svelte"
import PersonAbout from "src/app/shared/PersonAbout.svelte"
import {keys, user} from "src/app/engine"
import {Keys, User} from "src/app/engine"
import {routes} from "src/app/state"
export let pubkey
const graphEntry = nip02.graph.key(keys.pubkey.get())
const following = graphEntry.derived(() => user.isFollowing(pubkey))
const muted = graphEntry.derived(() => user.isIgnoring(pubkey))
const graphEntry = nip02.graph.key(keyS.pubkey.get())
const following = graphEntry.derived(() => User.isFollowing(pubkey))
const muted = graphEntry.derived(() => User.isIgnoring(pubkey))
const profile = directory.profiles.key(pubkey).derived(defaultTo({pubkey}))
const handle = nip05.handles.key(pubkey)
const unfollow = () => user.unfollow(pubkey)
const follow = () => user.follow(pubkey)
const unmute = () => user.unmute(pubkey)
const mute = () => user.mute("p", pubkey)
const unfollow = () => User.unfollow(pubkey)
const follow = () => User.follow(pubkey)
const unmute = () => User.unmute(pubkey)
const mute = () => User.mute("p", pubkey)
</script>
<div class="relative flex flex-col gap-4 px-3 py-2">
@ -34,7 +34,7 @@
</div>
</Anchor>
<div class="absolute right-1 top-1 flex gap-4 py-2 text-lg">
{#if keys.canSign.get()}
{#if Keys.canSign.get()}
{#if $muted}
<i
title="Unmute"

View File

@ -2,13 +2,13 @@
import {last} from "ramda"
import {modal} from "src/partials/state"
import OverflowMenu from "src/partials/OverflowMenu.svelte"
import {nip65, keys, user} from "src/app/engine"
import {Nip65, Keys, User} from "src/app/engine"
import {addToList} from "src/app/state"
export let relay
const info = nip65.getRelayInfo(relay.url)
const relays = nip65.policies.key(keys.pubkey.get()).derived(() => user.getRelayUrls())
const info = Nip65.getRelayInfo(relay.url)
const relays = Nip65.policies.key(Keys.pubkey.get()).derived(() => User.getRelayUrls())
let actions = []
@ -18,19 +18,19 @@
if (!joined) {
actions.push({
onClick: () => user.addRelay(relay.url),
onClick: () => User.addRelay(relay.url),
label: "Join",
icon: "right-to-bracket",
})
} else if ($relays.length > 1) {
actions.push({
onClick: () => user.removeRelay(relay.url),
onClick: () => User.removeRelay(relay.url),
label: "Leave",
icon: "right-from-bracket",
})
}
if (keys.canSign.get()) {
if (Keys.canSign.get()) {
actions.push({
onClick: () => addToList("r", relay.url),
label: "Add to list",

View File

@ -6,7 +6,7 @@
import {normalizeRelayUrl, Tags, getAvgQuality} from "src/util/nostr"
import Input from "src/partials/Input.svelte"
import RelayCard from "src/app/shared/RelayCard.svelte"
import {nip65, network, user, keys} from "src/app/engine"
import {Nip65, Network, User, Keys} from "src/app/engine"
export let q = ""
export let limit = 50
@ -16,8 +16,8 @@
let search
let reviews = []
const joined = nip65.policies.key(keys.pubkey.get()).derived(() => new Set(user.getRelayUrls()))
const knownRelays = nip65.relays
const joined = Nip65.policies.key(Keys.pubkey.get()).derived(() => new Set(User.getRelayUrls()))
const knownRelays = Nip65.relays
$: ratings = mapVals(
events => getAvgQuality("review/relay", events),
@ -32,8 +32,8 @@
}
onMount(() => {
const sub = network.subscribe({
relays: nip65.getPubkeyHints(3, user.getPubkey(), "read"),
const sub = Network.subscribe({
relays: Nip65.getPubkeyHints(3, User.getPubkey(), "read"),
filter: {
limit: 1000,
kinds: [1985],

View File

@ -5,7 +5,7 @@
import {stringToHue, hsl} from "src/util/misc"
import Rating from "src/partials/Rating.svelte"
import Anchor from "src/partials/Anchor.svelte"
import {nip65, meta} from "src/app/engine"
import {Nip65, Meta} from "src/app/engine"
export let relay
export let rating = null
@ -16,7 +16,7 @@
onMount(() => {
return poll(10_000, () => {
;[quality, message] = meta.getRelayQuality(relay.url)
;[quality, message] = Meta.getRelayQuality(relay.url)
})
})
</script>
@ -28,7 +28,7 @@
href={`/relays/${webSocketURLToPlainOrBase64(relay.url)}`}
class="border-b border-solid"
style={`border-color: ${hsl(stringToHue(relay.url))}`}>
{nip65.displayRelay(relay)}
{Nip65.displayRelay(relay)}
</Anchor>
<span
on:mouseout={() => {

View File

@ -1,7 +1,7 @@
<script lang="ts">
import OverflowMenu from "src/partials/OverflowMenu.svelte"
import {addToList} from "src/app/state"
import {keys} from "src/app/engine"
import {Keys} from "src/app/engine"
export let topic
@ -10,7 +10,7 @@
$: {
actions = []
if (keys.canSign.get()) {
if (Keys.canSign.get()) {
actions.push({
onClick: () => addToList("t", topic),
label: "Add to list",

View File

@ -10,19 +10,8 @@ import {warn} from "src/util/logger"
import {now} from "src/util/misc"
import {userKinds, noteKinds} from "src/util/nostr"
import {modal, toast} from "src/partials/state"
import type {Event} from 'src/engine/types'
import {
FORCE_RELAYS,
DEFAULT_FOLLOWS,
PubkeyLoader,
Events,
Nip28,
Meta,
Network,
Outbox,
User,
Keys,
} from "src/app/engine"
import type {Event} from "src/engine/types"
import {PubkeyLoader, Events, Nip28, Meta, Network, Outbox, User, Keys} from "src/app/engine"
// Routing
@ -171,7 +160,7 @@ export const loadAppData = async () => {
export const login = async (method: string, key: string) => {
Keys.login(method, key)
if (FORCE_RELAYS.length > 0) {
if (Env.FORCE_RELAYS.length > 0) {
modal.replace({
type: "message",
message: "Logging you in...",
@ -218,7 +207,7 @@ export const publishWithToast = (event: Event, relays: string[]) =>
export const compileFilter = (filter: DynamicFilter): Filter => {
const getAuthors = (pubkeys: string[]) =>
shuffle(pubkeys.length > 0 ? pubkeys : DEFAULT_FOLLOWS as string[]).slice(0, 256)
shuffle(pubkeys.length > 0 ? pubkeys : (Env.DEFAULT_FOLLOWS as string[])).slice(0, 256)
if (filter.authors === "global") {
filter = omit(["authors"], filter)

View File

@ -7,7 +7,7 @@
import NoteDetail from "src/app/views/NoteDetail.svelte"
import NaddrDetail from "src/app/views/NaddrDetail.svelte"
import PersonDetail from "src/app/views/PersonDetail.svelte"
import {nip65} from "src/app/engine"
import {Nip65} from "src/app/engine"
export let entity
@ -18,7 +18,7 @@
onMount(() => {
try {
;({type, data} = nip19.decode(entity) as {type: string; data: any})
relays = nip65.selectHints(3, data.relays || [])
relays = Nip65.selectHints(3, data.relays || [])
} catch (e) {
warn(e)
}

View File

@ -8,16 +8,16 @@
import Anchor from "src/partials/Anchor.svelte"
import PersonBadge from "src/app/shared/PersonBadge.svelte"
import NoteContent from "src/app/shared/NoteContent.svelte"
import {builder, nip28, user, outbox, nip65, network} from "src/app/engine"
import {Builder, Nip28, User, Keys, Outbox, Nip65, Network} from "src/app/engine"
export let entity
const id = toHex(entity)
const channel = nip28.channels.key(id).derived(defaultTo({id}))
const messages = nip28.messages.derived(filter(whereEq({channel: id})))
const getRelays = () => nip65.selectHints(user.getSetting("relay_limit"), $channel.hints || [])
const channel = Nip28.channels.key(id).derived(defaultTo({id}))
const messages = Nip28.messages.derived(filter(whereEq({channel: id})))
const getRelays = () => Nip65.selectHints(User.getSetting("relay_limit"), $channel.hints || [])
user.setChannelLastChecked(id)
User.setChannelLastChecked(id)
const edit = () => {
modal.push({type: "channel/edit", channel: $channel})
@ -26,11 +26,11 @@
const sendMessage = async content => {
const relays = getRelays()
await outbox.publish(builder.createChatMessage(id, content, relays[0]), relays)
await Outbox.publish(Builder.createChatMessage(id, content, relays[0]), relays)
}
onMount(() => {
const sub = network.subscribe({
const sub = Network.subscribe({
relays: getRelays(),
filter: [{kinds: [42], "#e": [id]}],
onEvent: e => console.log(e),
@ -41,7 +41,7 @@
onDestroy(() => {
if (!$channel.joined) {
nip28.messages.reject(m => m.channel === id)
Nip28.messages.reject(m => m.channel === id)
}
})
@ -60,7 +60,7 @@
<div class="flex w-full items-center justify-between">
<div class="flex items-center gap-4">
<div class="text-lg font-bold">{$channel.name || ""}</div>
{#if $channel.pubkey === user.getPubkey()}
{#if $channel.pubkey === Keys.pubkey.get()}
<button class="cursor-pointer text-sm" on:click={edit}>
<i class="fa-solid fa-edit" /> Edit
</button>

View File

@ -8,7 +8,7 @@
import Textarea from "src/partials/Textarea.svelte"
import Anchor from "src/partials/Anchor.svelte"
import {toast, modal} from "src/partials/state"
import {builder, user} from "src/app/engine"
import {Builder, User} from "src/app/engine"
import {publishWithToast} from "src/app/state"
export let channel = {name: null, id: null, about: null, picture: null}
@ -35,15 +35,15 @@
if (!channel.name) {
toast.show("error", "Please enter a name for your room.")
} else {
const relays = user.getRelayUrls("write")
const relays = User.getRelayUrls("write")
if (channel.id) {
publishWithToast(builder.updateChannel(channel), relays)
publishWithToast(Builder.updateChannel(channel), relays)
} else {
const [event] = await publishWithToast(builder.createChannel(channel), relays)
const [event] = await publishWithToast(Builder.createChannel(channel), relays)
// Auto join the room the user just created
await user.joinChannel(event.id)
await User.joinChannel(event.id)
}
modal.pop()

View File

@ -4,13 +4,13 @@
import {fly} from "src/util/transition"
import {ellipsize} from "hurdak"
import Anchor from "src/partials/Anchor.svelte"
import {keys, user} from "src/app/engine"
import {Keys, User} from "src/app/engine"
export let channel
const enter = () => navigate(`/chat/${nip19.noteEncode(channel.id)}`)
const join = () => user.joinChannel(channel.id)
const leave = () => user.leaveChannel(channel.id)
const join = () => User.joinChannel(channel.id)
const leave = () => User.leaveChannel(channel.id)
</script>
<button
@ -31,7 +31,7 @@
<i class="fa fa-right-from-bracket" />
<span>Leave</span>
</Anchor>
{:else if keys.canSign.get()}
{:else if Keys.canSign.get()}
<Anchor theme="button" killEvent class="flex items-center gap-2" on:click={join}>
<i class="fa fa-right-to-bracket" />
<span>Join</span>

View File

@ -8,15 +8,15 @@
import Content from "src/partials/Content.svelte"
import Popover from "src/partials/Popover.svelte"
import Feed from "src/app/shared/Feed.svelte"
import {keys, user, content} from "src/app/engine"
import {Keys, User, default as engine} from "src/app/engine"
const lists = content.lists.derived(() => user.getLists())
const lists = engine.Content.lists.derived(() => User.getLists())
let relays = []
let key = Math.random()
let filter = {
kinds: noteKinds,
authors: user.getFollows().length > 0 ? "follows" : "network",
authors: User.getFollows().length > 0 ? "follows" : "network",
} as DynamicFilter
const showLists = () => {
@ -24,7 +24,7 @@
}
const loadListFeed = naddr => {
const list = content.lists.key(naddr).get()
const list = engine.Content.lists.key(naddr).get()
const authors = Tags.from(list).pubkeys()
const topics = Tags.from(list).topics()
const urls = Tags.from(list).urls()
@ -50,7 +50,7 @@
</script>
<Content>
{#if !user.getPubkey()}
{#if !Keys.pubkey.get()}
<Content size="lg" class="text-center">
<p class="text-xl">Don't have an account?</p>
<p>
@ -61,7 +61,7 @@
{#key key}
<Feed {filter} {relays}>
<div slot="controls">
{#if keys.canSign.get()}
{#if Keys.canSign.get()}
{#if $lists.length > 0}
<Popover placement="bottom" opts={{hideOnClick: true}} theme="transparent">
<i slot="trigger" class="fa fa-ellipsis-v cursor-pointer p-2" />

View File

@ -4,9 +4,9 @@
import Anchor from "src/partials/Anchor.svelte"
import Content from "src/partials/Content.svelte"
import ListSummary from "src/app/shared/ListSummary.svelte"
import {content, user} from "src/app/engine"
import {default as engine, User} from "src/app/engine"
const lists = content.lists.derived(() => user.getLists())
const lists = engine.Content.lists.derived(() => User.getLists())
const createFeed = () => {
modal.push({type: "list/edit"})
@ -33,7 +33,7 @@
<div class="flex justify-start gap-3">
<i
class="fa fa-sm fa-trash cursor-pointer py-3"
on:click|stopPropagation={() => user.removeList(list.naddr)} />
on:click|stopPropagation={() => User.removeList(list.naddr)} />
<div class="flex w-full justify-between">
<div>
<strong>{list.name}</strong>

View File

@ -1,22 +1,21 @@
<script type="ts">
import {updateIn} from "hurdak"
import {Tags} from "src/util/nostr"
import {derived} from "svelte/store"
import {modal} from "src/partials/state"
import Heading from "src/partials/Heading.svelte"
import Anchor from "src/partials/Anchor.svelte"
import BorderLeft from "src/partials/BorderLeft.svelte"
import Content from "src/partials/Content.svelte"
import ListSummary from "src/app/shared/ListSummary.svelte"
import E from "src/app/engine"
import {User, default as engine} from "src/app/engine"
export let item
const lists = E.Content.lists.derived(() => E.User.getLists())
const lists = engine.Content.lists.derived(() => User.getLists())
const label = item.type === "p" ? "person" : "topic"
const modifyList = updateIn("tags", (tags: string[][]) =>
(tags || []).concat([[item.type, item.value]])
)
const modifyList = updateIn("tags", tags => (tags || []).concat([[item.type, item.value]]))
const selectlist = list => modal.replace({type: "list/edit", list: modifyList(list)})
</script>

View File

@ -6,7 +6,7 @@
import Anchor from "src/partials/Anchor.svelte"
import Content from "src/partials/Content.svelte"
import Heading from "src/partials/Heading.svelte"
import {user} from "src/app/engine"
import {User} from "src/app/engine"
import {login} from "src/app/state"
const nip07 = "https://github.com/nostr-protocol/nips/blob/master/07.md"
@ -29,7 +29,7 @@
modal.push({type: "login/advanced"})
}
if (user.getPubkey()) {
if (User.getPubkey()) {
navigate("/")
}

View File

@ -5,7 +5,7 @@
import Anchor from "src/partials/Anchor.svelte"
import Content from "src/partials/Content.svelte"
import Heading from "src/partials/Heading.svelte"
import {keys} from "src/app/engine"
import {Keys} from "src/app/engine"
import {login} from "src/app/state"
let input = ""
@ -14,7 +14,7 @@
const [npub, token] = input.split("#")
const pubkey = npub.startsWith("npub") ? toHex(npub) : npub
if (keys.isKeyValid(pubkey)) {
if (Keys.isKeyValid(pubkey)) {
login("bunker", {pubkey, token})
} else {
toast.show("error", "Sorry, but that's an invalid public key.")

View File

@ -12,15 +12,7 @@
import Anchor from "src/partials/Anchor.svelte"
import Modal from "src/partials/Modal.svelte"
import RelayCard from "src/app/shared/RelayCard.svelte"
import {
DEFAULT_RELAYS,
FORCE_RELAYS,
Nip65,
User,
Keys,
PubkeyLoader,
Network,
} from "src/app/engine"
import {Env, Nip65, User, Keys, PubkeyLoader, Network} from "src/app/engine"
import {loadAppData} from "src/app/state"
const pubkey = Keys.pubkey.get()
@ -36,7 +28,7 @@
uniqBy(
prop("url"),
// Make sure our hardcoded urls are first, since they're more likely to find a match
DEFAULT_RELAYS.map(objOf("url")).concat(shuffle($relays))
Env.DEFAULT_RELAYS.map(objOf("url")).concat(shuffle($relays))
)
)
@ -130,7 +122,7 @@
}}>here</Anchor
>.
</p>
{#if FORCE_RELAYS.length > 0}
{#if Env.FORCE_RELAYS.length > 0}
<Spinner />
{:else if Object.values(currentRelays).length > 0}
<p>Currently searching:</p>

View File

@ -6,7 +6,7 @@
import Anchor from "src/partials/Anchor.svelte"
import Content from "src/partials/Content.svelte"
import Heading from "src/partials/Heading.svelte"
import {keys} from "src/app/engine"
import {Keys} from "src/app/engine"
import {login} from "src/app/state"
let nsec = ""
@ -15,7 +15,7 @@
const logIn = () => {
const privkey = nsec.startsWith("nsec") ? toHex(nsec) : nsec
if (keys.isKeyValid(privkey)) {
if (Keys.isKeyValid(privkey)) {
login("privkey", privkey)
} else {
toast.show("error", "Sorry, but that's an invalid private key.")

View File

@ -4,7 +4,7 @@
import Anchor from "src/partials/Anchor.svelte"
import Content from "src/partials/Content.svelte"
import Heading from "src/partials/Heading.svelte"
import {keys} from "src/app/engine"
import {Keys} from "src/app/engine"
import {toast} from "src/partials/state"
import {login} from "src/app/state"
@ -13,7 +13,7 @@
const logIn = () => {
const pubkey = npub.startsWith("npub") ? toHex(npub) : npub
if (keys.isKeyValid(pubkey)) {
if (Keys.isKeyValid(pubkey)) {
login("pubkey", pubkey)
} else {
toast.show("error", "Sorry, but that's an invalid public key.")

View File

@ -2,14 +2,14 @@
import {fly} from "src/util/transition"
import Anchor from "src/partials/Anchor.svelte"
import Content from "src/partials/Content.svelte"
import {storage} from "src/app/engine"
import {Storage} from "src/app/engine"
let confirmed = false
const confirm = async () => {
confirmed = true
await storage.clear()
await Storage.clear()
// do a hard refresh so everything gets totally cleared.
// Give them a moment to see the state transition. IndexedDB

View File

@ -7,7 +7,7 @@
import Channel from "src/partials/Channel.svelte"
import Anchor from "src/partials/Anchor.svelte"
import NoteContent from "src/app/shared/NoteContent.svelte"
import {user, nip04, nip65, outbox, Crypt, directory, builder, network} from "src/app/engine"
import {User, Nip04, Nip65, Outbox, Crypt, Directory, Builder, Network} from "src/app/engine"
import {routes} from "src/app/state"
import PersonCircle from "src/app/shared/PersonCircle.svelte"
import PersonAbout from "src/app/shared/PersonAbout.svelte"
@ -15,21 +15,21 @@
export let entity
const pubkey = toHex(entity)
const profile = directory.profiles.key(pubkey).derived(defaultTo({pubkey}))
const messages = nip04.messages.derived(filter(whereEq({contact: pubkey})))
const profile = Directory.profiles.key(pubkey).derived(defaultTo({pubkey}))
const messages = Nip04.messages.derived(filter(whereEq({contact: pubkey})))
user.setContactLastChecked(pubkey)
User.setContactLastChecked(pubkey)
const getRelays = () =>
nip65.mergeHints(3, [
nip65.getPubkeyHints(3, pubkey),
nip65.getPubkeyHints(3, user.getPubkey()),
Nip65.mergeHints(3, [
Nip65.getPubkeyHints(3, pubkey),
Nip65.getPubkeyHints(3, Keys.pubkey.get()),
])
const sendMessage = async content => {
const cyphertext = await Crypt.encrypt(pubkey, content)
const [event] = await outbox.publish(
builder.createDirectMessage(pubkey, cyphertext),
const [event] = await Outbox.publish(
Builder.createDirectMessage(pubkey, cyphertext),
getRelays()
)
@ -38,16 +38,16 @@
}
onMount(() => {
return network.subscribe({
return Network.subscribe({
relays: getRelays(),
filter: [
{kinds: [4], authors: [user.getPubkey()], "#p": [pubkey]},
{kinds: [4], authors: [pubkey], "#p": [user.getPubkey()]},
{kinds: [4], authors: [Keys.pubkey.get()], "#p": [pubkey]},
{kinds: [4], authors: [pubkey], "#p": [Keys.pubkey.get()]},
],
})
})
document.title = `DMs with ${directory.displayProfile($profile)}`
document.title = `DMs with ${Directory.displayProfile($profile)}`
</script>
<Channel {messages} {sendMessage}>
@ -63,7 +63,7 @@
<div class="flex w-full items-center justify-between">
<div class="flex items-center gap-4">
<Anchor href={routes.person(pubkey)} class="text-lg font-bold">
{directory.displayProfile($profile)}
{Directory.displayProfile($profile)}
</Anchor>
</div>
<div class="flex items-center gap-2">
@ -78,14 +78,14 @@
slot="message"
let:message
class={cx("flex overflow-hidden text-ellipsis", {
"ml-12 justify-end": message.profile.pubkey === user.getPubkey(),
"mr-12": message.profile.pubkey !== user.getPubkey(),
"ml-12 justify-end": message.profile.pubkey === Keys.pubkey.get(),
"mr-12": message.profile.pubkey !== Keys.pubkey.get(),
})}>
<div
class={cx("inline-block max-w-xl rounded-2xl px-4 py-2", {
"rounded-br-none bg-gray-1 text-end text-gray-8":
message.profile.pubkey === user.getPubkey(),
"rounded-bl-none bg-gray-7": message.profile.pubkey !== user.getPubkey(),
message.profile.pubkey === Keys.pubkey.get(),
"rounded-bl-none bg-gray-7": message.profile.pubkey !== Keys.pubkey.get(),
})}>
<div class="break-words">
{#if typeof message.content === "string"}
@ -94,8 +94,8 @@
</div>
<small
class="mt-1"
class:text-gray-7={message.profile.pubkey === user.getPubkey()}
class:text-gray-1={message.profile.pubkey !== user.getPubkey()}>
class:text-gray-7={message.profile.pubkey === Keys.pubkey.get()}
class:text-gray-1={message.profile.pubkey !== Keys.pubkey.get()}>
{formatTimestamp(message.created_at)}
</small>
</div>

View File

@ -4,12 +4,12 @@
import {ellipsize} from "hurdak"
import PersonCircle from "src/app/shared/PersonCircle.svelte"
import Card from "src/partials/Card.svelte"
import {directory, nip04} from "src/app/engine"
import {Directory, Nip04} from "src/app/engine"
export let contact
const hasNewMessages = nip04.contacts.key(contact.pubkey).derived(nip04.messageIsNew)
const profile = directory.getProfile(contact.pubkey)
const hasNewMessages = Nip04.contacts.key(contact.pubkey).derived(Nip04.messageIsNew)
const profile = Directory.getProfile(contact.pubkey)
const enter = () => navigate(`/messages/${nip19.npubEncode(contact.pubkey)}`)
</script>
@ -20,7 +20,7 @@
<div class="flex flex-grow items-start justify-between gap-2">
<div class="flex items-center gap-2 overflow-hidden">
<i class="fa fa-lock text-gray-1" />
<h2 class="text-lg">{directory.displayProfile(profile)}</h2>
<h2 class="text-lg">{Directory.displayProfile(profile)}</h2>
</div>
<div class="relative">
<i class="fa fa-bell" class:text-gray-5={!$hasNewMessages} />

View File

@ -15,7 +15,7 @@
import RelayCard from "src/app/shared/RelayCard.svelte"
import NoteContent from "src/app/shared/NoteContent.svelte"
import RelaySearch from "src/app/shared/RelaySearch.svelte"
import {directory, builder, nip65, user} from "src/app/engine"
import {Directory, Builder, Nip65, Keys} from "src/app/engine"
import {toast, modal} from "src/partials/state"
import {publishWithToast} from "src/app/state"
@ -28,7 +28,7 @@
let compose = null
let showPreview = false
let showSettings = false
let relays = writable(writeTo ? writeTo : user.getRelayUrls("write"))
let relays = writable(writeTo ? writeTo : User.getRelayUrls("write"))
const onSubmit = async () => {
let content = compose.parse()
@ -39,11 +39,11 @@
}
if (quote) {
tags.push(builder.mention(quote.pubkey))
tags.push(Builder.mention(quote.pubkey))
}
if (content) {
const rawEvent = builder.createNote(content.trim(), tags)
const rawEvent = Builder.createNote(content.trim(), tags)
const [event, promise] = await publishWithToast(rawEvent, $relays)
promise.then(() =>
@ -88,8 +88,8 @@
}
onMount(() => {
if (pubkey && pubkey !== user.getPubkey()) {
compose.mention(directory.getProfile(pubkey))
if (pubkey && pubkey !== Keys.pubkey.get()) {
compose.mention(Directory.getProfile(pubkey))
}
if (quote) {
@ -120,7 +120,7 @@
</div>
<div class="flex items-center justify-end gap-2 text-gray-5">
<small>
Posting as @{directory.displayPubkey(user.getPubkey())}
Posting as @{Directory.displayPubkey(Keys.pubkey.get())}
</small>
<span></span>
<small on:click={togglePreview} class="cursor-pointer underline">
@ -147,7 +147,7 @@
}}>
<span>
Publishing to {#if $relays?.length === 1}
{nip65.displayRelay({url: $relays[0]})}
{Nip65.displayRelay({url: $relays[0]})}
{:else}
{$relays.length} relays
{/if}
@ -174,7 +174,7 @@
type="button"
class="fa fa-times cursor-pointer"
on:click={() => removeRelay(url)} />
{nip65.displayRelay(url)}
{Nip65.displayRelay(url)}
</div>
{/each}
</div>

View File

@ -8,17 +8,17 @@
import RelayFeed from "src/app/shared/RelayFeed.svelte"
import Modal from "src/partials/Modal.svelte"
import Spinner from "src/partials/Spinner.svelte"
import {nip65, network} from "src/app/engine"
import {Nip65, Network} from "src/app/engine"
import Note from "src/app/shared/Note.svelte"
export let note
export let relays = []
export let invertColors = false
const feed = network.feed({
const feed = Network.feed({
limit: 1,
depth: 6,
relays: nip65.selectHints(10, relays),
relays: Nip65.selectHints(10, relays),
filter: {ids: [note.id]},
})

View File

@ -3,11 +3,11 @@
import {toNostrURI} from "src/util/nostr"
import Content from "src/partials/Content.svelte"
import QRCode from "src/partials/QRCode.svelte"
import {nip65} from "src/app/engine"
import {Nip65} from "src/app/engine"
export let note
const nevent = nip19.neventEncode({id: note.id, relays: nip65.getEventHints(3, note)})
const nevent = nip19.neventEncode({id: note.id, relays: Nip65.getEventHints(3, note)})
</script>
<Content size="lg">

View File

@ -9,13 +9,13 @@
import Anchor from "src/partials/Anchor.svelte"
import Input from "src/partials/Input.svelte"
import Textarea from "src/partials/Textarea.svelte"
import {directory, nip65, user, outbox, network, builder, nip57} from "src/app/engine"
import {Directory, Nip65, User, Outbox, Network, Builder, Nip57} from "src/app/engine"
export let note
let sub
let zap = {
amount: user.getSetting("default_zap"),
amount: User.getSetting("default_zap"),
message: "",
invoice: null,
loading: false,
@ -23,16 +23,16 @@
confirmed: false,
}
const author = directory.getProfile(note.pubkey)
const author = Directory.getProfile(note.pubkey)
const loadZapInvoice = async () => {
zap.loading = true
const amount = zap.amount * 1000
const zapper = nip57.zappers.key(note.pubkey).get()
const relays = nip65.getPublishHints(3, note, user.getRelayUrls("write"))
const event = await outbox.prepEvent(
builder.requestZap(relays, zap.message, note.pubkey, note.id, amount, zapper.lnurl)
const zapper = Nip57.zappers.key(note.pubkey).get()
const relays = Nip65.getPublishHints(3, note, User.getRelayUrls("write"))
const event = await Outbox.prepEvent(
Builder.requestZap(relays, zap.message, note.pubkey, note.id, amount, zapper.lnurl)
)
const eventString = encodeURI(JSON.stringify(event))
const res = await Fetch.fetchJson(
@ -64,7 +64,7 @@
}
// Listen for the zap confirmation
sub = network.subscribe({
sub = Network.subscribe({
relays,
filter: {
kinds: [9735],
@ -87,7 +87,7 @@
<Content size="lg">
<div class="text-center">
<h1 class="staatliches text-2xl">Send a zap</h1>
<p>to {directory.displayProfile(author)}</p>
<p>to {Directory.displayProfile(author)}</p>
</div>
{#if zap.confirmed}
<div class="flex items-center justify-center gap-2 text-gray-1">

View File

@ -5,14 +5,14 @@
import Heading from "src/partials/Heading.svelte"
import Content from "src/partials/Content.svelte"
import PersonInfo from "src/app/shared/PersonInfo.svelte"
import {DEFAULT_FOLLOWS, nip02, user, directory, builder} from "src/app/engine"
import {Env, Nip02, User, Directory, Builder} from "src/app/engine"
import {modal} from "src/partials/state"
const {searchProfiles} = directory
const follows = nip02.graph.derived(() => user.getFollowsSet())
const {searchProfiles} = Directory
const follows = Nip02.graph.derived(() => User.getFollowsSet())
if ($follows.size === 0) {
user.setPetnames(DEFAULT_FOLLOWS.map(builder.mention))
User.setPetnames(Env.DEFAULT_FOLLOWS.map(Builder.mention))
}
let q = ""

View File

@ -6,12 +6,12 @@
import Anchor from "src/partials/Anchor.svelte"
import Heading from "src/partials/Heading.svelte"
import Content from "src/partials/Content.svelte"
import {FORCE_RELAYS} from "src/app/engine"
import {Env} from "src/app/engine"
export let privkey
const nsec = nip19.nsecEncode(privkey)
const nextStage = FORCE_RELAYS.length > 0 ? "follows" : "relays"
const nextStage = Env.FORCE_RELAYS.length > 0 ? "follows" : "relays"
const copyKey = () => {
copyToClipboard(nsec)

View File

@ -7,13 +7,13 @@
import Heading from "src/partials/Heading.svelte"
import Content from "src/partials/Content.svelte"
import RelayCard from "src/app/shared/RelayCard.svelte"
import {nip65, user} from "src/app/engine"
import {Nip65, User} from "src/app/engine"
let q = ""
let search
const userRelays = nip65.policies.derived(() => user.getRelays())
const knownRelays = nip65.relays.derived()
const userRelays = Nip65.policies.derived(() => User.getRelays())
const knownRelays = Nip65.relays.derived()
$: {
const joined = new Set(pluck("url", $userRelays))

View File

@ -12,7 +12,7 @@
import PersonNotes from "src/app/shared/PersonNotes.svelte"
import PersonLikes from "src/app/shared/PersonLikes.svelte"
import PersonRelays from "src/app/shared/PersonRelays.svelte"
import {FORCE_RELAYS, pubkeyLoader, nip05, directory, nip65} from "src/app/engine"
import {Env, PubkeyLoader, Nip05, Directory, Nip65} from "src/app/engine"
import {routes} from "src/app/state"
import PersonCircle from "src/app/shared/PersonCircle.svelte"
import PersonAbout from "src/app/shared/PersonAbout.svelte"
@ -22,16 +22,16 @@
export let activeTab
export let relays = []
const tabs = ["notes", "likes", FORCE_RELAYS.length === 0 && "relays"].filter(identity)
const tabs = ["notes", "likes", Env.FORCE_RELAYS.length === 0 && "relays"].filter(identity)
const pubkey = toHex(npub)
const handle = nip05.handles.key(pubkey)
const profile = directory.profiles.key(pubkey).derived(defaultTo({pubkey}))
const handle = Nip05.handles.key(pubkey)
const profile = Directory.profiles.key(pubkey).derived(defaultTo({pubkey}))
let loading = true
let rgb, rgba
$: ownRelays = nip65.getPubkeyRelays(pubkey)
$: relays = nip65.getPubkeyHints(pubkey)
$: ownRelays = Nip65.getPubkeyRelays(pubkey)
$: relays = Nip65.getPubkeyHints(pubkey)
$: {
const color = parseHex(getThemeColor($theme, "gray-8"))
@ -42,9 +42,9 @@
log("Person", npub, $profile)
pubkeyLoader.load([pubkey], {force: true})
PubkeyLoader.load([pubkey], {force: true})
document.title = directory.displayProfile($profile)
document.title = Directory.displayProfile($profile)
const setActiveTab = tab => navigate(routes.person(pubkey, tab))
</script>
@ -64,12 +64,12 @@
<div class="flex items-start justify-between gap-4">
<div class="flex flex-grow flex-col gap-2">
<div class="flex items-center gap-2">
<h1 class="text-2xl">{directory.displayProfile($profile)}</h1>
<h1 class="text-2xl">{Directory.displayProfile($profile)}</h1>
</div>
{#if $handle}
<div class="flex gap-1 text-sm">
<i class="fa fa-user-check text-accent" />
<span class="text-gray-1">{nip05.displayHandle($handle)}</span>
<span class="text-gray-1">{Nip05.displayHandle($handle)}</span>
</div>
{/if}
</div>

View File

@ -4,13 +4,13 @@
import Content from "src/partials/Content.svelte"
import RelayCard from "src/app/shared/RelayCard.svelte"
import CopyValue from "src/partials/CopyValue.svelte"
import {nip05, nip65} from "src/app/engine"
import {Nip05, Nip65} from "src/app/engine"
export let pubkey
const handle = nip05.getHandle(pubkey)
const handle = Nip05.getHandle(pubkey)
const npub = nip19.npubEncode(pubkey)
const relays = nip65.getPubkeyHints(3, pubkey)
const relays = Nip65.getPubkeyHints(3, pubkey)
const nprofile = nip19.nprofileEncode({pubkey, relays})
</script>
@ -26,7 +26,7 @@
<h1 class="staatliches mt-4 text-2xl">NIP05</h1>
{#if handle}
<CopyValue label="NIP 05 Identifier" value={nip05.displayHandle(handle)} />
<CopyValue label="NIP 05 Identifier" value={Nip05.displayHandle(handle)} />
<div>
<div class="mb-2 text-lg">NIP05 Relay Configuration</div>
{#if handle.profile.relays?.length > 0}

View File

@ -3,11 +3,11 @@
import {toNostrURI} from "src/util/nostr"
import Content from "src/partials/Content.svelte"
import QRCode from "src/partials/QRCode.svelte"
import {nip65} from "src/app/engine"
import {Nip65} from "src/app/engine"
export let pubkey
const relays = nip65.getPubkeyHints(3, pubkey)
const relays = Nip65.getPubkeyHints(3, pubkey)
const nprofile = nip19.nprofileEncode({pubkey, relays})
</script>

View File

@ -7,7 +7,7 @@
import Rating from "src/partials/Rating.svelte"
import RelayTitle from "src/app/shared/RelayTitle.svelte"
import RelayActions from "src/app/shared/RelayActions.svelte"
import {nip65} from "src/app/engine"
import {Nip65} from "src/app/engine"
export let url
@ -18,7 +18,7 @@
$: rating = getAvgQuality("review/relay", reviews)
const relay = nip65.getRelay(url)
const relay = Nip65.getRelay(url)
const tabs = ["reviews", "notes"]
const setActiveTab = tab => {
activeTab = tab
@ -28,7 +28,7 @@
reviews = reviews.concat(chunk)
})
document.title = nip65.displayRelay(relay)
document.title = Nip65.displayRelay(relay)
</script>
<Content>

View File

@ -3,10 +3,10 @@
import Anchor from "src/partials/Anchor.svelte"
import Content from "src/partials/Content.svelte"
import RelayCard from "src/app/shared/RelayCard.svelte"
import {nip65, user} from "src/app/engine"
import {Nip65, User} from "src/app/engine"
import {modal} from "src/partials/state"
const relays = nip65.policies.derived(() => user.getRelays())
const relays = Nip65.policies.derived(() => User.getRelays())
document.title = "Relays"
</script>

View File

@ -6,7 +6,7 @@
import Heading from "src/partials/Heading.svelte"
import Compose from "src/partials/Compose.svelte"
import Rating from "src/partials/Rating.svelte"
import {builder, outbox} from "src/app/engine"
import {Builder, Outbox} from "src/app/engine"
export let url
@ -15,7 +15,7 @@
const onSubmit = () => {
const review = compose.parse()
const event = builder.createLabel({
const event = Builder.createLabel({
content: review,
tagClient: false,
tags: [
@ -25,7 +25,7 @@
],
})
outbox.publish(event)
Outbox.publish(event)
modal.pop()
}

View File

@ -3,11 +3,11 @@
import Content from "src/partials/Content.svelte"
import Heading from "src/partials/Heading.svelte"
import TopicActions from "src/app/shared/TopicActions.svelte"
import {nip65, user} from "src/app/engine"
import {Nip65, User} from "src/app/engine"
export let topic
const relays = nip65.getPubkeyHints(3, user.getPubkey(), "read")
const relays = Nip65.getPubkeyHints(3, User.getPubkey(), "read")
const filter = {kinds: [1], "#t": [topic]}
</script>

View File

@ -9,10 +9,10 @@
import Content from "src/partials/Content.svelte"
import Toggle from "src/partials/Toggle.svelte"
import Heading from "src/partials/Heading.svelte"
import {keys} from "src/app/engine"
import {Keys} from "src/app/engine"
import {toast} from "src/partials/state"
const {pubkey, privkey, bunkerKey} = keys
const {pubkey, privkey, bunkerKey} = Keys
const nip07 = "https://github.com/nostr-protocol/nips/blob/master/07.md"
const keypairUrl = "https://www.cloudflare.com/learning/ssl/how-does-public-key-encryption-work/"

View File

@ -8,7 +8,7 @@
import Anchor from "src/partials/Anchor.svelte"
import Content from "src/partials/Content.svelte"
import Heading from "src/partials/Heading.svelte"
import {directory, keys, user, builder} from "src/app/engine"
import {Directory, Keys, User, Builder} from "src/app/engine"
import {routes} from "src/app/state"
import {publishWithToast} from "src/app/state"
@ -18,22 +18,22 @@
"https://www.coindesk.com/markets/2020/06/29/many-bitcoin-developers-are-choosing-to-use-pseudonyms-for-good-reason/"
onMount(async () => {
if (!keys.canSign.get()) {
if (!Keys.canSign.get()) {
return navigate("/login")
}
})
const submit = async event => {
const relays = user.getRelayUrls("write")
const relays = User.getRelayUrls("write")
event?.preventDefault()
publishWithToast(builder.setProfile(values), relays)
publishWithToast(Builder.setProfile(values), relays)
navigate(routes.person($pubkey, "notes"))
}
const {pubkey} = keys
const {pubkey} = Keys
let values = directory.getProfile($pubkey)
let values = Directory.getProfile($pubkey)
document.title = "Profile"
</script>

View File

@ -6,12 +6,12 @@
import Anchor from "src/partials/Anchor.svelte"
import Content from "src/partials/Content.svelte"
import Heading from "src/partials/Heading.svelte"
import {FORCE_RELAYS, user} from "src/app/engine"
import {Env, User} from "src/app/engine"
let values = {...user.settings.get()}
let values = {...User.settings.get()}
const submit = () => {
user.setSettings(values)
User.setSettings(values)
toast.show("info", "Your settings have been saved!")
}
@ -67,7 +67,7 @@
>.
</p>
</div>
{#if FORCE_RELAYS.length === 0}
{#if Env.FORCE_RELAYS.length === 0}
<div class="flex flex-col gap-1">
<strong>Multiplextr URL</strong>
<Input bind:value={values.multiplextr_url}>

View File

@ -6,7 +6,7 @@
import {fly} from "src/util/transition"
import {createScroller} from "src/util/misc"
import Spinner from "src/partials/Spinner.svelte"
import {keys, directory} from "src/app/engine"
import {Keys, Directory} from "src/app/engine"
export let messages
export let sendMessage
@ -66,7 +66,7 @@
const groupedMessages = derived([messages], ([$messages, $limit]) => {
const result = reverse(
sortBy(prop("created_at"), $messages).reduce((mx, m) => {
const profile = directory.getProfile(m.pubkey)
const profile = Directory.getProfile(m.pubkey)
const showProfile = profile.pubkey !== getPath(["profile", "pubkey"], last(mx))
return mx.concat({...m, profile, showProfile})
@ -86,7 +86,7 @@
<div class="flex h-full gap-4">
<div class="relative w-full">
<div class="py-18 flex h-screen flex-col" class:pb-20={keys.canSign.get()}>
<div class="py-18 flex h-screen flex-col" class:pb-20={Keys.canSign.get()}>
<ul
class="channel-messages flex flex-grow flex-col-reverse justify-start overflow-auto p-4 pb-6">
{#each $groupedMessages as m (m.id)}
@ -104,7 +104,7 @@
<div class="fixed top-0 z-20 w-full border-b border-solid border-gray-6 bg-gray-7">
<slot name="header" />
</div>
{#if keys.canSign.get()}
{#if Keys.canSign.get()}
<div
class="fixed bottom-0 z-10 flex w-full border-t border-solid border-gray-6 border-gray-7 bg-gray-6 lg:-ml-56 lg:pl-56">
<textarea

View File

@ -4,7 +4,7 @@
import PersonBadge from "src/app/shared/PersonBadge.svelte"
import ContentEditable from "src/partials/ContentEditable.svelte"
import Suggestions from "src/partials/Suggestions.svelte"
import {nip65, directory, user} from "src/app/engine"
import {Nip65, Directory, User} from "src/app/engine"
export let onSubmit
@ -12,7 +12,7 @@
const pubkeyEncoder = {
encode: pubkey => {
const relays = nip65.getPubkeyHints(3, pubkey)
const relays = Nip65.getPubkeyHints(3, pubkey)
const nprofile = nip19.nprofileEncode({pubkey, relays})
return "nostr:" + nprofile
@ -29,7 +29,7 @@
let results = []
if (word.length > 1 && word.startsWith("@")) {
const [followed, notFollowed] = partition(
p => user.isFollowing(p.pubkey),
p => User.isFollowing(p.pubkey),
$searchProfiles(word.slice(1))
)
@ -83,7 +83,7 @@
// Mentions
if ((force || word.length > 1) && word.startsWith("@") && profile) {
annotate("@", directory.displayProfile(profile).trim(), pubkeyEncoder.encode(profile.pubkey))
annotate("@", Directory.displayProfile(profile).trim(), pubkeyEncoder.encode(profile.pubkey))
}
// Topics

View File

@ -6,7 +6,7 @@
import Content from "src/partials/Content.svelte"
import Anchor from "src/partials/Anchor.svelte"
import {listenForFile, stripExifData, blobToFile} from "src/util/html"
import {user} from "src/app/engine"
import {User} from "src/app/engine"
export let value
export let icon
@ -25,7 +25,7 @@
const opts = filter(identity, {maxWidth, maxHeight})
file = blobToFile(await stripExifData(inputFile, opts))
quote = await Fetch.postJson(user.dufflepud("upload/quote"), {
quote = await Fetch.postJson(User.dufflepud("upload/quote"), {
uploads: [{size: file.size}],
})
} else {
@ -41,7 +41,7 @@
try {
const {id} = quote.uploads[0]
const {url} = await Fetch.uploadFile(user.dufflepud(`upload/${id}`), file)
const {url} = await Fetch.uploadFile(User.dufflepud(`upload/${id}`), file)
value = url
} finally {

View File

@ -3,14 +3,14 @@
import {ellipsize} from "hurdak"
import Anchor from "src/partials/Anchor.svelte"
import Spinner from "src/partials/Spinner.svelte"
import {user} from "src/app/engine"
import {User} from "src/app/engine"
export let link
export let onClick = null
export let onClose = null
const loadPreview = async () => {
const res = await fetch(user.dufflepud("link/preview"), {
const res = await fetch(User.dufflepud("link/preview"), {
method: "POST",
body: JSON.stringify({url: link.url}),
headers: {

View File

@ -6,6 +6,7 @@
"paths": {
"src/*": ["src/*"]
},
"isolatedModules": true,
"strictPropertyInitialization": false,
"strictNullChecks": false
}