Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9df8cee501 |
@@ -1,6 +1,6 @@
|
||||
VITE_DEFAULT_PUBKEYS=06639a386c9c1014217622ccbcf40908c4f1a0c33e23f8d6d68f4abf655f8f71,266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5,391819e2f2f13b90cac7209419eb574ef7c0d1f4e81867fc24c47a3ce5e8a248,3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d,3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24,55f04590674f3648f4cdc9dc8ce32da2a282074cd0b020596ee033d12d385185,58c741aa630c2da35a56a77c1d05381908bd10504fdd2d8b43f725efa6d23196,61066504617ee79387021e18c89fb79d1ddbc3e7bff19cf2298f40466f8715e9,6389be6491e7b693e9f368ece88fcd145f07c068d2c1bbae4247b9b5ef439d32,63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed,6e75f7972397ca3295e0f4ca0fbc6eb9cc79be85bafdd56bd378220ca8eee74e,76c71aae3a491f1d9eec47cba17e229cda4113a0bbb6e6ae1776d7643e29cafa,7fa56f5d6962ab1e3cd424e758c3002b8665f7b0d8dcee9fe9e288d7751ac194,82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2,84dee6e676e5bb67b4ad4e042cf70cbd8681155db535942fcc6a0533858a7240,97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322,b676ded7c768d66a757aa3967b1243d90bf57afb09d1044d3219d8d424e4aea0,dace63b00c42e6e017d00dd190a9328386002ff597b841eb5ef91de4f1ce8491,eeb11961b25442b16389fe6c7ebea9adf0ac36dd596816ea7119e521b8821b9e,fe7f6bc6f7338b76bbf80db402ade65953e20b2f23e66e898204b63cc42539a3
|
||||
VITE_DEFAULT_BLOSSOM_SERVERS=https://blossom.primal.net/
|
||||
VITE_DEFAULT_SPACES=https://support.flotilla.social/
|
||||
VITE_DEFAULT_SPACES=https://chat.flotilla.social/
|
||||
VITE_POMADE_SIGNERS=https://pomade.coracle.social,https://pomade.fiatjaf.com,https://pomade.nostrver.se,https://pomade.scuttle.works
|
||||
VITE_PLATFORM_URL=https://app.flotilla.social
|
||||
VITE_PLATFORM_TERMS=https://flotilla.social/terms
|
||||
|
||||
@@ -170,9 +170,6 @@ src/
|
||||
- Do not define svelte event handlers inline, instead name them and put them in the script section of templates
|
||||
- Avoid using `as`, except where necessary. Instead, annotate function parameters, and ensure upstream values are typed correctly.
|
||||
- Instead of `getTag(tagName, event.tags)?.[1] || ""`, use `getTagValue(tagName, event.tags)`
|
||||
- Do not render a profile's `about` directly (e.g. `profile.about`); use the `ProfileInfo` component instead.
|
||||
- Use `type Props` instead of interface when defining props for svelte components.
|
||||
- When a component's value/prop shape mirrors a subset of an existing type, derive it with `Pick`/`Partial` and `export` that type from the component's `<script module>` (e.g. a `Values` type) for callers to import, instead of re-enumerating its sub-properties.
|
||||
|
||||
**Human-First Simplicity (Jon Staab Style):**
|
||||
|
||||
|
||||
@@ -1,31 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
# 1.8.2
|
||||
|
||||
* Fix thread board styling
|
||||
* Fix space joining errors
|
||||
|
||||
# 1.8.1
|
||||
|
||||
* Add space dashboard and directory
|
||||
* Add space roles
|
||||
* Fix UI bugs
|
||||
* Redesign threads as a linear phpBB-style forum view
|
||||
* Unwrap messages that are only quotes
|
||||
* Use direct zapping for the donate page, link to flotilla space for support
|
||||
* Speed up feed loading
|
||||
* Fix bunker login
|
||||
* Add welshman skill
|
||||
* Replace zap slider with common amount pills
|
||||
* Make join rejections due to an empty claim more forgiving
|
||||
* Show voice room participants before joining
|
||||
* Fix direct links to spaces
|
||||
* Show per-relay publish status on outgoing messages
|
||||
* Fix A/V call bugs
|
||||
* Sync checked read state for cross-device badges
|
||||
* Fix deleted rooms persisting in navigation
|
||||
* Turn on notification defaults and prompt on first DM visit
|
||||
|
||||
# 1.8.0
|
||||
|
||||
* Fix relay badge overflow
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ RUN corepack enable
|
||||
|
||||
WORKDIR /app
|
||||
ENV NODE_OPTIONS=--max_old_space_size=16384
|
||||
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
RUN pnpm i --frozen-lockfile
|
||||
COPY . .
|
||||
ARG VITE_BUILD_HASH
|
||||
|
||||
@@ -8,8 +8,8 @@ android {
|
||||
applicationId "social.flotilla"
|
||||
minSdk rootProject.ext.minSdkVersion
|
||||
targetSdk rootProject.ext.targetSdkVersion
|
||||
versionCode 49
|
||||
versionName "1.8.2"
|
||||
versionCode 47
|
||||
versionName "1.8.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
|
||||
@@ -10,6 +10,7 @@ android {
|
||||
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
||||
dependencies {
|
||||
implementation project(':aparajita-capacitor-secure-storage')
|
||||
implementation project(':capacitor-community-safe-area')
|
||||
implementation project(':capacitor-app')
|
||||
implementation project(':capacitor-clipboard')
|
||||
implementation project(':capacitor-filesystem')
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
<item name="android:background">@null</item>
|
||||
<item name="android:windowOptOutEdgeToEdgeEnforcement" tools:ignore="NewApi">true</item>
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
@@ -1,36 +1,39 @@
|
||||
// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
|
||||
include ':capacitor-android'
|
||||
project(':capacitor-android').projectDir = new File('../node_modules/.pnpm/@capacitor+android@8.3.4_@capacitor+core@8.3.4/node_modules/@capacitor/android/capacitor')
|
||||
project(':capacitor-android').projectDir = new File('../node_modules/.pnpm/@capacitor+android@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor/android/capacitor')
|
||||
|
||||
include ':aparajita-capacitor-secure-storage'
|
||||
project(':aparajita-capacitor-secure-storage').projectDir = new File('../node_modules/.pnpm/@aparajita+capacitor-secure-storage@8.0.0/node_modules/@aparajita/capacitor-secure-storage/android')
|
||||
|
||||
include ':capacitor-community-safe-area'
|
||||
project(':capacitor-community-safe-area').projectDir = new File('../node_modules/.pnpm/@capacitor-community+safe-area@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor-community/safe-area/android')
|
||||
|
||||
include ':capacitor-app'
|
||||
project(':capacitor-app').projectDir = new File('../node_modules/.pnpm/@capacitor+app@8.1.0_@capacitor+core@8.3.4/node_modules/@capacitor/app/android')
|
||||
project(':capacitor-app').projectDir = new File('../node_modules/.pnpm/@capacitor+app@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/app/android')
|
||||
|
||||
include ':capacitor-clipboard'
|
||||
project(':capacitor-clipboard').projectDir = new File('../node_modules/.pnpm/@capacitor+clipboard@8.0.1_@capacitor+core@8.3.4/node_modules/@capacitor/clipboard/android')
|
||||
project(':capacitor-clipboard').projectDir = new File('../node_modules/.pnpm/@capacitor+clipboard@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor/clipboard/android')
|
||||
|
||||
include ':capacitor-filesystem'
|
||||
project(':capacitor-filesystem').projectDir = new File('../node_modules/.pnpm/@capacitor+filesystem@8.1.2_@capacitor+core@8.3.4/node_modules/@capacitor/filesystem/android')
|
||||
project(':capacitor-filesystem').projectDir = new File('../node_modules/.pnpm/@capacitor+filesystem@8.1.0_@capacitor+core@8.0.1/node_modules/@capacitor/filesystem/android')
|
||||
|
||||
include ':capacitor-keyboard'
|
||||
project(':capacitor-keyboard').projectDir = new File('../node_modules/.pnpm/@capacitor+keyboard@8.0.3_@capacitor+core@8.3.4/node_modules/@capacitor/keyboard/android')
|
||||
project(':capacitor-keyboard').projectDir = new File('../node_modules/.pnpm/@capacitor+keyboard@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/keyboard/android')
|
||||
|
||||
include ':capacitor-preferences'
|
||||
project(':capacitor-preferences').projectDir = new File('../node_modules/.pnpm/@capacitor+preferences@8.0.1_@capacitor+core@8.3.4/node_modules/@capacitor/preferences/android')
|
||||
project(':capacitor-preferences').projectDir = new File('../node_modules/.pnpm/@capacitor+preferences@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/preferences/android')
|
||||
|
||||
include ':capacitor-push-notifications'
|
||||
project(':capacitor-push-notifications').projectDir = new File('../node_modules/.pnpm/@capacitor+push-notifications@8.1.1_@capacitor+core@8.3.4/node_modules/@capacitor/push-notifications/android')
|
||||
project(':capacitor-push-notifications').projectDir = new File('../node_modules/.pnpm/@capacitor+push-notifications@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/push-notifications/android')
|
||||
|
||||
include ':capacitor-share'
|
||||
project(':capacitor-share').projectDir = new File('../node_modules/.pnpm/@capacitor+share@8.0.1_@capacitor+core@8.3.4/node_modules/@capacitor/share/android')
|
||||
project(':capacitor-share').projectDir = new File('../node_modules/.pnpm/@capacitor+share@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor/share/android')
|
||||
|
||||
include ':capawesome-capacitor-android-dark-mode-support'
|
||||
project(':capawesome-capacitor-android-dark-mode-support').projectDir = new File('../node_modules/.pnpm/@capawesome+capacitor-android-dark-mode-support@8.0.1_@capacitor+core@8.3.4/node_modules/@capawesome/capacitor-android-dark-mode-support/android')
|
||||
project(':capawesome-capacitor-android-dark-mode-support').projectDir = new File('../node_modules/.pnpm/@capawesome+capacitor-android-dark-mode-support@8.0.0_@capacitor+core@8.0.1/node_modules/@capawesome/capacitor-android-dark-mode-support/android')
|
||||
|
||||
include ':capawesome-capacitor-badge'
|
||||
project(':capawesome-capacitor-badge').projectDir = new File('../node_modules/.pnpm/@capawesome+capacitor-badge@8.0.2_@capacitor+core@8.3.4/node_modules/@capawesome/capacitor-badge/android')
|
||||
project(':capawesome-capacitor-badge').projectDir = new File('../node_modules/.pnpm/@capawesome+capacitor-badge@8.0.0_@capacitor+core@8.0.1/node_modules/@capawesome/capacitor-badge/android')
|
||||
|
||||
include ':nostr-signer-capacitor-plugin'
|
||||
project(':nostr-signer-capacitor-plugin').projectDir = new File('../node_modules/.pnpm/nostr-signer-capacitor-plugin@https+++codeload.github.com+coracle-social+nostr-signer-c_fd4b5c957724da9f45e5678eca5c7fd4/node_modules/nostr-signer-capacitor-plugin/android')
|
||||
project(':nostr-signer-capacitor-plugin').projectDir = new File('../node_modules/.pnpm/nostr-signer-capacitor-plugin@https+++codeload.github.com+coracle-social+nostr-signer-c_a3c0fb15d5bfa83f24d0070ca2583fc9/node_modules/nostr-signer-capacitor-plugin/android')
|
||||
|
||||
+5
-1
@@ -7,18 +7,22 @@ const config: CapacitorConfig = {
|
||||
ios: {
|
||||
scheme: "Flotilla Chat",
|
||||
},
|
||||
android: {
|
||||
adjustMarginsForEdgeToEdge: true,
|
||||
},
|
||||
plugins: {
|
||||
CapacitorHttp: {
|
||||
enabled: true,
|
||||
},
|
||||
SystemBars: {
|
||||
insetsHandling: "css",
|
||||
insetsHandling: "enable",
|
||||
},
|
||||
SplashScreen: {
|
||||
androidSplashResourceName: "splash",
|
||||
},
|
||||
Keyboard: {
|
||||
style: "DARK",
|
||||
resizeOnFullScreen: true,
|
||||
},
|
||||
Badge: {
|
||||
persist: true,
|
||||
|
||||
@@ -372,7 +372,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Flotilla Chat.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 40;
|
||||
CURRENT_PROJECT_VERSION = 38;
|
||||
INFOPLIST_FILE = App/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "Flotilla Chat";
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||
@@ -381,7 +381,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.8.2;
|
||||
MARKETING_VERSION = 1.8.0;
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = social.flotilla;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -401,7 +401,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Flotilla Chat.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 40;
|
||||
CURRENT_PROJECT_VERSION = 38;
|
||||
INFOPLIST_FILE = App/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "Flotilla Chat";
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||
@@ -410,7 +410,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.8.2;
|
||||
MARKETING_VERSION = 1.8.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = social.flotilla;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
||||
+13
-12
@@ -1,4 +1,4 @@
|
||||
require_relative '../../node_modules/.pnpm/@capacitor+ios@8.3.4_@capacitor+core@8.3.4/node_modules/@capacitor/ios/scripts/pods_helpers'
|
||||
require_relative '../../node_modules/.pnpm/@capacitor+ios@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor/ios/scripts/pods_helpers'
|
||||
|
||||
platform :ios, '15.0'
|
||||
use_frameworks!
|
||||
@@ -9,18 +9,19 @@ use_frameworks!
|
||||
install! 'cocoapods', :disable_input_output_paths => true
|
||||
|
||||
def capacitor_pods
|
||||
pod 'Capacitor', :path => '../../node_modules/.pnpm/@capacitor+ios@8.3.4_@capacitor+core@8.3.4/node_modules/@capacitor/ios'
|
||||
pod 'CapacitorCordova', :path => '../../node_modules/.pnpm/@capacitor+ios@8.3.4_@capacitor+core@8.3.4/node_modules/@capacitor/ios'
|
||||
pod 'Capacitor', :path => '../../node_modules/.pnpm/@capacitor+ios@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor/ios'
|
||||
pod 'CapacitorCordova', :path => '../../node_modules/.pnpm/@capacitor+ios@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor/ios'
|
||||
pod 'AparajitaCapacitorSecureStorage', :path => '../../node_modules/.pnpm/@aparajita+capacitor-secure-storage@8.0.0/node_modules/@aparajita/capacitor-secure-storage'
|
||||
pod 'CapacitorApp', :path => '../../node_modules/.pnpm/@capacitor+app@8.1.0_@capacitor+core@8.3.4/node_modules/@capacitor/app'
|
||||
pod 'CapacitorClipboard', :path => '../../node_modules/.pnpm/@capacitor+clipboard@8.0.1_@capacitor+core@8.3.4/node_modules/@capacitor/clipboard'
|
||||
pod 'CapacitorFilesystem', :path => '../../node_modules/.pnpm/@capacitor+filesystem@8.1.2_@capacitor+core@8.3.4/node_modules/@capacitor/filesystem'
|
||||
pod 'CapacitorKeyboard', :path => '../../node_modules/.pnpm/@capacitor+keyboard@8.0.3_@capacitor+core@8.3.4/node_modules/@capacitor/keyboard'
|
||||
pod 'CapacitorPreferences', :path => '../../node_modules/.pnpm/@capacitor+preferences@8.0.1_@capacitor+core@8.3.4/node_modules/@capacitor/preferences'
|
||||
pod 'CapacitorPushNotifications', :path => '../../node_modules/.pnpm/@capacitor+push-notifications@8.1.1_@capacitor+core@8.3.4/node_modules/@capacitor/push-notifications'
|
||||
pod 'CapacitorShare', :path => '../../node_modules/.pnpm/@capacitor+share@8.0.1_@capacitor+core@8.3.4/node_modules/@capacitor/share'
|
||||
pod 'CapawesomeCapacitorBadge', :path => '../../node_modules/.pnpm/@capawesome+capacitor-badge@8.0.2_@capacitor+core@8.3.4/node_modules/@capawesome/capacitor-badge'
|
||||
pod 'NostrSignerCapacitorPlugin', :path => '../../node_modules/.pnpm/nostr-signer-capacitor-plugin@https+++codeload.github.com+coracle-social+nostr-signer-c_fd4b5c957724da9f45e5678eca5c7fd4/node_modules/nostr-signer-capacitor-plugin'
|
||||
pod 'CapacitorCommunitySafeArea', :path => '../../node_modules/.pnpm/@capacitor-community+safe-area@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor-community/safe-area'
|
||||
pod 'CapacitorApp', :path => '../../node_modules/.pnpm/@capacitor+app@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/app'
|
||||
pod 'CapacitorClipboard', :path => '../../node_modules/.pnpm/@capacitor+clipboard@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor/clipboard'
|
||||
pod 'CapacitorFilesystem', :path => '../../node_modules/.pnpm/@capacitor+filesystem@8.1.0_@capacitor+core@8.0.1/node_modules/@capacitor/filesystem'
|
||||
pod 'CapacitorKeyboard', :path => '../../node_modules/.pnpm/@capacitor+keyboard@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/keyboard'
|
||||
pod 'CapacitorPreferences', :path => '../../node_modules/.pnpm/@capacitor+preferences@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/preferences'
|
||||
pod 'CapacitorPushNotifications', :path => '../../node_modules/.pnpm/@capacitor+push-notifications@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/push-notifications'
|
||||
pod 'CapacitorShare', :path => '../../node_modules/.pnpm/@capacitor+share@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor/share'
|
||||
pod 'CapawesomeCapacitorBadge', :path => '../../node_modules/.pnpm/@capawesome+capacitor-badge@8.0.0_@capacitor+core@8.0.1/node_modules/@capawesome/capacitor-badge'
|
||||
pod 'NostrSignerCapacitorPlugin', :path => '../../node_modules/.pnpm/nostr-signer-capacitor-plugin@https+++codeload.github.com+coracle-social+nostr-signer-c_a3c0fb15d5bfa83f24d0070ca2583fc9/node_modules/nostr-signer-capacitor-plugin'
|
||||
end
|
||||
|
||||
target 'Flotilla Chat' do
|
||||
|
||||
+4
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "flotilla",
|
||||
"version": "1.8.2",
|
||||
"version": "1.8.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
@@ -45,6 +45,7 @@
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@aparajita/capacitor-secure-storage": "^8.0.0",
|
||||
"@capacitor-community/safe-area": "^8.0.1",
|
||||
"@capacitor/android": "^8.0.1",
|
||||
"@capacitor/app": "^8.0.0",
|
||||
"@capacitor/cli": "^8.0.1",
|
||||
@@ -62,7 +63,7 @@
|
||||
"@getalby/sdk": "^5.1.2",
|
||||
"@hono/node-server": "^2.0.0",
|
||||
"@noble/curves": "^1.9.7",
|
||||
"@pomade/core": "^0.3.1",
|
||||
"@pomade/core": "^0.3.0",
|
||||
"@poppanator/sveltekit-svg": "^7.0.0",
|
||||
"@sveltejs/adapter-static": "^3.0.10",
|
||||
"@tiptap/core": "^2.27.2",
|
||||
@@ -73,6 +74,7 @@
|
||||
"@vite-pwa/sveltekit": "^1.1.0",
|
||||
"@welshman/app": "^0.8.16",
|
||||
"@welshman/content": "^0.8.16",
|
||||
"@welshman/domain": "^0.8.16",
|
||||
"@welshman/editor": "^0.8.16",
|
||||
"@welshman/feeds": "^0.8.16",
|
||||
"@welshman/lib": "^0.8.16",
|
||||
|
||||
Generated
+26
-14
@@ -14,6 +14,9 @@ importers:
|
||||
'@aparajita/capacitor-secure-storage':
|
||||
specifier: ^8.0.0
|
||||
version: 8.0.0
|
||||
'@capacitor-community/safe-area':
|
||||
specifier: ^8.0.1
|
||||
version: 8.0.1(@capacitor/core@8.3.4)
|
||||
'@capacitor/android':
|
||||
specifier: ^8.0.1
|
||||
version: 8.3.4(@capacitor/core@8.3.4)
|
||||
@@ -66,8 +69,8 @@ importers:
|
||||
specifier: ^1.9.7
|
||||
version: 1.9.7
|
||||
'@pomade/core':
|
||||
specifier: ^0.3.1
|
||||
version: 0.3.1(@frostr/bifrost@1.0.7(typescript@5.9.3))(@noble/hashes@2.2.0)(@welshman/lib@0.8.16)(@welshman/net@0.8.16(@welshman/lib@0.8.16)(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(ws@8.21.0))(@welshman/signer@0.8.16(@noble/curves@1.9.7)(@noble/hashes@2.2.0)(@welshman/lib@0.8.16)(@welshman/net@0.8.16(@welshman/lib@0.8.16)(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(ws@8.21.0))(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/436adec9ed1e71569748cd56aa697f361e7a8d47(@capacitor/core@8.3.4))(nostr-tools@2.23.5(typescript@5.9.3)))(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(nostr-tools@2.23.5(typescript@5.9.3))
|
||||
specifier: ^0.3.0
|
||||
version: 0.3.0(@frostr/bifrost@1.0.7(typescript@5.9.3))(@noble/hashes@2.2.0)(@welshman/lib@0.8.16)(@welshman/net@0.8.16(@welshman/lib@0.8.16)(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(ws@8.21.0))(@welshman/signer@0.8.16(@noble/curves@1.9.7)(@noble/hashes@2.2.0)(@welshman/lib@0.8.16)(@welshman/net@0.8.16(@welshman/lib@0.8.16)(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(ws@8.21.0))(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/436adec9ed1e71569748cd56aa697f361e7a8d47(@capacitor/core@8.3.4))(nostr-tools@2.23.5(typescript@5.9.3)))(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(nostr-tools@2.23.5(typescript@5.9.3))
|
||||
'@poppanator/sveltekit-svg':
|
||||
specifier: ^7.0.0
|
||||
version: 7.0.0(rollup@4.60.4)(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@6.4.2(@types/node@25.9.1)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0))
|
||||
@@ -94,7 +97,7 @@ importers:
|
||||
version: 1.1.0(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@6.4.2(@types/node@25.9.1)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@5.9.3)(vite@6.4.2(@types/node@25.9.1)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0)))(@vite-pwa/assets-generator@1.0.2)(vite@6.4.2(@types/node@25.9.1)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0))(workbox-build@7.4.1)(workbox-window@7.4.1)
|
||||
'@welshman/app':
|
||||
specifier: ^0.8.16
|
||||
version: 0.8.16(9e2dd3230191940679c41b23e5e365c3)
|
||||
version: 0.8.16(7683b6be0f65191b839378ceee4e4014)
|
||||
'@welshman/content':
|
||||
specifier: ^0.8.16
|
||||
version: 0.8.16(nostr-tools@2.23.5(typescript@5.9.3))
|
||||
@@ -776,6 +779,11 @@ packages:
|
||||
'@canvas/image-data@1.1.0':
|
||||
resolution: {integrity: sha512-QdObRRjRbcXGmM1tmJ+MrHcaz1MftF2+W7YI+MsphnsCrmtyfS0d5qJbk0MeSbUeyM/jCb0hmnkXPsy026L7dA==}
|
||||
|
||||
'@capacitor-community/safe-area@8.0.1':
|
||||
resolution: {integrity: sha512-zVVQ7k94DbOff1mHP8qrZGTJZWyhGZnKHD2eXdcobIoOBFW9CeVphLNZYDCop/DBsHXfv6r8k0/Ac8xMIlwT+A==}
|
||||
peerDependencies:
|
||||
'@capacitor/core': '>=8.0.0'
|
||||
|
||||
'@capacitor/android@8.3.4':
|
||||
resolution: {integrity: sha512-7gJjrG3X32Am1QMLqgMztWTYMLMVNE+VZwhekNxhvYizH4mOV05vH+rC9B+f17bCkYZfyu/qXQX6hoY7kLeVZw==}
|
||||
peerDependencies:
|
||||
@@ -1468,9 +1476,9 @@ packages:
|
||||
'@polka/url@1.0.0-next.29':
|
||||
resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
|
||||
|
||||
'@pomade/core@0.3.1':
|
||||
resolution: {integrity: sha512-lNsM60bu2o9JlqPc47JoAz19QACXS5dNYgvoeApLW8LpxuWy7RcMyHDZ3llklVPYd99PXslFtBdVRpbP26oKyQ==}
|
||||
version: 0.3.1
|
||||
'@pomade/core@0.3.0':
|
||||
resolution: {integrity: sha512-zWx0wJftbW92GSIEdLnOk8oUzaGAd0DbOqCBOoNeyCtgn9i4aNy0QsVmYDwxI8xKtVujsxppqk+fMJvinIiEqA==}
|
||||
version: 0.3.0
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
'@frostr/bifrost': ^1.0.7
|
||||
@@ -5839,6 +5847,10 @@ snapshots:
|
||||
|
||||
'@canvas/image-data@1.1.0': {}
|
||||
|
||||
'@capacitor-community/safe-area@8.0.1(@capacitor/core@8.3.4)':
|
||||
dependencies:
|
||||
'@capacitor/core': 8.3.4
|
||||
|
||||
'@capacitor/android@8.3.4(@capacitor/core@8.3.4)':
|
||||
dependencies:
|
||||
'@capacitor/core': 8.3.4
|
||||
@@ -6001,7 +6013,7 @@ snapshots:
|
||||
|
||||
'@emnapi/runtime@1.10.0':
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
tslib: 2.6.2
|
||||
optional: true
|
||||
|
||||
'@esbuild/aix-ppc64@0.25.12':
|
||||
@@ -6306,7 +6318,7 @@ snapshots:
|
||||
debug: 4.3.4
|
||||
signal-exit: 3.0.7
|
||||
tree-kill: 1.2.2
|
||||
tslib: 2.8.1
|
||||
tslib: 2.6.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -6324,7 +6336,7 @@ snapshots:
|
||||
'@ionic/utils-stream@3.1.6':
|
||||
dependencies:
|
||||
debug: 4.3.4
|
||||
tslib: 2.8.1
|
||||
tslib: 2.6.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -6344,7 +6356,7 @@ snapshots:
|
||||
'@ionic/utils-terminal': 2.3.4
|
||||
cross-spawn: 7.0.6
|
||||
debug: 4.3.4
|
||||
tslib: 2.8.1
|
||||
tslib: 2.6.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -6369,7 +6381,7 @@ snapshots:
|
||||
slice-ansi: 4.0.0
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
tslib: 2.8.1
|
||||
tslib: 2.6.2
|
||||
untildify: 4.0.0
|
||||
wrap-ansi: 7.0.0
|
||||
transitivePeerDependencies:
|
||||
@@ -6566,7 +6578,7 @@ snapshots:
|
||||
|
||||
'@polka/url@1.0.0-next.29': {}
|
||||
|
||||
'@pomade/core@0.3.1(@frostr/bifrost@1.0.7(typescript@5.9.3))(@noble/hashes@2.2.0)(@welshman/lib@0.8.16)(@welshman/net@0.8.16(@welshman/lib@0.8.16)(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(ws@8.21.0))(@welshman/signer@0.8.16(@noble/curves@1.9.7)(@noble/hashes@2.2.0)(@welshman/lib@0.8.16)(@welshman/net@0.8.16(@welshman/lib@0.8.16)(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(ws@8.21.0))(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/436adec9ed1e71569748cd56aa697f361e7a8d47(@capacitor/core@8.3.4))(nostr-tools@2.23.5(typescript@5.9.3)))(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(nostr-tools@2.23.5(typescript@5.9.3))':
|
||||
'@pomade/core@0.3.0(@frostr/bifrost@1.0.7(typescript@5.9.3))(@noble/hashes@2.2.0)(@welshman/lib@0.8.16)(@welshman/net@0.8.16(@welshman/lib@0.8.16)(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(ws@8.21.0))(@welshman/signer@0.8.16(@noble/curves@1.9.7)(@noble/hashes@2.2.0)(@welshman/lib@0.8.16)(@welshman/net@0.8.16(@welshman/lib@0.8.16)(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(ws@8.21.0))(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/436adec9ed1e71569748cd56aa697f361e7a8d47(@capacitor/core@8.3.4))(nostr-tools@2.23.5(typescript@5.9.3)))(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(nostr-tools@2.23.5(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@frostr/bifrost': 1.0.7(typescript@5.9.3)
|
||||
'@noble/hashes': 2.2.0
|
||||
@@ -7185,9 +7197,9 @@ snapshots:
|
||||
- workbox-build
|
||||
- workbox-window
|
||||
|
||||
'@welshman/app@0.8.16(9e2dd3230191940679c41b23e5e365c3)':
|
||||
'@welshman/app@0.8.16(7683b6be0f65191b839378ceee4e4014)':
|
||||
dependencies:
|
||||
'@pomade/core': 0.3.1(@frostr/bifrost@1.0.7(typescript@5.9.3))(@noble/hashes@2.2.0)(@welshman/lib@0.8.16)(@welshman/net@0.8.16(@welshman/lib@0.8.16)(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(ws@8.21.0))(@welshman/signer@0.8.16(@noble/curves@1.9.7)(@noble/hashes@2.2.0)(@welshman/lib@0.8.16)(@welshman/net@0.8.16(@welshman/lib@0.8.16)(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(ws@8.21.0))(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/436adec9ed1e71569748cd56aa697f361e7a8d47(@capacitor/core@8.3.4))(nostr-tools@2.23.5(typescript@5.9.3)))(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(nostr-tools@2.23.5(typescript@5.9.3))
|
||||
'@pomade/core': 0.3.0(@frostr/bifrost@1.0.7(typescript@5.9.3))(@noble/hashes@2.2.0)(@welshman/lib@0.8.16)(@welshman/net@0.8.16(@welshman/lib@0.8.16)(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(ws@8.21.0))(@welshman/signer@0.8.16(@noble/curves@1.9.7)(@noble/hashes@2.2.0)(@welshman/lib@0.8.16)(@welshman/net@0.8.16(@welshman/lib@0.8.16)(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(ws@8.21.0))(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(nostr-signer-capacitor-plugin@https://codeload.github.com/coracle-social/nostr-signer-capacitor-plugin/tar.gz/436adec9ed1e71569748cd56aa697f361e7a8d47(@capacitor/core@8.3.4))(nostr-tools@2.23.5(typescript@5.9.3)))(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(nostr-tools@2.23.5(typescript@5.9.3))
|
||||
'@welshman/feeds': 0.8.16(942b3be06d36b211cee078a14ee828c5)
|
||||
'@welshman/lib': 0.8.16
|
||||
'@welshman/net': 0.8.16(@welshman/lib@0.8.16)(@welshman/util@0.8.16(@noble/curves@1.9.7)(@welshman/lib@0.8.16)(nostr-tools@2.23.5(typescript@5.9.3)))(ws@8.21.0)
|
||||
|
||||
+3
-8
@@ -85,7 +85,7 @@
|
||||
}
|
||||
|
||||
@utility card2 {
|
||||
@apply rounded-box text-base-content border-base-content/20 bg-base-100 border border-solid p-4 shadow-xl/5 sm:p-6;
|
||||
@apply rounded-box text-base-content p-4 sm:p-6;
|
||||
}
|
||||
|
||||
@utility column {
|
||||
@@ -276,11 +276,6 @@
|
||||
@apply text-base-content p-2 sm:p-4;
|
||||
}
|
||||
|
||||
.card2 .card2,
|
||||
.dialog .card2 {
|
||||
@apply shadow-none;
|
||||
}
|
||||
|
||||
[data-tip]::before {
|
||||
@apply overflow-hidden text-ellipsis;
|
||||
}
|
||||
@@ -419,11 +414,11 @@ progress[value]::-webkit-progress-value {
|
||||
/* content width for fixed elements */
|
||||
|
||||
.left-content {
|
||||
@apply left-sai md:left-[calc(18.5rem+var(--sail))];
|
||||
@apply md:left-[calc(18.5rem+var(--sail))];
|
||||
}
|
||||
|
||||
.left-content-full {
|
||||
@apply left-sai md:left-[calc(3.5rem+var(--sail))];
|
||||
@apply md:left-[calc(3.5rem+var(--sail))];
|
||||
}
|
||||
|
||||
/* Keyboard open state adjustments */
|
||||
|
||||
+3
-1
@@ -4,7 +4,9 @@
|
||||
<meta charset="utf-8" />
|
||||
<title>{NAME}</title>
|
||||
<link rel="canonical" href="{URL}" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, viewport-fit=cover, interactive-widget=resizes-content" />
|
||||
<meta name="theme-color" content="{ACCENT}" />
|
||||
<meta name="description" content="{DESCRIPTION}" />
|
||||
<meta property="og:url" content="{URL}" />
|
||||
|
||||
@@ -18,7 +18,7 @@ import {derived, get} from "svelte/store"
|
||||
import {map, not, nthEq, reject, removeUndefined, uniqBy} from "@welshman/lib"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {makeHttpAuth, makeHttpAuthHeader, getTags} from "@welshman/util"
|
||||
import {signer} from "@welshman/app"
|
||||
import {signer} from "@app/welshman"
|
||||
import {load} from "@welshman/net"
|
||||
import {getLivekitEndpoint} from "$lib/livekit"
|
||||
import {AbortError, TimeoutError, whenAborted, whenTimeout} from "$lib/util"
|
||||
|
||||
+4
-1
@@ -2,7 +2,8 @@ import {DELETE, PROFILE, getPubkeyTagValues} from "@welshman/util"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {append, call, on, reject, remove, sort, sortBy, spec, uniq, uniqBy} from "@welshman/lib"
|
||||
import type {Override} from "@welshman/lib"
|
||||
import {createSearch, displayProfileByPubkey, pubkey, repository} from "@welshman/app"
|
||||
import {Profiles} from "@welshman/app"
|
||||
import {app, createSearch, pubkey, repository} from "@app/welshman"
|
||||
import {derived, readable} from "svelte/store"
|
||||
import {DM_KINDS} from "@app/content"
|
||||
import type {RepositoryUpdate} from "@welshman/net"
|
||||
@@ -35,6 +36,8 @@ export const chatsById = call(() => {
|
||||
const chatsByPubkey = new Map<string, string[]>()
|
||||
|
||||
const addSearchText = (chat: Override<Chat, {search_text?: string}>) => {
|
||||
const displayProfileByPubkey = (pk: string) => app.use(Profiles).display(pk).get()
|
||||
|
||||
chat.search_text =
|
||||
chat.pubkeys.length === 1
|
||||
? displayProfileByPubkey(chat.pubkeys[0]) + " note to self"
|
||||
|
||||
+4
-3
@@ -1,6 +1,7 @@
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {COMMENT, makeEvent} from "@welshman/util"
|
||||
import {publishThunk, tagEventForComment} from "@welshman/app"
|
||||
import {Thunks, Tags} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
|
||||
export type CommentParams = {
|
||||
event: TrustedEvent
|
||||
@@ -10,7 +11,7 @@ export type CommentParams = {
|
||||
}
|
||||
|
||||
export const makeComment = ({url, event, content, tags = []}: CommentParams) =>
|
||||
makeEvent(COMMENT, {content, tags: [...tags, ...tagEventForComment(event, url)]})
|
||||
makeEvent(COMMENT, {content, tags: [...tags, ...app.use(Tags).tagEventForComment(event, url)]})
|
||||
|
||||
export const publishComment = ({relays, ...params}: CommentParams & {relays: string[]}) =>
|
||||
publishThunk({event: makeComment({url: relays[0], ...params}), relays})
|
||||
app.use(Thunks).publish({event: makeComment({url: relays[0], ...params}), relays})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type {Snippet} from "svelte"
|
||||
import {pubkey} from "@welshman/app"
|
||||
import {pubkey} from "@app/welshman"
|
||||
import Dialog from "@lib/components/Dialog.svelte"
|
||||
import Landing from "@app/components/Landing.svelte"
|
||||
import Toast from "@app/components/Toast.svelte"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type {TrustedEvent, EventContent} from "@welshman/util"
|
||||
import {getTagValue, getAddress} from "@welshman/util"
|
||||
import {pubkey} from "@welshman/app"
|
||||
import {pubkey} from "@app/welshman"
|
||||
import Pen2 from "@assets/icons/pen-2.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
import {writable} from "svelte/store"
|
||||
import {randomId, HOUR} from "@welshman/lib"
|
||||
import {makeEvent, EVENT_TIME} from "@welshman/util"
|
||||
import {publishThunk, waitForThunkError} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import {Thunks} from "@welshman/app"
|
||||
import {preventDefault} from "@lib/html"
|
||||
import {daysBetween} from "@lib/util"
|
||||
import GallerySend from "@assets/icons/gallery-send.svg?dataurl"
|
||||
@@ -107,8 +108,8 @@
|
||||
}
|
||||
|
||||
const event = makeEvent(EVENT_TIME, {content, tags})
|
||||
const calendarThunk = publishThunk({event, relays: [url]})
|
||||
const error = await waitForThunkError(calendarThunk)
|
||||
const calendarThunk = app.use(Thunks).publish({event, relays: [url]})
|
||||
const error = await calendarThunk.waitForError()
|
||||
|
||||
if (error) {
|
||||
return pushToast({theme: "error", message: error})
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
const h = getTagValue("h", event.tags)
|
||||
</script>
|
||||
|
||||
<Link class="cv col-3 card2 w-full cursor-pointer" href={makeCalendarPath(url, getAddress(event))}>
|
||||
<Link
|
||||
class="cv col-3 card2 bg-alt w-full cursor-pointer shadow-md"
|
||||
href={makeCalendarPath(url, getAddress(event))}>
|
||||
<CalendarEventHeader {event} />
|
||||
<div class="flex w-full flex-col items-end justify-between gap-2 sm:flex-row">
|
||||
<span class="whitespace-nowrap py-1 text-sm opacity-75">
|
||||
|
||||
@@ -26,14 +26,10 @@
|
||||
DIRECT_MESSAGE,
|
||||
DIRECT_MESSAGE_FILE,
|
||||
} from "@welshman/util"
|
||||
import {
|
||||
pubkey,
|
||||
tagPubkey,
|
||||
sendWrapped,
|
||||
mergeThunks,
|
||||
loadMessagingRelayList,
|
||||
messagingRelayListsByPubkey,
|
||||
} from "@welshman/app"
|
||||
import {app, pubkey} from "@app/welshman"
|
||||
import {Tags, Wraps, Thunks, MessagingRelayLists} from "@welshman/app"
|
||||
|
||||
const messagingRelayListsByPubkey = app.use(MessagingRelayLists).index.$
|
||||
import Danger from "@assets/icons/danger-triangle.svg?dataurl"
|
||||
import ArrowLeft from "@assets/icons/arrow-left.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
@@ -96,7 +92,7 @@
|
||||
|
||||
const onSubmit = async (params: EventContent) => {
|
||||
try {
|
||||
const ptags = remove($pubkey!, pubkeys).map(tagPubkey)
|
||||
const ptags = remove($pubkey!, pubkeys).map(pk => app.use(Tags).tagPubkey(pk))
|
||||
|
||||
// Remove p tags since they result in forking the conversation
|
||||
params.tags = params.tags.filter(nthNe(0, "p"))
|
||||
@@ -109,7 +105,7 @@
|
||||
return
|
||||
}
|
||||
|
||||
await sendWrapped({
|
||||
await app.use(Wraps).publish({
|
||||
event: makeDelete({event: eventToEdit, protect: false}),
|
||||
recipients: pubkeys,
|
||||
pow: 16,
|
||||
@@ -158,7 +154,7 @@
|
||||
// Sleep 1 second between each one to make sure timestamps are distinct
|
||||
const thunks = await Promise.all(
|
||||
Array.from(enumerate(templates)).map(([i, event]) =>
|
||||
sendWrapped({
|
||||
app.use(Wraps).publish({
|
||||
event,
|
||||
recipients: pubkeys,
|
||||
delay: $userSettingsValues.send_delay + ms(i),
|
||||
@@ -171,7 +167,7 @@
|
||||
timeout: 30_000,
|
||||
children: {
|
||||
component: ThunkToast,
|
||||
props: {thunk: mergeThunks(thunks)},
|
||||
props: {thunk: app.use(Thunks).merge(thunks)},
|
||||
},
|
||||
})
|
||||
} finally {
|
||||
@@ -234,7 +230,7 @@
|
||||
|
||||
onMount(() => {
|
||||
for (const pubkey of others) {
|
||||
loadMessagingRelayList(pubkey)
|
||||
app.use(MessagingRelayLists).load(pubkey)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {displayProfileByPubkey} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import {Profiles} from "@welshman/app"
|
||||
import {slide} from "@lib/transition"
|
||||
import CloseCircle from "@assets/icons/close-circle.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
@@ -21,7 +22,7 @@
|
||||
<div
|
||||
class="relative border-l-2 border-solid border-primary bg-base-300 px-2 py-1 pr-8"
|
||||
transition:slide>
|
||||
<p class="text-xs text-primary">{verb} @{displayProfileByPubkey(event.pubkey)}</p>
|
||||
<p class="text-xs text-primary">{verb} @{app.use(Profiles).display(event.pubkey).get()}</p>
|
||||
{#key event.id}
|
||||
<NoteContentMinimal trimParent {event} />
|
||||
{/key}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import {getRelaysFromList} from "@welshman/util"
|
||||
import {waitForThunkError, setMessagingRelays, userRelayList, setRelays} from "@welshman/app"
|
||||
import {app, userRelayList} from "@app/welshman"
|
||||
import {RelayLists, MessagingRelayLists} from "@welshman/app"
|
||||
import {preventDefault} from "@lib/html"
|
||||
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
|
||||
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
|
||||
@@ -29,8 +29,10 @@
|
||||
loading = true
|
||||
|
||||
try {
|
||||
if (getRelaysFromList($userRelayList).length === 0) {
|
||||
const error = await waitForThunkError(await setRelays(DEFAULT_RELAYS.map(r => ["r", r])))
|
||||
if (($userRelayList?.urls() ?? []).length === 0) {
|
||||
const error = await (
|
||||
await app.use(RelayLists).setRelays(DEFAULT_RELAYS.map(r => ["r", r]))
|
||||
).waitForError()
|
||||
|
||||
if (error) {
|
||||
pushToast({theme: "error", message: error})
|
||||
@@ -38,7 +40,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
const error = await waitForThunkError(await setMessagingRelays(DEFAULT_MESSAGING_RELAYS))
|
||||
const error = await (
|
||||
await app.use(MessagingRelayLists).setUrls(DEFAULT_MESSAGING_RELAYS)
|
||||
).waitForError()
|
||||
|
||||
if (error) {
|
||||
pushToast({theme: "error", message: error})
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
import {page} from "$app/stores"
|
||||
import {remove, uniq, formatTimestamp} from "@welshman/lib"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {pubkey, loadMessagingRelayList} from "@welshman/app"
|
||||
import {app, pubkey} from "@app/welshman"
|
||||
import {MessagingRelayLists} from "@welshman/app"
|
||||
import {fade} from "@lib/transition"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import ProfileName from "@app/components/ProfileName.svelte"
|
||||
@@ -28,7 +29,7 @@
|
||||
|
||||
onMount(() => {
|
||||
for (const pk of others) {
|
||||
loadMessagingRelayList(pk)
|
||||
app.use(MessagingRelayLists).load(pk)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
import {type Instance} from "tippy.js"
|
||||
import {hash, formatTimestampAsTime} from "@welshman/lib"
|
||||
import type {TrustedEvent, EventContent} from "@welshman/util"
|
||||
import {thunks, mergeThunks, pubkey, deriveProfileDisplay, sendWrapped} from "@welshman/app"
|
||||
import {app, thunks, pubkey} from "@app/welshman"
|
||||
import {Thunks, Profiles, Wraps} from "@welshman/app"
|
||||
import {isMobile} from "@lib/html"
|
||||
import MenuDots from "@assets/icons/menu-dots.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
@@ -33,18 +34,18 @@
|
||||
const {event, replyTo, canEdit, onEdit, pubkeys, showPubkey = false}: Props = $props()
|
||||
|
||||
const isOwn = event.pubkey === $pubkey
|
||||
const profileDisplay = deriveProfileDisplay(event.pubkey)
|
||||
const thunk = mergeThunks($thunks.filter(t => t.event.id === event.id))
|
||||
const profileDisplay = app.use(Profiles).display(event.pubkey).$
|
||||
const thunk = app.use(Thunks).merge($thunks.filter(t => t.event.id === event.id))
|
||||
const [_, colorValue] = colors[hash(event.pubkey) % colors.length]
|
||||
|
||||
const reply = () => replyTo(event)
|
||||
const edit = canEdit?.(event) ? () => onEdit?.(event) : undefined
|
||||
|
||||
const deleteReaction = (event: TrustedEvent) =>
|
||||
sendWrapped({event: makeDelete({event, protect: false}), recipients: pubkeys, pow: 16})
|
||||
app.use(Wraps).publish({event: makeDelete({event, protect: false}), recipients: pubkeys, pow: 16})
|
||||
|
||||
const createReaction = (template: EventContent) =>
|
||||
sendWrapped({
|
||||
app.use(Wraps).publish({
|
||||
event: makeReaction({event, protect: false, ...template}),
|
||||
recipients: pubkeys,
|
||||
pow: 16,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
import type {NativeEmoji} from "emoji-picker-element/shared"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {sendWrapped} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import {Wraps} from "@welshman/app"
|
||||
import SmileCircle from "@assets/icons/smile-circle.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import EmojiButton from "@lib/components/EmojiButton.svelte"
|
||||
@@ -15,7 +16,7 @@
|
||||
const {event, pubkeys}: Props = $props()
|
||||
|
||||
const onEmoji = (emoji: NativeEmoji) =>
|
||||
sendWrapped({
|
||||
app.use(Wraps).publish({
|
||||
event: makeReaction({event, content: emoji.unicode, protect: false}),
|
||||
recipients: pubkeys,
|
||||
pow: 16,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
import type {NativeEmoji} from "emoji-picker-element/shared"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {sendWrapped} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import {Wraps} from "@welshman/app"
|
||||
import SmileCircle from "@assets/icons/smile-circle.svg?dataurl"
|
||||
import Pen from "@assets/icons/pen.svg?dataurl"
|
||||
import Reply from "@assets/icons/reply-2.svg?dataurl"
|
||||
@@ -28,7 +29,7 @@
|
||||
|
||||
const onEmoji = ((event: TrustedEvent, pubkeys: string[], emoji: NativeEmoji) => {
|
||||
history.back()
|
||||
sendWrapped({
|
||||
app.use(Wraps).publish({
|
||||
event: makeReaction({event, content: emoji.unicode, protect: false}),
|
||||
recipients: pubkeys,
|
||||
pow: 16,
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
import {writable} from "svelte/store"
|
||||
import {tryCatch, uniq} from "@welshman/lib"
|
||||
import {fromNostrURI} from "@welshman/util"
|
||||
import {loadMessagingRelayList} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import {MessagingRelayLists} from "@welshman/app"
|
||||
import {preventDefault} from "@lib/html"
|
||||
import Field from "@lib/components/Field.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
@@ -34,7 +35,7 @@
|
||||
let pubkeys: string[] = $state([])
|
||||
|
||||
$effect(() => {
|
||||
pubkeys.forEach(pubkey => loadMessagingRelayList(pubkey))
|
||||
pubkeys.forEach(pubkey => app.use(MessagingRelayLists).load(pubkey))
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import {uniq} from "@welshman/lib"
|
||||
import type {TrustedEvent, EventContent} from "@welshman/util"
|
||||
import {getTagValue, getTagValues, getAddress} from "@welshman/util"
|
||||
import {pubkey} from "@welshman/app"
|
||||
import {pubkey} from "@app/welshman"
|
||||
import Pen2 from "@assets/icons/pen-2.svg?dataurl"
|
||||
import {normalizeTopic} from "@lib/util"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
import type {Snippet} from "svelte"
|
||||
import {removeUndefined, randomId, uniq} from "@welshman/lib"
|
||||
import {makeEvent, CLASSIFIED} from "@welshman/util"
|
||||
import {publishThunk, waitForThunkError} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import {Thunks} from "@welshman/app"
|
||||
import {isMobile, preventDefault} from "@lib/html"
|
||||
import {normalizeTopic} from "@lib/util"
|
||||
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
|
||||
@@ -118,12 +119,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
const classifiedThunk = publishThunk({
|
||||
const classifiedThunk = app.use(Thunks).publish({
|
||||
relays: [url],
|
||||
event: makeEvent(CLASSIFIED, {content, tags}),
|
||||
})
|
||||
|
||||
const error = await waitForThunkError(classifiedThunk)
|
||||
const error = await classifiedThunk.waitForError()
|
||||
|
||||
if (error) {
|
||||
return pushToast({theme: "error", message: error})
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</script>
|
||||
|
||||
<Link
|
||||
class="cv col-2 card2 w-full cursor-pointer"
|
||||
class="cv col-2 card2 bg-alt w-full cursor-pointer shadow-xl"
|
||||
href={makeClassifiedPath(url, getAddress(event))}>
|
||||
{#if title}
|
||||
<div class="flex w-full items-center justify-between gap-2">
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
</script>
|
||||
|
||||
<code
|
||||
class="w-full overflow-auto whitespace-pre rounded bg-neutral px-1 text-neutral-content text-sm"
|
||||
class="w-full overflow-auto whitespace-pre rounded bg-neutral px-1 text-neutral-content"
|
||||
class:block={isBlock}>
|
||||
{value.trim()}
|
||||
</code>
|
||||
|
||||
@@ -77,8 +77,7 @@
|
||||
<span class="loading loading-spinner"></span>
|
||||
</div>
|
||||
{:then preview}
|
||||
<div
|
||||
class="border border-solid border-base-content/20 flex max-w-xl flex-col leading-normal rounded-box">
|
||||
<div class="bg-alt flex max-w-xl flex-col leading-normal">
|
||||
{#if preview.image && !hideImage}
|
||||
<img
|
||||
alt=""
|
||||
@@ -93,7 +92,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{:catch}
|
||||
<p class="border border-solid border-base-content/20 p-12 text-center leading-normal">
|
||||
<p class="bg-alt p-12 text-center leading-normal">
|
||||
Unable to load a preview for {url}
|
||||
</p>
|
||||
{/await}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
tagsFromIMeta,
|
||||
makeBlossomAuthEvent,
|
||||
} from "@welshman/util"
|
||||
import {signer} from "@welshman/app"
|
||||
import {signer} from "@app/welshman"
|
||||
import LinkRound from "@assets/icons/link-round.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
import {removeUndefined} from "@welshman/lib"
|
||||
import type {ProfilePointer} from "@welshman/content"
|
||||
import {deriveProfileDisplay} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import {Profiles} from "@welshman/app"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import ProfileDetail from "@app/components/ProfileDetail.svelte"
|
||||
import {pushModal} from "@app/modal"
|
||||
@@ -13,7 +14,7 @@
|
||||
|
||||
const {value, url}: Props = $props()
|
||||
|
||||
const display = deriveProfileDisplay(value.pubkey, removeUndefined([url]))
|
||||
const display = app.use(Profiles).display(value.pubkey, removeUndefined([url])).$
|
||||
|
||||
const openProfile = () => pushModal(ProfileDetail, {pubkey: value.pubkey, url})
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import {fromNostrURI} from "@welshman/util"
|
||||
import {nthEq} from "@welshman/lib"
|
||||
import {
|
||||
@@ -38,11 +37,10 @@
|
||||
interface Props {
|
||||
event: any
|
||||
trimParent?: boolean
|
||||
singleLine?: boolean
|
||||
url?: string
|
||||
}
|
||||
|
||||
const {event, trimParent = false, singleLine = false, url}: Props = $props()
|
||||
const {event, trimParent = false, url}: Props = $props()
|
||||
|
||||
const fullContent = parse(event)
|
||||
|
||||
@@ -106,18 +104,10 @@
|
||||
</p>
|
||||
</div>
|
||||
{:else}
|
||||
<div
|
||||
class={cx(
|
||||
"overflow-hidden text-ellipsis",
|
||||
singleLine ? "whitespace-nowrap" : "wrap-break-word",
|
||||
)}>
|
||||
<div class="overflow-hidden text-ellipsis wrap-break-word">
|
||||
{#each shortContent as parsed, i}
|
||||
{#if isNewline(parsed)}
|
||||
{#if singleLine}
|
||||
{" "}
|
||||
{:else}
|
||||
<ContentNewline value={parsed.value} />
|
||||
{/if}
|
||||
<ContentNewline value={parsed.value} />
|
||||
{:else if isTopic(parsed)}
|
||||
<ContentTopic value={parsed.value} />
|
||||
{:else if isEmoji(parsed)}
|
||||
|
||||
@@ -53,11 +53,7 @@
|
||||
<NoteContentMinimal trimParent {url} event={$quote} />
|
||||
</div>
|
||||
{:else}
|
||||
<NoteCard
|
||||
noShadow
|
||||
event={$quote}
|
||||
{url}
|
||||
class="border border-solid border-base-content/20 rounded-box p-4">
|
||||
<NoteCard noShadow event={$quote} {url} class="bg-alt rounded-box p-4">
|
||||
<NoteContentMinimal {url} event={$quote} />
|
||||
</NoteCard>
|
||||
{/if}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import type {Writable} from "svelte/store"
|
||||
import type {Instance} from "tippy.js"
|
||||
import {preventDefault} from "@lib/html"
|
||||
import {createSearch} from "@welshman/app"
|
||||
import {createSearch} from "@app/welshman"
|
||||
import {currencyOptions, displayCurrency} from "@lib/currency"
|
||||
import Suggestions from "@lib/components/Suggestions.svelte"
|
||||
import CurrencySuggestion from "@app/components/CurrencySuggestion.svelte"
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
<script lang="ts">
|
||||
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
|
||||
import Spinner from "@lib/components/Spinner.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import Field from "@lib/components/Field.svelte"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Modal from "@lib/components/Modal.svelte"
|
||||
import ModalBody from "@lib/components/ModalBody.svelte"
|
||||
import ModalHeader from "@lib/components/ModalHeader.svelte"
|
||||
import ModalTitle from "@lib/components/ModalTitle.svelte"
|
||||
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
|
||||
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
||||
import InputList from "@lib/components/InputList.svelte"
|
||||
import RelayName from "@app/components/RelayName.svelte"
|
||||
import {setFeaturedContent} from "@app/featured"
|
||||
import {pushToast} from "@app/toast"
|
||||
|
||||
type Props = {
|
||||
url: string
|
||||
initial: string[]
|
||||
}
|
||||
|
||||
const {url, initial}: Props = $props()
|
||||
|
||||
let content = $state([...initial])
|
||||
let loading = $state(false)
|
||||
|
||||
const back = () => history.back()
|
||||
|
||||
const submit = async () => {
|
||||
loading = true
|
||||
|
||||
try {
|
||||
const error = await setFeaturedContent(url, content)
|
||||
|
||||
if (error) {
|
||||
pushToast({theme: "error", message: error})
|
||||
} else {
|
||||
pushToast({message: "Featured content updated!"})
|
||||
back()
|
||||
}
|
||||
} finally {
|
||||
loading = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<Modal>
|
||||
<ModalBody>
|
||||
<ModalHeader>
|
||||
<ModalTitle>Featured Content</ModalTitle>
|
||||
<ModalSubtitle>on <RelayName {url} class="text-primary" /></ModalSubtitle>
|
||||
</ModalHeader>
|
||||
<Field>
|
||||
{#snippet info()}
|
||||
<p>
|
||||
Each entry is shown on the space's About page. Links will be fetched and displayed
|
||||
automatically.
|
||||
</p>
|
||||
{/snippet}
|
||||
{#snippet input()}
|
||||
<InputList bind:value={content} placeholder="URL or nevent...">
|
||||
{#snippet addLabel()}
|
||||
Add content
|
||||
{/snippet}
|
||||
</InputList>
|
||||
{/snippet}
|
||||
</Field>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button class="btn btn-link" onclick={back}>
|
||||
<Icon icon={AltArrowLeft} />
|
||||
Go back
|
||||
</Button>
|
||||
<Button class="btn btn-primary" onclick={submit} disabled={loading}>
|
||||
<Spinner {loading}>Save changes</Spinner>
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
@@ -5,7 +5,7 @@
|
||||
import {load} from "@welshman/net"
|
||||
import {deriveArray, deriveEventsById} from "@welshman/store"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {repository} from "@welshman/app"
|
||||
import {repository} from "@app/welshman"
|
||||
import {deriveChecked} from "@app/notifications"
|
||||
import Reply from "@assets/icons/reply-2.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import {LOCALE, secondsToDate} from "@welshman/lib"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {displayRelayUrl} from "@welshman/util"
|
||||
import {tracker} from "@welshman/app"
|
||||
import {tracker} from "@app/welshman"
|
||||
import FileText from "@assets/icons/file-text.svg?dataurl"
|
||||
import Copy from "@assets/icons/copy.svg?dataurl"
|
||||
import UserCircle from "@assets/icons/user-circle.svg?dataurl"
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
import {goto} from "$app/navigation"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {COMMENT, ManagementMethod} from "@welshman/util"
|
||||
import {pubkey, repository, relaysByUrl, manageRelay} from "@welshman/app"
|
||||
import {app, pubkey, repository, relaysByUrl} from "@app/welshman"
|
||||
import {RelayManagement} from "@welshman/app"
|
||||
import ShareCircle from "@assets/icons/share-circle.svg?dataurl"
|
||||
import Code2 from "@assets/icons/code-2.svg?dataurl"
|
||||
import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl"
|
||||
@@ -56,7 +57,7 @@
|
||||
title: `Delete ${noun}`,
|
||||
message: `Are you sure you want to delete this ${noun.toLowerCase()} from the space?`,
|
||||
confirm: async () => {
|
||||
const {error} = await manageRelay(url, {
|
||||
const {error} = await app.use(RelayManagement).post(url, {
|
||||
method: ManagementMethod.BanEvent,
|
||||
params: [event.id],
|
||||
})
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
import {writable} from "svelte/store"
|
||||
import {makeEvent, ZAP_GOAL} from "@welshman/util"
|
||||
import {publishThunk, waitForThunkError} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import {Thunks} from "@welshman/app"
|
||||
import {isMobile, preventDefault} from "@lib/html"
|
||||
import Paperclip from "@assets/icons/paperclip-2.svg?dataurl"
|
||||
import Bolt from "@assets/icons/bolt.svg?dataurl"
|
||||
@@ -93,12 +94,12 @@
|
||||
tags.push(["h", h])
|
||||
}
|
||||
|
||||
const goalThunk = publishThunk({
|
||||
const goalThunk = app.use(Thunks).publish({
|
||||
relays: [url],
|
||||
event: makeEvent(ZAP_GOAL, {content: title, tags}),
|
||||
})
|
||||
|
||||
const error = await waitForThunkError(goalThunk)
|
||||
const error = await goalThunk.waitForError()
|
||||
|
||||
if (error) {
|
||||
return pushToast({theme: "error", message: error})
|
||||
|
||||
@@ -20,7 +20,9 @@
|
||||
const h = getTagValue("h", event.tags)
|
||||
</script>
|
||||
|
||||
<Link class="cv col-2 card2 w-full cursor-pointer" href={makeGoalPath(url, event.id)}>
|
||||
<Link
|
||||
class="cv col-2 card2 bg-alt w-full cursor-pointer shadow-md"
|
||||
href={makeGoalPath(url, event.id)}>
|
||||
<p class="text-2xl">{event.content}</p>
|
||||
<Content
|
||||
event={{content: summary, tags: event.tags}}
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
import {now, DAY, uniq, sum} from "@welshman/lib"
|
||||
import type {Zap, TrustedEvent} from "@welshman/util"
|
||||
import {getTagValue, fromMsats, ZAP_RESPONSE} from "@welshman/util"
|
||||
import {deriveItemsByKey, deriveArray} from "@welshman/store"
|
||||
import {repository, getValidZap} from "@welshman/app"
|
||||
import {derived} from "svelte/store"
|
||||
import {deriveEvents} from "@welshman/store"
|
||||
import {app, repository} from "@app/welshman"
|
||||
import {Zappers} from "@welshman/app"
|
||||
import Bolt from "@assets/icons/bolt.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import ZapButton from "@app/components/ZapButton.svelte"
|
||||
@@ -16,13 +18,15 @@
|
||||
|
||||
const {url, event, ...props}: Props = $props()
|
||||
|
||||
const zaps = deriveArray(
|
||||
deriveItemsByKey<Zap>({
|
||||
repository,
|
||||
getKey: zap => zap.response.id,
|
||||
filters: [{kinds: [ZAP_RESPONSE], "#e": [event.id]}],
|
||||
eventToItem: (response: TrustedEvent) => getValidZap(response, event),
|
||||
}),
|
||||
// Validated zaps for this goal. `validZapReceipts` is a reactive Projection
|
||||
// (resolves recipient zappers from loaded profiles); we re-derive it whenever
|
||||
// the set of ZAP_RESPONSE events in the repository changes.
|
||||
const zapReceipts = deriveEvents({repository, filters: [{kinds: [ZAP_RESPONSE], "#e": [event.id]}]})
|
||||
const zaps = derived(
|
||||
zapReceipts,
|
||||
($receipts: TrustedEvent[], set) =>
|
||||
app.use(Zappers).validZapReceipts($receipts, event).$.subscribe(set),
|
||||
[] as Zap[],
|
||||
)
|
||||
|
||||
const goalAmount = parseInt(getTagValue("amount", event.tags) || "0")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import {createSearch} from "@welshman/app"
|
||||
import {createSearch} from "@app/welshman"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Magnifier from "@assets/icons/magnifier.svg?dataurl"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import {session} from "@welshman/app"
|
||||
import {session} from "@app/welshman"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
|
||||
import CheckCircle from "@assets/icons/check-circle.svg?dataurl"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import {deriveZapperForPubkey} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import {Zappers} from "@welshman/app"
|
||||
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
@@ -12,7 +13,7 @@
|
||||
|
||||
const {pubkey} = $props()
|
||||
|
||||
const zapper = deriveZapperForPubkey(pubkey)
|
||||
const zapper = app.use(Zappers).forPubkey(pubkey).$
|
||||
|
||||
const back = () => history.back()
|
||||
</script>
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
<script lang="ts">
|
||||
import {Client} from "@pomade/core"
|
||||
import {getPubkey} from "@welshman/util"
|
||||
import type {SessionPomade} from "@welshman/app"
|
||||
import {session} from "@welshman/app"
|
||||
import {session} from "@app/welshman"
|
||||
// TODO(welshman-migration): `SessionPomade` was removed from @welshman/app; the
|
||||
// new generic Session nests its descriptor under `.data` ({clientOptions, email}),
|
||||
// whereas this code destructures `email`/`clientOptions` from the top level.
|
||||
// Confirm whether flotilla's FlotillaSession still surfaces these at the top
|
||||
// level (loginWithPomade stores them under `.data` via toSession) and adjust the
|
||||
// destructuring accordingly. Local type kept loose to avoid a broken import.
|
||||
type SessionPomade = {email: string; clientOptions: {secret: string; peers: any}}
|
||||
import {preventDefault} from "@lib/html"
|
||||
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
|
||||
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
<script lang="ts">
|
||||
import {Client} from "@pomade/core"
|
||||
import type {SessionPomade} from "@welshman/app"
|
||||
import {session} from "@welshman/app"
|
||||
import {session} from "@app/welshman"
|
||||
// TODO(welshman-migration): `SessionPomade` was removed from @welshman/app; the
|
||||
// new generic Session nests its descriptor under `.data` ({clientOptions, email}),
|
||||
// whereas this code destructures from the top level. Confirm whether flotilla's
|
||||
// FlotillaSession still surfaces these at the top level and adjust accordingly.
|
||||
// Local type kept loose to avoid a broken import.
|
||||
type SessionPomade = {email: string; clientOptions: {peers: any}}
|
||||
import {preventDefault} from "@lib/html"
|
||||
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
|
||||
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import {onMount} from "svelte"
|
||||
import {Capacitor} from "@capacitor/core"
|
||||
import {getNip07, getNip55, Nip55Signer} from "@welshman/signer"
|
||||
import {addSession, type Session, makeNip07Session, makeNip55Session} from "@welshman/app"
|
||||
import {addSession, type FlotillaSession, makeNip07Session, makeNip55Session} from "@app/welshman"
|
||||
import Widget from "@assets/icons/widget-4.svg?dataurl"
|
||||
import Letter from "@assets/icons/letter.svg?dataurl"
|
||||
import Cpu from "@assets/icons/cpu-bolt.svg?dataurl"
|
||||
@@ -32,8 +32,8 @@
|
||||
|
||||
const signUp = () => pushModal(SignUp)
|
||||
|
||||
const onSuccess = async (session: Session) => {
|
||||
addSession(session)
|
||||
const onSuccess = async (session: FlotillaSession, pubkey: string) => {
|
||||
addSession({...session, pubkey})
|
||||
setChecked("*")
|
||||
clearModals()
|
||||
}
|
||||
@@ -45,7 +45,7 @@
|
||||
const pubkey = await getNip07()?.getPublicKey()
|
||||
|
||||
if (pubkey) {
|
||||
await onSuccess(makeNip07Session(pubkey))
|
||||
await onSuccess(makeNip07Session(pubkey), pubkey)
|
||||
} else {
|
||||
pushToast({
|
||||
theme: "error",
|
||||
@@ -65,7 +65,7 @@
|
||||
const pubkey = await signer.getPubkey()
|
||||
|
||||
if (pubkey) {
|
||||
await onSuccess(makeNip55Session(pubkey, app.packageName))
|
||||
await onSuccess(makeNip55Session(pubkey, app.packageName), pubkey)
|
||||
} else {
|
||||
pushToast({
|
||||
theme: "error",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import type {Nip46ResponseWithResult} from "@welshman/signer"
|
||||
import {Nip46Broker} from "@welshman/signer"
|
||||
import {makeSecret} from "@welshman/util"
|
||||
import {loginWithNip01, loginWithNip46} from "@welshman/app"
|
||||
import {loginWithNip01, loginWithNip46} from "@app/welshman"
|
||||
import {preventDefault} from "@lib/html"
|
||||
import Spinner from "@lib/components/Spinner.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import {bytesToHex} from "@welshman/lib"
|
||||
import {loginWithNip01} from "@welshman/app"
|
||||
import {loginWithNip01} from "@app/welshman"
|
||||
import {decrypt} from "nostr-tools/nip49"
|
||||
import {preventDefault} from "@lib/html"
|
||||
import {nsecDecode} from "@lib/util"
|
||||
@@ -56,7 +56,7 @@
|
||||
})
|
||||
}
|
||||
|
||||
loginWithNip01(secret)
|
||||
await loginWithNip01(secret)
|
||||
setChecked("*")
|
||||
clearModals()
|
||||
} catch (e) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import {Capacitor} from "@capacitor/core"
|
||||
import {pubkey} from "@welshman/app"
|
||||
import {pubkey} from "@app/welshman"
|
||||
import Server from "@assets/icons/server.svg?dataurl"
|
||||
import GalleryMinimalistic from "@assets/icons/gallery-minimalistic.svg?dataurl"
|
||||
import Shield from "@assets/icons/shield-minimalistic.svg?dataurl"
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
import {sum} from "@welshman/lib"
|
||||
import type {Zap, TrustedEvent} from "@welshman/util"
|
||||
import {getTagValue, fromMsats, ZAP_RESPONSE} from "@welshman/util"
|
||||
import {deriveItemsByKey, deriveArray} from "@welshman/store"
|
||||
import {repository, getValidZap} from "@welshman/app"
|
||||
import {derived} from "svelte/store"
|
||||
import {deriveEvents} from "@welshman/store"
|
||||
import {app, repository} from "@app/welshman"
|
||||
import {Zappers} from "@welshman/app"
|
||||
import Bolt from "@assets/icons/bolt.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import ContentMinimal from "@app/components/ContentMinimal.svelte"
|
||||
@@ -14,13 +16,14 @@
|
||||
const content = getTagValue("summary", props.event.tags)
|
||||
const fakeEvent = {content, tags: props.event.tags}
|
||||
|
||||
const zaps = deriveArray(
|
||||
deriveItemsByKey<Zap>({
|
||||
repository,
|
||||
getKey: zap => zap.response.id,
|
||||
filters: [{kinds: [ZAP_RESPONSE], "#e": [props.event.id]}],
|
||||
eventToItem: (response: TrustedEvent) => getValidZap(response, props.event),
|
||||
}),
|
||||
// Validated zaps for this goal (reactive Projection, re-derived as the set of
|
||||
// ZAP_RESPONSE events in the repository changes).
|
||||
const zapReceipts = deriveEvents({repository, filters: [{kinds: [ZAP_RESPONSE], "#e": [props.event.id]}]})
|
||||
const zaps = derived(
|
||||
zapReceipts,
|
||||
($receipts: TrustedEvent[], set) =>
|
||||
app.use(Zappers).validZapReceipts($receipts, props.event).$.subscribe(set),
|
||||
[] as Zap[],
|
||||
)
|
||||
|
||||
const goalAmount = parseInt(getTagValue("amount", props.event.tags) || "0")
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
})
|
||||
</script>
|
||||
|
||||
<NoteCard {event} {url} class="cv card2">
|
||||
<NoteCard {event} {url} class="cv card2 bg-alt">
|
||||
<NoteContent {event} expandMode="inline" />
|
||||
<div class="flex w-full justify-between gap-2">
|
||||
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="tooltip-right">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import {Client} from "@pomade/core"
|
||||
import type {SessionPomade} from "@welshman/app"
|
||||
import {session} from "@welshman/app"
|
||||
import {session} from "@app/welshman"
|
||||
import {preventDefault} from "@lib/html"
|
||||
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
|
||||
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
<script lang="ts">
|
||||
import {Client} from "@pomade/core"
|
||||
import {session} from "@welshman/app"
|
||||
import type {SessionPomade} from "@welshman/app"
|
||||
import {session} from "@app/welshman"
|
||||
// TODO(welshman-migration): `SessionPomade` was removed from @welshman/app; the
|
||||
// new generic Session nests its descriptor under `.data` ({clientOptions, email}),
|
||||
// whereas this code destructures `email` from the top level. Confirm whether
|
||||
// flotilla's FlotillaSession still surfaces `email` at the top level and adjust.
|
||||
// Local type kept loose to avoid a broken import.
|
||||
type SessionPomade = {email: string}
|
||||
import {preventDefault} from "@lib/html"
|
||||
import Key from "@assets/icons/key.svg?dataurl"
|
||||
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
import {insertAt, now, randomId, removeAt, removeUndefined} from "@welshman/lib"
|
||||
import {makeEvent, POLL} from "@welshman/util"
|
||||
import {publishThunk, waitForThunkError} from "@welshman/app"
|
||||
import {Thunks} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import {isMobile, preventDefault} from "@lib/html"
|
||||
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
|
||||
import HamburgerMenu from "@assets/icons/hamburger-menu.svg?dataurl"
|
||||
@@ -142,12 +143,12 @@
|
||||
tags.push(PROTECTED)
|
||||
}
|
||||
|
||||
const pollThunk = publishThunk({
|
||||
const pollThunk = app.use(Thunks).publish({
|
||||
relays: [url],
|
||||
event: makeEvent(POLL, {content: title.trim(), tags}),
|
||||
})
|
||||
|
||||
const error = await waitForThunkError(pollThunk)
|
||||
const error = await pollThunk.waitForError()
|
||||
|
||||
if (error) {
|
||||
return pushToast({theme: "error", message: error})
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
import {onDestroy} from "svelte"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {POLL_RESPONSE} from "@welshman/util"
|
||||
import {pubkey, publishThunk, abortThunk} from "@welshman/app"
|
||||
import type {Thunk} from "@welshman/app"
|
||||
import {Thunks} from "@welshman/app"
|
||||
import {pubkey, app} from "@app/welshman"
|
||||
import {formatTimestampRelative} from "@welshman/lib"
|
||||
import {deriveEvents} from "@app/repository"
|
||||
import {pushToast} from "@app/toast"
|
||||
@@ -50,7 +52,7 @@
|
||||
|
||||
const publishSelection = (selection: string[]) => {
|
||||
if (activeThunk) {
|
||||
abortThunk(activeThunk)
|
||||
activeThunk.abort()
|
||||
}
|
||||
|
||||
if (selection.length === 0) {
|
||||
@@ -58,7 +60,7 @@
|
||||
return
|
||||
}
|
||||
|
||||
activeThunk = publishThunk({
|
||||
activeThunk = app.use(Thunks).publish({
|
||||
relays: [url],
|
||||
event: makePollResponse({event, selectedIds: selection}),
|
||||
delay: publishDelay,
|
||||
@@ -92,7 +94,7 @@
|
||||
}
|
||||
|
||||
let selectedIds = $state<string[]>([])
|
||||
let activeThunk: ReturnType<typeof publishThunk> | undefined
|
||||
let activeThunk: Thunk | undefined
|
||||
|
||||
$effect(() => {
|
||||
if (ownResponse) {
|
||||
@@ -102,7 +104,7 @@
|
||||
|
||||
onDestroy(() => {
|
||||
if (activeThunk) {
|
||||
abortThunk(activeThunk)
|
||||
activeThunk.abort()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import {onMount} from "svelte"
|
||||
import {Client} from "@pomade/core"
|
||||
import {session, isPomadeSession} from "@welshman/app"
|
||||
import {session, isPomadeSession} from "@app/welshman"
|
||||
import MenuDots from "@assets/icons/menu-dots.svg?dataurl"
|
||||
import {fly} from "@lib/transition"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type {Snippet} from "svelte"
|
||||
import {userProfile} from "@welshman/app"
|
||||
import {userProfile} from "@app/welshman"
|
||||
import Letter from "@assets/icons/letter.svg?dataurl"
|
||||
import Magnifier from "@assets/icons/magnifier.svg?dataurl"
|
||||
import Widget from "@assets/icons/widget-4.svg?dataurl"
|
||||
@@ -33,7 +33,7 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="ml-sai mt-sai mb-sai relative z-popover isolate hidden w-14 shrink-0 bg-base-200 pt-2 md:block border-r border-solid border-base-content/15 dark:border-base-content/10">
|
||||
class="ml-sai mt-sai mb-sai relative z-popover isolate hidden w-14 shrink-0 bg-base-200 pt-2 md:block">
|
||||
<div class="flex h-full flex-col" class:justify-between={PLATFORM_RELAYS.length === 0}>
|
||||
<PrimaryNavSpaces />
|
||||
{#if PLATFORM_RELAYS.length > 0}
|
||||
@@ -41,8 +41,8 @@
|
||||
{/if}
|
||||
<div class="flex flex-col">
|
||||
<PrimaryNavItem title="Settings" href="/settings/profile" prefix="/settings">
|
||||
{#if $userProfile?.picture}
|
||||
<ImageIcon alt="Settings" src={$userProfile?.picture} class="rounded-full" size={10} />
|
||||
{#if $userProfile?.picture()}
|
||||
<ImageIcon alt="Settings" src={$userProfile?.picture()} class="rounded-full" size={10} />
|
||||
{:else}
|
||||
<ImageIcon alt="Settings" src={UserRounded} class="rounded-full" size={8} />
|
||||
{/if}
|
||||
@@ -86,8 +86,8 @@
|
||||
{/if}
|
||||
</div>
|
||||
<PrimaryNavItem title="Settings" onclick={showSettingsMenu}>
|
||||
{#if $userProfile?.picture}
|
||||
<ImageIcon alt="Settings" src={$userProfile?.picture} size={10} class="rounded-full" />
|
||||
{#if $userProfile?.picture()}
|
||||
<ImageIcon alt="Settings" src={$userProfile?.picture()} size={10} class="rounded-full" />
|
||||
{:else}
|
||||
<ImageIcon alt="Settings" src={Settings} size={8} class="rounded-full" />
|
||||
{/if}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import {deriveRelayDisplay} from "@welshman/app"
|
||||
import {Relays} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import PrimaryNavItem from "@lib/components/PrimaryNavItem.svelte"
|
||||
import RelayIcon from "@app/components/RelayIcon.svelte"
|
||||
import {makeSpacePath, goToSpace} from "@app/routes"
|
||||
@@ -15,7 +16,7 @@
|
||||
|
||||
const path = makeSpacePath(url)
|
||||
|
||||
const display = $derived(deriveRelayDisplay(url))
|
||||
const display = $derived(app.use(Relays).display(url).$)
|
||||
</script>
|
||||
|
||||
<PrimaryNavItem
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<script lang="ts">
|
||||
import * as nip19 from "nostr-tools/nip19"
|
||||
import {removeUndefined} from "@welshman/lib"
|
||||
import {displayPubkey} from "@welshman/util"
|
||||
import {deriveHandleForPubkey, displayHandle, deriveProfileDisplay} from "@welshman/app"
|
||||
import {displayPubkey, displayNip05} from "@welshman/util"
|
||||
import {Handles, Profiles} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import ProfileCircle from "@app/components/ProfileCircle.svelte"
|
||||
@@ -23,8 +24,8 @@
|
||||
const {pubkey, url, showPubkey, inert, avatarSize = 10}: Props = $props()
|
||||
|
||||
const relays = removeUndefined([url])
|
||||
const profileDisplay = deriveProfileDisplay(pubkey, relays)
|
||||
const handle = deriveHandleForPubkey(pubkey)
|
||||
const profileDisplay = app.use(Profiles).display(pubkey, relays).$
|
||||
const handle = app.use(Handles).forPubkey(pubkey).$
|
||||
|
||||
const openProfile = () => {
|
||||
pushModal(ProfileDetail, {pubkey, url})
|
||||
@@ -33,7 +34,7 @@
|
||||
const copyPubkey = () => clip(nip19.npubEncode(pubkey))
|
||||
</script>
|
||||
|
||||
<div class="flex max-w-full items-start gap-2">
|
||||
<div class="flex max-w-full items-start gap-3">
|
||||
{#if inert}
|
||||
<span class="py-1">
|
||||
<ProfileCircle {pubkey} size={avatarSize} />
|
||||
@@ -46,7 +47,7 @@
|
||||
<div class="flex min-w-0 flex-col">
|
||||
<div class="flex items-center gap-2">
|
||||
{#if inert}
|
||||
<span class="text-bold overflow-hidden text-ellipsis whitespace-nowrap">
|
||||
<span class="text-bold overflow-hidden text-ellipsis">
|
||||
{$profileDisplay}
|
||||
</span>
|
||||
{:else}
|
||||
@@ -58,7 +59,7 @@
|
||||
</div>
|
||||
{#if $handle}
|
||||
<div class="overflow-hidden text-ellipsis text-sm opacity-75">
|
||||
{displayHandle($handle)}
|
||||
{displayNip05($handle?.nip05)}
|
||||
</div>
|
||||
{/if}
|
||||
{#if showPubkey}
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
import {deriveEventsDesc, deriveEventsById} from "@welshman/store"
|
||||
import {formatTimestampRelative} from "@welshman/lib"
|
||||
import {NOTE, ROOMS, COMMENT, MESSAGE} from "@welshman/util"
|
||||
import {repository, loadRelayList} from "@welshman/app"
|
||||
import {RelayLists} from "@welshman/app"
|
||||
import {repository, app} from "@app/welshman"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import ProfileSpaces from "@app/components/ProfileSpaces.svelte"
|
||||
import {deriveGroupList, getSpaceUrlsFromGroupList} from "@app/groups"
|
||||
@@ -30,7 +31,7 @@
|
||||
|
||||
onMount(async () => {
|
||||
// Make sure we have their relay selections before we load their posts
|
||||
await loadRelayList(pubkey)
|
||||
await app.use(RelayLists).load(pubkey)
|
||||
|
||||
// Load groups and at least one note, regardless of time frame
|
||||
load({
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import {removeUndefined} from "@welshman/lib"
|
||||
import {deriveProfile} from "@welshman/app"
|
||||
import {Profiles} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import UserRounded from "@assets/icons/user-rounded.svg?dataurl"
|
||||
import ImageIcon from "@lib/components/ImageIcon.svelte"
|
||||
|
||||
@@ -14,11 +15,11 @@
|
||||
|
||||
const {pubkey, url, size = 7, ...props}: Props = $props()
|
||||
|
||||
const profile = deriveProfile(pubkey, removeUndefined([url]))
|
||||
const profile = app.use(Profiles).one(pubkey, removeUndefined([url]))
|
||||
</script>
|
||||
|
||||
<ImageIcon
|
||||
{size}
|
||||
alt=""
|
||||
class={cx(props.class, "rounded-full")}
|
||||
src={$profile?.picture || UserRounded} />
|
||||
src={$profile?.picture() || UserRounded} />
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import {getProfile, loadProfile} from "@welshman/app"
|
||||
import {Profiles} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import {isMobile} from "@lib/html"
|
||||
import ProfileCircle from "@app/components/ProfileCircle.svelte"
|
||||
|
||||
@@ -23,11 +24,11 @@
|
||||
)
|
||||
|
||||
for (const pubkey of pubkeys) {
|
||||
loadProfile(pubkey)
|
||||
app.use(Profiles).load(pubkey)
|
||||
}
|
||||
|
||||
const visiblePubkeys = $derived.by(() => {
|
||||
const filtered = pubkeys.filter(pubkey => getProfile(pubkey)?.picture)
|
||||
const filtered = pubkeys.filter(pubkey => app.use(Profiles).get(pubkey)?.picture())
|
||||
|
||||
return filtered.length > 0 ? filtered : pubkeys.slice(0, 1)
|
||||
})
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
<script lang="ts">
|
||||
import {chunk, sleep, uniq} from "@welshman/lib"
|
||||
import {
|
||||
makeEvent,
|
||||
createProfile,
|
||||
PROFILE,
|
||||
DELETE,
|
||||
isReplaceable,
|
||||
getAddress,
|
||||
RelayMode,
|
||||
} from "@welshman/util"
|
||||
import {pubkey, publishThunk, repository, derivePubkeyRelays} from "@welshman/app"
|
||||
import {makeEvent, DELETE, isReplaceable, getAddress} from "@welshman/util"
|
||||
import {ProfileBuilder} from "@welshman/domain"
|
||||
import {Thunks, RelayLists} from "@welshman/app"
|
||||
import {pubkey, repository, app} from "@app/welshman"
|
||||
import {preventDefault} from "@lib/html"
|
||||
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
|
||||
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
|
||||
@@ -31,7 +25,7 @@
|
||||
let confirmText = $state("")
|
||||
|
||||
const CONFIRM_TEXT = "permanently delete my nostr account"
|
||||
const userWriteRelays = derivePubkeyRelays($pubkey!, RelayMode.Write)
|
||||
const userWriteRelays = app.use(RelayLists).writeUrls($pubkey!).$
|
||||
const confirmOk = $derived(confirmText.toLowerCase().trim() === CONFIRM_TEXT)
|
||||
const showProgress = $derived(progress !== undefined)
|
||||
|
||||
@@ -44,7 +38,7 @@
|
||||
}
|
||||
|
||||
const chunks = chunk(500, repository.query([{authors: [$pubkey!]}]))
|
||||
const profileEvent = makeEvent(PROFILE, createProfile({name: "[deleted]"}))
|
||||
const profileEvent = await new ProfileBuilder().update({name: "[deleted]"}).toTemplate()
|
||||
const vanishEvent = makeEvent(62, {tags: [["relay", "ALL_RELAYS"]]})
|
||||
const denominator = chunks.length + 2
|
||||
const relays = uniq([...INDEXER_RELAYS, ...$userWriteRelays, ...$userSpaceUrls])
|
||||
@@ -58,12 +52,12 @@
|
||||
}
|
||||
|
||||
// First, blank out their profile in case relays don't support deletion by address
|
||||
await publishThunk({relays, event: profileEvent})
|
||||
await app.use(Thunks).publish({relays, event: profileEvent})
|
||||
|
||||
await incrementProgress()
|
||||
|
||||
// Next, send a "right to vanish" event to all relays
|
||||
await publishThunk({relays, event: vanishEvent})
|
||||
await app.use(Thunks).publish({relays, event: vanishEvent})
|
||||
|
||||
await incrementProgress()
|
||||
|
||||
@@ -79,7 +73,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
await publishThunk({relays, event: makeEvent(DELETE, {tags})})
|
||||
await app.use(Thunks).publish({relays, event: makeEvent(DELETE, {tags})})
|
||||
|
||||
await incrementProgress()
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<script lang="ts">
|
||||
import {onMount} from "svelte"
|
||||
import {removeUndefined} from "@welshman/lib"
|
||||
import {deriveProfile, displayProfileByPubkey, loadMessagingRelayList} from "@welshman/app"
|
||||
import {ManagementMethod} from "@welshman/util"
|
||||
import {RelayManagement, Profiles, MessagingRelayLists} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
|
||||
import Code2 from "@assets/icons/code-2.svg?dataurl"
|
||||
import Letter from "@assets/icons/letter-opened.svg?dataurl"
|
||||
@@ -23,12 +25,7 @@
|
||||
import EventInfo from "@app/components/EventInfo.svelte"
|
||||
import ProfileBadges from "@app/components/ProfileBadges.svelte"
|
||||
import {pubkeyLink} from "@app/env"
|
||||
import {
|
||||
deriveUserIsSpaceAdmin,
|
||||
deriveSpaceBannedPubkeyItems,
|
||||
addSpaceMembers,
|
||||
banSpaceMembers,
|
||||
} from "@app/members"
|
||||
import {deriveUserIsSpaceAdmin, deriveSpaceBannedPubkeyItems, addSpaceMembers} from "@app/members"
|
||||
import {pushModal} from "@app/modal"
|
||||
import {pushToast} from "@app/toast"
|
||||
import {goToChat} from "@app/routes"
|
||||
@@ -40,7 +37,7 @@
|
||||
|
||||
const {pubkey, url}: Props = $props()
|
||||
|
||||
const profile = deriveProfile(pubkey, removeUndefined([url]))
|
||||
const profile = app.use(Profiles).one(pubkey, removeUndefined([url]))
|
||||
|
||||
const userIsAdmin = deriveUserIsSpaceAdmin(url)
|
||||
|
||||
@@ -65,9 +62,12 @@
|
||||
const banMember = () =>
|
||||
pushModal(Confirm, {
|
||||
title: "Ban User",
|
||||
message: `Are you sure you want to ban @${displayProfileByPubkey(pubkey)} from the space?`,
|
||||
message: `Are you sure you want to ban @${app.use(Profiles).display(pubkey).get()} from the space?`,
|
||||
confirm: async () => {
|
||||
const error = await banSpaceMembers(url!, [pubkey])
|
||||
const {error} = await app.use(RelayManagement).post(url!, {
|
||||
method: ManagementMethod.BanPubkey,
|
||||
params: [pubkey],
|
||||
})
|
||||
|
||||
if (error) {
|
||||
pushToast({theme: "error", message: error})
|
||||
@@ -92,7 +92,7 @@
|
||||
let showMenu = $state(false)
|
||||
|
||||
onMount(() => {
|
||||
loadMessagingRelayList(pubkey)
|
||||
app.use(MessagingRelayLists).load(pubkey)
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type {Profile} from "@welshman/util"
|
||||
import {makeProfile} from "@welshman/util"
|
||||
import {pubkey, profilesByPubkey, waitForThunkError} from "@welshman/app"
|
||||
import {Profile, ProfileBuilder} from "@welshman/domain"
|
||||
import {pubkey, profilesByPubkey} from "@app/welshman"
|
||||
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
|
||||
import {errorMessage} from "@lib/util"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
@@ -12,16 +11,28 @@
|
||||
import {pushToast} from "@app/toast"
|
||||
import {updateProfile} from "@app/profiles"
|
||||
|
||||
const profile = $profilesByPubkey.get($pubkey!) || makeProfile()
|
||||
// The edit form binds to plain mutable fields (name/about/nip05/picture), so we
|
||||
// hand it a plain values object rather than a Profile Reader. A Reader exposes its
|
||||
// raw parsed content as `.values`; a fresh profile starts from an empty builder.
|
||||
const reader = $profilesByPubkey.get($pubkey!)
|
||||
const profile = reader instanceof Profile ? {...reader.values} : new ProfileBuilder().update({}).values
|
||||
const initialValues = {profile}
|
||||
|
||||
const back = () => history.back()
|
||||
|
||||
// TODO(welshman-migration): `profile` here is a plain values object (the form binds
|
||||
// mutable fields), not a Profile Reader. It is typed Profile to match ProfileEditForm's
|
||||
// Values type and updateProfile's signature, both of which still say Profile; updateProfile
|
||||
// routes a non-Reader through `new ProfileBuilder().update(profile)`. Confirm the intended
|
||||
// values vs Reader contract once the shared types settle.
|
||||
const onsubmit = async ({profile}: {profile: Profile}) => {
|
||||
loading = true
|
||||
|
||||
try {
|
||||
const error = await waitForThunkError(updateProfile({profile}))
|
||||
// TODO(welshman-migration): updateProfile is async (returns Promise<Thunk>); the old
|
||||
// waitForThunkError shim did not await its arg. Awaiting the thunk first before
|
||||
// .waitForError() — confirm this matches intended behavior.
|
||||
const error = await (await updateProfile({profile})).waitForError()
|
||||
|
||||
if (error) {
|
||||
pushToast({
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
import {feedFromFilter, makeIntersectionFeed, makeRelayFeed} from "@welshman/feeds"
|
||||
import {NOTE, getReplyTags} from "@welshman/util"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {makeFeedController} from "@welshman/app"
|
||||
import {Feeds} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import {createScroller} from "@lib/html"
|
||||
import {fly} from "@lib/transition"
|
||||
import Spinner from "@lib/components/Spinner.svelte"
|
||||
@@ -19,7 +20,7 @@
|
||||
|
||||
let {url, pubkey, events = $bindable([]), hideLoading = false}: Props = $props()
|
||||
|
||||
const ctrl = makeFeedController({
|
||||
const ctrl = app.use(Feeds).makeFeedController({
|
||||
useWindowing: true,
|
||||
feed: makeIntersectionFeed(
|
||||
makeRelayFeed(url),
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<script lang="ts">
|
||||
import {removeUndefined} from "@welshman/lib"
|
||||
import {deriveProfile} from "@welshman/app"
|
||||
import {Profiles} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import ContentMinimal from "@app/components/ContentMinimal.svelte"
|
||||
|
||||
export type Props = {
|
||||
pubkey: string
|
||||
singleLine?: boolean
|
||||
url?: string
|
||||
}
|
||||
|
||||
const {pubkey, url, singleLine}: Props = $props()
|
||||
const {pubkey, url}: Props = $props()
|
||||
|
||||
const profile = deriveProfile(pubkey, removeUndefined([url]))
|
||||
const profile = app.use(Profiles).one(pubkey, removeUndefined([url]))
|
||||
</script>
|
||||
|
||||
{#if $profile}
|
||||
<ContentMinimal event={{content: $profile.about || "", tags: []}} {singleLine} />
|
||||
<ContentMinimal event={{content: $profile.about() || "", tags: []}} />
|
||||
{/if}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import type {Writable} from "svelte/store"
|
||||
import {type Instance} from "tippy.js"
|
||||
import {append, remove, uniq} from "@welshman/lib"
|
||||
import {profileSearch} from "@welshman/app"
|
||||
import {profileSearch} from "@app/welshman"
|
||||
import Suggestions from "@lib/components/Suggestions.svelte"
|
||||
import CloseCircle from "@assets/icons/close-circle.svg?dataurl"
|
||||
import Magnifier from "@assets/icons/magnifier.svg?dataurl"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import {removeUndefined} from "@welshman/lib"
|
||||
import {deriveProfileDisplay} from "@welshman/app"
|
||||
import {Profiles} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
|
||||
type Props = {
|
||||
pubkey: string
|
||||
@@ -9,7 +10,7 @@
|
||||
|
||||
const {pubkey, url}: Props = $props()
|
||||
|
||||
const profileDisplay = deriveProfileDisplay(pubkey, removeUndefined([url]))
|
||||
const profileDisplay = app.use(Profiles).display(pubkey, removeUndefined([url])).$
|
||||
</script>
|
||||
|
||||
{$profileDisplay}
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
import type {TrustedEvent, EventContent, Zap} from "@welshman/util"
|
||||
import {deriveArray, deriveEventsById, deriveItemsByKey} from "@welshman/store"
|
||||
import {load} from "@welshman/net"
|
||||
import {pubkey, repository, getValidZap, displayProfileByPubkey} from "@welshman/app"
|
||||
import {Zappers, Profiles} from "@welshman/app"
|
||||
import {pubkey, repository, app} from "@app/welshman"
|
||||
import {isMobile, preventDefault, stopPropagation} from "@lib/html"
|
||||
import Danger from "@assets/icons/danger-triangle.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
@@ -64,15 +65,15 @@
|
||||
repository,
|
||||
getKey: zap => zap.response.id,
|
||||
filters: [{kinds: [ZAP_RESPONSE], "#e": eventIds}],
|
||||
eventToItem: (response: TrustedEvent) => {
|
||||
const zap = getValidZap(response, event)
|
||||
eventToItem: async (response: TrustedEvent) => {
|
||||
const zap = await app.use(Zappers).validateZapReceipt(response, event)
|
||||
|
||||
if (zap) {
|
||||
return zap
|
||||
}
|
||||
|
||||
if (innerEvent) {
|
||||
return getValidZap(response, innerEvent)
|
||||
return await app.use(Zappers).validateZapReceipt(response, innerEvent)
|
||||
}
|
||||
},
|
||||
}),
|
||||
@@ -150,7 +151,7 @@
|
||||
{@const amount = fromMsats(sum(zaps.map(zap => zap.invoiceAmount)))}
|
||||
{@const pubkeys = uniq(zaps.map(zap => zap.request.pubkey))}
|
||||
{@const isOwn = $pubkey && pubkeys.includes($pubkey)}
|
||||
{@const info = displayList(pubkeys.map(pubkey => displayProfileByPubkey(pubkey)))}
|
||||
{@const info = displayList(pubkeys.map(pubkey => app.use(Profiles).display(pubkey).get()))}
|
||||
{@const tooltip = `${info} zapped`}
|
||||
<button
|
||||
type="button"
|
||||
@@ -171,7 +172,7 @@
|
||||
{#each groupedReactions.entries() as [key, events]}
|
||||
{@const pubkeys = events.map(e => e.pubkey)}
|
||||
{@const isOwn = $pubkey && pubkeys.includes($pubkey)}
|
||||
{@const info = displayList(pubkeys.map(pubkey => displayProfileByPubkey(pubkey)))}
|
||||
{@const info = displayList(pubkeys.map(pubkey => app.use(Profiles).display(pubkey).get()))}
|
||||
{@const tooltip = `${info} reacted`}
|
||||
{@const onClick = () => onReactionClick(events)}
|
||||
<button
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
const onClick = () => goto(h ? makeRoomPath(url, h) : makeSpaceChatPath(url))
|
||||
</script>
|
||||
|
||||
<Button class="cv card2" onclick={onClick}>
|
||||
<Button class="cv card2 bg-alt shadow-md" onclick={onClick}>
|
||||
<div class="flex flex-col gap-3">
|
||||
<div class="flex items-center gap-2 text-sm">
|
||||
{#if h}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
<script lang="ts">
|
||||
import {THREAD, CLASSIFIED, ZAP_GOAL, EVENT_TIME, POLL} from "@welshman/util"
|
||||
import NoteItem from "@app/components/NoteItem.svelte"
|
||||
import ThreadItem from "@app/components/ThreadItem.svelte"
|
||||
import ClassifiedItem from "@app/components/ClassifiedItem.svelte"
|
||||
import GoalItem from "@app/components/GoalItem.svelte"
|
||||
import CalendarEventItem from "@app/components/CalendarEventItem.svelte"
|
||||
import PollItem from "@app/components/PollItem.svelte"
|
||||
import RecentConversation from "@app/components/RecentConversation.svelte"
|
||||
import type {RecentActivityItem} from "@app/recent"
|
||||
|
||||
type Props = {
|
||||
url: string
|
||||
item: RecentActivityItem
|
||||
}
|
||||
|
||||
const {url, item}: Props = $props()
|
||||
</script>
|
||||
|
||||
{#if item.type === "message"}
|
||||
<RecentConversation {url} event={item.event} count={item.count} />
|
||||
{:else if item.event.kind === THREAD}
|
||||
<ThreadItem {url} event={item.event} />
|
||||
{:else if item.event.kind === CLASSIFIED}
|
||||
<ClassifiedItem {url} event={item.event} />
|
||||
{:else if item.event.kind === ZAP_GOAL}
|
||||
<GoalItem {url} event={item.event} />
|
||||
{:else if item.event.kind === EVENT_TIME}
|
||||
<CalendarEventItem {url} event={item.event} />
|
||||
{:else if item.event.kind === POLL}
|
||||
<PollItem {url} event={item.event} />
|
||||
{:else}
|
||||
<NoteItem {url} event={item.event} />
|
||||
{/if}
|
||||
@@ -5,7 +5,7 @@
|
||||
import {tryCatch} from "@welshman/lib"
|
||||
import {isShareableRelayUrl, isIPAddress, normalizeRelayUrl} from "@welshman/util"
|
||||
import type {Thunk} from "@welshman/app"
|
||||
import {waitForThunkError, relaySearch} from "@welshman/app"
|
||||
import {relaySearch} from "@app/welshman"
|
||||
import {createScroller} from "@lib/html"
|
||||
import {errorMessage} from "@lib/util"
|
||||
import Magnifier from "@assets/icons/magnifier.svg?dataurl"
|
||||
@@ -34,7 +34,7 @@
|
||||
loading.add(url)
|
||||
|
||||
try {
|
||||
const error = await waitForThunkError(await addRelay(url))
|
||||
const error = await (await addRelay(url)).waitForError()
|
||||
|
||||
if (error) {
|
||||
pushToast({
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<script lang="ts">
|
||||
import {deriveRelay} from "@welshman/app"
|
||||
import {Relays} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
|
||||
const {...props} = $props()
|
||||
|
||||
const relay = deriveRelay(props.url)
|
||||
const relay = app.use(Relays).one(props.url)
|
||||
</script>
|
||||
|
||||
{#if $relay?.description}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import {deriveRelay} from "@welshman/app"
|
||||
import {Relays} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import RemoteControllerMinimalistic from "@assets/icons/remote-controller-minimalistic.svg?dataurl"
|
||||
import ImageIcon from "@lib/components/ImageIcon.svelte"
|
||||
|
||||
@@ -11,7 +12,7 @@
|
||||
|
||||
const {url, size = 7, ...props}: Props = $props()
|
||||
|
||||
const relay = deriveRelay(url)
|
||||
const relay = app.use(Relays).one(url)
|
||||
</script>
|
||||
|
||||
{#if $relay?.icon}
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
import {displayUrl} from "@welshman/lib"
|
||||
import {displayRelayUrl} from "@welshman/util"
|
||||
import {deriveRelay, deriveRelayStats} from "@welshman/app"
|
||||
import {Relays, RelayStats} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
|
||||
const {url, children} = $props()
|
||||
|
||||
const relay = deriveRelay(url)
|
||||
const relayStats = deriveRelayStats(url)
|
||||
const relay = app.use(Relays).one(url)
|
||||
const relayStats = app.use(RelayStats).one(url)
|
||||
const connections = $derived($relayStats?.open_count || 0)
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type {Readable} from "svelte/store"
|
||||
import {SvelteSet} from "svelte/reactivity"
|
||||
import {waitForThunkError} from "@welshman/app"
|
||||
import type {Thunk} from "@welshman/app"
|
||||
import CloseCircle from "@assets/icons/close-circle.svg?dataurl"
|
||||
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
|
||||
@@ -37,7 +36,7 @@
|
||||
loading.add(url)
|
||||
|
||||
try {
|
||||
const error = await waitForThunkError(await removeRelay(url))
|
||||
const error = await (await removeRelay(url)).waitForError()
|
||||
|
||||
if (error) {
|
||||
pushToast({
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import {deriveRelayDisplay} from "@welshman/app"
|
||||
import {Relays} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
|
||||
type Props = {
|
||||
url: string
|
||||
@@ -8,7 +9,7 @@
|
||||
|
||||
const {url, ...props}: Props = $props()
|
||||
|
||||
const display = $derived(deriveRelayDisplay(url))
|
||||
const display = $derived(app.use(Relays).display(url).$)
|
||||
</script>
|
||||
|
||||
<span class={props.class}>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import {REPORT} from "@welshman/util"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {deriveEventsById} from "@welshman/store"
|
||||
import {repository} from "@welshman/app"
|
||||
import {repository} from "@app/welshman"
|
||||
import ModalHeader from "@lib/components/ModalHeader.svelte"
|
||||
import ModalTitle from "@lib/components/ModalTitle.svelte"
|
||||
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
import {getTag, ManagementMethod} from "@welshman/util"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {pubkey, manageRelay, repository, displayProfileByPubkey} from "@welshman/app"
|
||||
import {RelayManagement, Profiles} from "@welshman/app"
|
||||
import {pubkey, repository, app} from "@app/welshman"
|
||||
import InboxOut from "@assets/icons/inbox-out.svg?dataurl"
|
||||
import MenuDots from "@assets/icons/menu-dots.svg?dataurl"
|
||||
import MinusCircle from "@assets/icons/minus-circle.svg?dataurl"
|
||||
@@ -12,7 +13,7 @@
|
||||
import Popover from "@lib/components/Popover.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import Confirm from "@lib/components/Confirm.svelte"
|
||||
import {deriveUserIsSpaceAdmin, banSpaceMembers} from "@app/members"
|
||||
import {deriveUserIsSpaceAdmin} from "@app/members"
|
||||
import {publishDelete} from "@app/deletes"
|
||||
import {canEnforceNip70} from "@app/relays"
|
||||
import {pushToast} from "@app/toast"
|
||||
@@ -45,7 +46,7 @@
|
||||
}
|
||||
|
||||
const dismissReport = async () => {
|
||||
const {error} = await manageRelay(url, {
|
||||
const {error} = await app.use(RelayManagement).post(url, {
|
||||
method: ManagementMethod.BanEvent,
|
||||
params: [event.id, "Dismissed by admin"],
|
||||
})
|
||||
@@ -66,7 +67,7 @@
|
||||
title: `Remove Content`,
|
||||
message: `Are you sure you want to delete this content from the space?`,
|
||||
confirm: async () => {
|
||||
const {error} = await manageRelay(url, {
|
||||
const {error} = await app.use(RelayManagement).post(url, {
|
||||
method: ManagementMethod.BanEvent,
|
||||
params: [id, reason],
|
||||
})
|
||||
@@ -89,9 +90,12 @@
|
||||
|
||||
pushModal(Confirm, {
|
||||
title: "Ban User",
|
||||
message: `Are you sure you want to ban @${displayProfileByPubkey(pubkey)} from the space?`,
|
||||
message: `Are you sure you want to ban @${app.use(Profiles).display(pubkey).get()} from the space?`,
|
||||
confirm: async () => {
|
||||
const error = await banSpaceMembers(url, [pubkey], reason)
|
||||
const {error} = await app.use(RelayManagement).post(url, {
|
||||
method: ManagementMethod.BanPubkey,
|
||||
params: [pubkey, reason],
|
||||
})
|
||||
|
||||
if (error) {
|
||||
pushToast({theme: "error", message: error})
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<script lang="ts">
|
||||
import {roleColor, roleColorSoft, type SpaceRole} from "@app/members"
|
||||
|
||||
interface Props {
|
||||
role: SpaceRole
|
||||
}
|
||||
|
||||
const {role}: Props = $props()
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="badge min-w-0"
|
||||
style="background-color: {roleColorSoft(role.color)}; border-color: {roleColor(
|
||||
role.color,
|
||||
)}; color: {roleColor(role.color)};">
|
||||
<strong>{role.label || "Untitled Role"}</strong>
|
||||
</div>
|
||||
@@ -1,49 +0,0 @@
|
||||
<script lang="ts">
|
||||
import {randomId} from "@welshman/lib"
|
||||
import Modal from "@lib/components/Modal.svelte"
|
||||
import ModalBody from "@lib/components/ModalBody.svelte"
|
||||
import ModalHeader from "@lib/components/ModalHeader.svelte"
|
||||
import ModalTitle from "@lib/components/ModalTitle.svelte"
|
||||
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
|
||||
import RelayName from "@app/components/RelayName.svelte"
|
||||
import RoleForm, {type Values} from "@app/components/RoleForm.svelte"
|
||||
import {createRole} from "@app/members"
|
||||
import {pushToast} from "@app/toast"
|
||||
|
||||
type Props = {
|
||||
url: string
|
||||
}
|
||||
|
||||
const {url}: Props = $props()
|
||||
|
||||
const back = () => history.back()
|
||||
|
||||
let loading = $state(false)
|
||||
|
||||
const onSubmit = async ({label, description, color}: Values) => {
|
||||
loading = true
|
||||
|
||||
try {
|
||||
const error = await createRole(url, randomId(), label, description, color, 0)
|
||||
|
||||
if (error) {
|
||||
pushToast({theme: "error", message: error})
|
||||
} else {
|
||||
pushToast({message: "Role created!"})
|
||||
back()
|
||||
}
|
||||
} finally {
|
||||
loading = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<Modal>
|
||||
<ModalBody>
|
||||
<ModalHeader>
|
||||
<ModalTitle>Create Role</ModalTitle>
|
||||
<ModalSubtitle>in <RelayName {url} class="text-primary" /></ModalSubtitle>
|
||||
</ModalHeader>
|
||||
<RoleForm {loading} {onSubmit} />
|
||||
</ModalBody>
|
||||
</Modal>
|
||||
@@ -1,49 +0,0 @@
|
||||
<script lang="ts">
|
||||
import Modal from "@lib/components/Modal.svelte"
|
||||
import ModalBody from "@lib/components/ModalBody.svelte"
|
||||
import ModalHeader from "@lib/components/ModalHeader.svelte"
|
||||
import ModalTitle from "@lib/components/ModalTitle.svelte"
|
||||
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
|
||||
import RelayName from "@app/components/RelayName.svelte"
|
||||
import RoleForm, {type Values} from "@app/components/RoleForm.svelte"
|
||||
import {editRole, type SpaceRole} from "@app/members"
|
||||
import {pushToast} from "@app/toast"
|
||||
|
||||
type Props = {
|
||||
url: string
|
||||
role: SpaceRole
|
||||
}
|
||||
|
||||
const {url, role}: Props = $props()
|
||||
|
||||
const back = () => history.back()
|
||||
|
||||
let loading = $state(false)
|
||||
|
||||
const onSubmit = async ({label, description, color}: Values) => {
|
||||
loading = true
|
||||
|
||||
try {
|
||||
const error = await editRole(url, role.id, label, description, color, role.order)
|
||||
|
||||
if (error) {
|
||||
pushToast({theme: "error", message: error})
|
||||
} else {
|
||||
pushToast({message: "Role updated!"})
|
||||
back()
|
||||
}
|
||||
} finally {
|
||||
loading = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<Modal>
|
||||
<ModalBody>
|
||||
<ModalHeader>
|
||||
<ModalTitle>Edit Role</ModalTitle>
|
||||
<ModalSubtitle>in <RelayName {url} class="text-primary" /></ModalSubtitle>
|
||||
</ModalHeader>
|
||||
<RoleForm {loading} {onSubmit} initialValues={role} />
|
||||
</ModalBody>
|
||||
</Modal>
|
||||
@@ -1,86 +0,0 @@
|
||||
<script module lang="ts">
|
||||
import type {SpaceRole} from "@app/members"
|
||||
|
||||
export type Values = Pick<SpaceRole, "label" | "description" | "color">
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import Spinner from "@lib/components/Spinner.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import Field from "@lib/components/Field.svelte"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
|
||||
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
||||
import {roleColor} from "@app/members"
|
||||
|
||||
type Props = {
|
||||
initialValues?: Partial<Values>
|
||||
loading?: boolean
|
||||
onSubmit: (values: Values) => void
|
||||
}
|
||||
|
||||
const {initialValues = {}, loading = false, onSubmit}: Props = $props()
|
||||
|
||||
const values: Values = $state({
|
||||
label: "",
|
||||
description: "",
|
||||
color: Math.floor(Math.random() * 256),
|
||||
...initialValues,
|
||||
})
|
||||
|
||||
const back = () => history.back()
|
||||
|
||||
const submit = () => onSubmit(values)
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
<Field>
|
||||
{#snippet label()}
|
||||
<p>Name</p>
|
||||
{/snippet}
|
||||
{#snippet input()}
|
||||
<input
|
||||
bind:value={values.label}
|
||||
class="input input-bordered w-full"
|
||||
placeholder="Moderator" />
|
||||
{/snippet}
|
||||
</Field>
|
||||
<Field>
|
||||
{#snippet label()}
|
||||
<p>Description</p>
|
||||
{/snippet}
|
||||
{#snippet input()}
|
||||
<textarea bind:value={values.description} class="textarea textarea-bordered w-full" rows="2"
|
||||
></textarea>
|
||||
{/snippet}
|
||||
</Field>
|
||||
<Field>
|
||||
{#snippet label()}
|
||||
<p>Color</p>
|
||||
{/snippet}
|
||||
{#snippet input()}
|
||||
<div class="flex items-center gap-3">
|
||||
<div
|
||||
class="h-8 w-8 shrink-0 rounded-full border-2 border-base-300"
|
||||
style="background-color: {roleColor(values.color)}">
|
||||
</div>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="255"
|
||||
bind:value={values.color}
|
||||
class="range range-sm grow"
|
||||
style="color: {roleColor(values.color)}; --range-shdw: {roleColor(values.color)}" />
|
||||
</div>
|
||||
{/snippet}
|
||||
</Field>
|
||||
</div>
|
||||
<ModalFooter>
|
||||
<Button class="btn btn-link" onclick={back}>
|
||||
<Icon icon={AltArrowLeft} />
|
||||
Go back
|
||||
</Button>
|
||||
<Button class="btn btn-primary" onclick={submit} disabled={loading || !values.label}>
|
||||
<Spinner {loading}>Save changes</Spinner>
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
@@ -1,17 +0,0 @@
|
||||
<script lang="ts">
|
||||
import RoleBadge from "@app/components/RoleBadge.svelte"
|
||||
import type {SpaceRole} from "@app/members"
|
||||
|
||||
interface Props {
|
||||
role: SpaceRole
|
||||
}
|
||||
|
||||
const {role}: Props = $props()
|
||||
</script>
|
||||
|
||||
<div class="flex min-w-0 flex-col gap-2">
|
||||
<RoleBadge {role} />
|
||||
{#if role.description}
|
||||
<p class="text-sm opacity-70">{role.description}</p>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {displayProfileByPubkey} from "@welshman/app"
|
||||
import {Profiles} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import {slide} from "@lib/transition"
|
||||
import CloseCircle from "@assets/icons/close-circle.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
@@ -21,7 +22,7 @@
|
||||
<div
|
||||
class="relative border-l-2 border-solid border-primary bg-base-300 px-2 py-1 pr-8"
|
||||
transition:slide>
|
||||
<p class="text-xs text-primary">{verb} @{displayProfileByPubkey(event.pubkey)}</p>
|
||||
<p class="text-xs text-primary">{verb} @{app.use(Profiles).display(event.pubkey).get()}</p>
|
||||
{#key event.id}
|
||||
<NoteContentMinimal trimParent {event} />
|
||||
{/key}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
import {goto} from "$app/navigation"
|
||||
import type {RoomMeta} from "@welshman/util"
|
||||
import {displayRelayUrl, makeRoomMeta} from "@welshman/util"
|
||||
import {displayRelayUrl} from "@welshman/util"
|
||||
import type {Thunk} from "@welshman/app"
|
||||
import {deleteRoom, waitForThunkError, repository, joinRoom, leaveRoom} from "@welshman/app"
|
||||
import {Rooms} from "@welshman/app"
|
||||
import {repository, app} from "@app/welshman"
|
||||
import Pen from "@assets/icons/pen.svg?dataurl"
|
||||
import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl"
|
||||
import Login3 from "@assets/icons/login-3.svg?dataurl"
|
||||
@@ -71,11 +71,13 @@
|
||||
|
||||
const startEdit = () => pushModal(RoomEdit, {url, h})
|
||||
|
||||
const handleLoading = async (f: (url: string, room: RoomMeta) => Thunk) => {
|
||||
const handleLoading = async (
|
||||
f: (url: string, room: {h: string}) => Promise<Thunk>,
|
||||
) => {
|
||||
loading = true
|
||||
|
||||
try {
|
||||
const message = await waitForThunkError(f(url, makeRoomMeta({h})))
|
||||
const message = await (await f(url, {h})).waitForError()
|
||||
|
||||
if (message && !message.startsWith("duplicate:")) {
|
||||
pushToast({theme: "error", message})
|
||||
@@ -85,9 +87,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
const join = () => handleLoading(joinRoom)
|
||||
const join = () => handleLoading((url, room) => app.use(Rooms).join(url, room))
|
||||
|
||||
const leave = () => handleLoading(leaveRoom)
|
||||
const leave = () => handleLoading((url, room) => app.use(Rooms).leave(url, room))
|
||||
|
||||
const showMembers = () => pushModal(RoomMembers, {url, h})
|
||||
|
||||
@@ -109,8 +111,8 @@
|
||||
message:
|
||||
"This room will no longer be accessible to space members, and all messages posted to it will be deleted.",
|
||||
confirm: async () => {
|
||||
const thunk = deleteRoom(url, $room)
|
||||
const message = await waitForThunkError(thunk)
|
||||
const thunk = await app.use(Rooms).delete(url, $room)
|
||||
const message = await thunk.waitForError()
|
||||
|
||||
if (message) {
|
||||
repository.removeEvent(thunk.event.id)
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type {Snippet} from "svelte"
|
||||
import type {RoomMeta} from "@welshman/util"
|
||||
import {makeRoomMeta} from "@welshman/util"
|
||||
import {waitForThunkError, createRoom, editRoom, joinRoom} from "@welshman/app"
|
||||
import {Rooms} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import StickerSmileSquare from "@assets/icons/sticker-smile-square.svg?dataurl"
|
||||
import Hashtag from "@assets/icons/hashtag.svg?dataurl"
|
||||
import Volume from "@assets/icons/volume.svg?dataurl"
|
||||
@@ -19,6 +18,56 @@
|
||||
import {deriveHasLivekit} from "@app/relays"
|
||||
import {getRoomType, RoomType} from "@app/groups"
|
||||
|
||||
// Plain mutable form object (the old @welshman/util `RoomMeta` plain-object
|
||||
// type, removed in the migration). The new domain `RoomMeta` is an async
|
||||
// method-accessor Reader, which doesn't fit a `$state` object bound to inputs,
|
||||
// so we keep a plain object here and let `app.use(Rooms).create/edit/join`
|
||||
// (which accept a plain object) build the events at submit time.
|
||||
type RoomMeta = {
|
||||
h: string
|
||||
name?: string
|
||||
about?: string
|
||||
picture?: string
|
||||
pictureMeta?: string[]
|
||||
isClosed?: boolean
|
||||
isHidden?: boolean
|
||||
isPrivate?: boolean
|
||||
isRestricted?: boolean
|
||||
livekit?: boolean
|
||||
}
|
||||
|
||||
// TODO(welshman-migration): reimplemented inline from the removed
|
||||
// @welshman/util `generateH`/`makeRoomMeta` (room-id generator). Verify the
|
||||
// generated id still matches the expected `^[a-z]+[1-9]$` shape and that no
|
||||
// shared generator should be used instead.
|
||||
const vowels = "a,e,i,o,u,ay,ey,oy,ou,ia,ea,ough,oo,ee,argh".split(",")
|
||||
|
||||
const consonants =
|
||||
"p,b,t,d,k,g,ch,sh,th,f,v,s,z,l,r,m,n,pl,bl,cl,gl,pr,br,tr,dr,kr,gr,fl,sl,fr,thr,str,sk,sp,st".split(
|
||||
",",
|
||||
)
|
||||
|
||||
const generateH = () => {
|
||||
const n = (6 + Math.random() * 2) | 0
|
||||
const s = [consonants.slice(), vowels.slice()]
|
||||
|
||||
if (Math.random() < 0.5) {
|
||||
s.reverse()
|
||||
}
|
||||
|
||||
return (
|
||||
Array.from({length: n}, (_, i) =>
|
||||
s[i % 2].splice((Math.random() * s[i % 2].length) | 0, 1),
|
||||
).join("") +
|
||||
(1 + Math.floor(Math.random() * 9))
|
||||
)
|
||||
}
|
||||
|
||||
const makeRoomMeta = (room: Partial<RoomMeta> = {}): RoomMeta => ({
|
||||
h: room.h ?? generateH(),
|
||||
...room,
|
||||
})
|
||||
|
||||
type Props = {
|
||||
url: string
|
||||
header: Snippet
|
||||
@@ -58,19 +107,22 @@
|
||||
room.pictureMeta = result.tags
|
||||
}
|
||||
|
||||
const createMessage = await waitForThunkError(createRoom(url, room))
|
||||
// TODO(welshman-migration): app.use(Rooms).create/edit/join are async
|
||||
// (return Promise<Thunk>); the old code passed the un-awaited result to
|
||||
// waitForThunkError. Awaiting the thunk first before .waitForError().
|
||||
const createMessage = await (await app.use(Rooms).create(url, room)).waitForError()
|
||||
|
||||
if (createMessage && !createMessage.includes("already")) {
|
||||
return pushToast({theme: "error", message: createMessage})
|
||||
}
|
||||
|
||||
const editMessage = await waitForThunkError(editRoom(url, room))
|
||||
const editMessage = await (await app.use(Rooms).edit(url, room)).waitForError()
|
||||
|
||||
if (editMessage) {
|
||||
return pushToast({theme: "error", message: editMessage})
|
||||
}
|
||||
|
||||
const joinMessage = await waitForThunkError(joinRoom(url, room))
|
||||
const joinMessage = await (await app.use(Rooms).join(url, room)).waitForError()
|
||||
|
||||
if (joinMessage && !joinMessage.includes("already")) {
|
||||
return pushToast({theme: "error", message: joinMessage})
|
||||
|
||||
@@ -11,13 +11,8 @@
|
||||
} from "@welshman/lib"
|
||||
import type {TrustedEvent, EventContent} from "@welshman/util"
|
||||
import {MESSAGE, COMMENT, getTag} from "@welshman/util"
|
||||
import {
|
||||
thunks,
|
||||
pubkey,
|
||||
mergeThunks,
|
||||
deriveProfileDisplay,
|
||||
displayProfileByPubkey,
|
||||
} from "@welshman/app"
|
||||
import {Thunks, Profiles} from "@welshman/app"
|
||||
import {thunks, pubkey, app} from "@app/welshman"
|
||||
import {isMobile} from "@lib/html"
|
||||
import Pen from "@assets/icons/pen.svg?dataurl"
|
||||
import Reply from "@assets/icons/reply-2.svg?dataurl"
|
||||
@@ -58,8 +53,8 @@
|
||||
const path = getRoomItemPath(url, event)
|
||||
const shouldProtect = canEnforceNip70(url)
|
||||
const today = formatTimestampAsDate(now())
|
||||
const profileDisplay = deriveProfileDisplay(event.pubkey, [url])
|
||||
const thunk = mergeThunks($thunks.filter(t => t.event.id === event.id))
|
||||
const profileDisplay = app.use(Profiles).display(event.pubkey, [url]).$
|
||||
const thunk = app.use(Thunks).merge($thunks.filter(t => t.event.id === event.id))
|
||||
const [_, colorValue] = colors[hash(event.pubkey) % colors.length]
|
||||
|
||||
const qTag = getTag("q", event.tags)
|
||||
@@ -138,7 +133,7 @@
|
||||
{#if path && $innerComments.length > 0}
|
||||
{@const pubkeys = $innerComments.map(e => e.pubkey)}
|
||||
{@const isOwn = $pubkey && pubkeys.includes($pubkey)}
|
||||
{@const info = displayList(pubkeys.map(pubkey => displayProfileByPubkey(pubkey)))}
|
||||
{@const info = displayList(pubkeys.map(pubkey => app.use(Profiles).display(pubkey).get()))}
|
||||
{@const tooltip = `${info} commented`}
|
||||
<div data-tip={tooltip} class="tooltip tooltip-right flex">
|
||||
<Link
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {ManagementMethod} from "@welshman/util"
|
||||
import {pubkey, manageRelay, repository} from "@welshman/app"
|
||||
import {RelayManagement} from "@welshman/app"
|
||||
import {pubkey, repository, app} from "@app/welshman"
|
||||
import Code2 from "@assets/icons/code-2.svg?dataurl"
|
||||
import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl"
|
||||
import Danger from "@assets/icons/danger.svg?dataurl"
|
||||
@@ -45,7 +46,7 @@
|
||||
title: `Delete Message`,
|
||||
message: `Are you sure you want to delete this message from the space?`,
|
||||
confirm: async () => {
|
||||
const {error} = await manageRelay(url, {
|
||||
const {error} = await app.use(RelayManagement).post(url, {
|
||||
method: ManagementMethod.BanEvent,
|
||||
params: [event.id],
|
||||
})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type {NativeEmoji} from "emoji-picker-element/shared"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {pubkey} from "@welshman/app"
|
||||
import {pubkey} from "@app/welshman"
|
||||
import Bolt from "@assets/icons/bolt.svg?dataurl"
|
||||
import Reply from "@assets/icons/reply-2.svg?dataurl"
|
||||
import Code2 from "@assets/icons/code-2.svg?dataurl"
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
import {getTagValue, ManagementMethod} from "@welshman/util"
|
||||
import type {TrustedEvent, PublishedRoomMeta} from "@welshman/util"
|
||||
import {repository, manageRelay} from "@welshman/app"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {RelayManagement} from "@welshman/app"
|
||||
import {app, repository} from "@app/welshman"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import ProfileName from "@app/components/ProfileName.svelte"
|
||||
import ProfileDetail from "@app/components/ProfileDetail.svelte"
|
||||
@@ -28,7 +29,7 @@
|
||||
loading = true
|
||||
|
||||
try {
|
||||
const {error} = await manageRelay(url, {
|
||||
const {error} = await app.use(RelayManagement).post(url, {
|
||||
method: ManagementMethod.BanEvent,
|
||||
params: [event.id, "Join request dismissed"],
|
||||
})
|
||||
@@ -49,7 +50,11 @@
|
||||
loading = true
|
||||
|
||||
try {
|
||||
const error = await addRoomMembers(url, $room as PublishedRoomMeta, [event.pubkey])
|
||||
// TODO(welshman-migration): addRoomMembers now expects a RoomMeta domain
|
||||
// Reader, but deriveRoom yields the plain `Room` object. Passing it through
|
||||
// as `any` preserves prior runtime behavior; verify Rooms.addMember accepts
|
||||
// the plain Room shape (url/h/...) or resolve a real RoomMeta reader here.
|
||||
const error = await addRoomMembers(url, $room as any, [event.pubkey])
|
||||
|
||||
if (error) {
|
||||
pushToast({theme: "error", message: error})
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import {waitForThunkError, removeRoomMember} from "@welshman/app"
|
||||
import {Rooms} from "@welshman/app"
|
||||
import {app} from "@app/welshman"
|
||||
import MenuDots from "@assets/icons/menu-dots.svg?dataurl"
|
||||
import MinusCircle from "@assets/icons/minus-circle.svg?dataurl"
|
||||
import AddCircle from "@assets/icons/add-circle.svg?dataurl"
|
||||
@@ -51,7 +52,8 @@
|
||||
title: "Remove Member",
|
||||
message: "Are you sure you want to remove this user from the room?",
|
||||
confirm: async () => {
|
||||
const error = await waitForThunkError(removeRoomMember(url, $room, pubkey))
|
||||
const thunk = await app.use(Rooms).removeMember(url, $room, pubkey)
|
||||
const error = await thunk.waitForError()
|
||||
|
||||
if (error) {
|
||||
pushToast({theme: "error", message: error})
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user