Compare commits

..

5 Commits

Author SHA1 Message Date
Jon Staab b428ad3d36 Fix dufflepud url
Container Image Build and Publish / build-and-push-image (push) Has started running
2026-06-23 13:11:18 -07:00
Jon Staab 18b52a37bb Fix keyboard safe insets 2026-06-23 13:03:42 -07:00
Jon Staab 7fba1752a1 Bump version, format 2026-06-23 09:58:08 -07:00
Jon Staab c44c3793fa Split up space information and directory 2026-06-23 06:04:22 -07:00
Jon Staab 7ec5a28d1f Add roles 2026-06-22 15:45:31 -07:00
343 changed files with 4191 additions and 7012 deletions
+1 -1
View File
@@ -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://chat.flotilla.social/
VITE_DEFAULT_SPACES=https://support.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
+3
View File
@@ -170,6 +170,9 @@ 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):**
+21
View File
@@ -1,5 +1,26 @@
# Changelog
# 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
+2 -2
View File
@@ -8,8 +8,8 @@ android {
applicationId "social.flotilla"
minSdk rootProject.ext.minSdkVersion
targetSdk rootProject.ext.targetSdkVersion
versionCode 47
versionName "1.8.0"
versionCode 48
versionName "1.8.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
-1
View File
@@ -10,7 +10,6 @@ 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,7 +11,6 @@
<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>
+11 -14
View File
@@ -1,39 +1,36 @@
// 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.0.1_@capacitor+core@8.0.1/node_modules/@capacitor/android/capacitor')
project(':capacitor-android').projectDir = new File('../node_modules/.pnpm/@capacitor+android@8.3.4_@capacitor+core@8.3.4/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.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/app/android')
project(':capacitor-app').projectDir = new File('../node_modules/.pnpm/@capacitor+app@8.1.0_@capacitor+core@8.3.4/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.0.1/node_modules/@capacitor/clipboard/android')
project(':capacitor-clipboard').projectDir = new File('../node_modules/.pnpm/@capacitor+clipboard@8.0.1_@capacitor+core@8.3.4/node_modules/@capacitor/clipboard/android')
include ':capacitor-filesystem'
project(':capacitor-filesystem').projectDir = new File('../node_modules/.pnpm/@capacitor+filesystem@8.1.0_@capacitor+core@8.0.1/node_modules/@capacitor/filesystem/android')
project(':capacitor-filesystem').projectDir = new File('../node_modules/.pnpm/@capacitor+filesystem@8.1.2_@capacitor+core@8.3.4/node_modules/@capacitor/filesystem/android')
include ':capacitor-keyboard'
project(':capacitor-keyboard').projectDir = new File('../node_modules/.pnpm/@capacitor+keyboard@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/keyboard/android')
project(':capacitor-keyboard').projectDir = new File('../node_modules/.pnpm/@capacitor+keyboard@8.0.3_@capacitor+core@8.3.4/node_modules/@capacitor/keyboard/android')
include ':capacitor-preferences'
project(':capacitor-preferences').projectDir = new File('../node_modules/.pnpm/@capacitor+preferences@8.0.0_@capacitor+core@8.0.1/node_modules/@capacitor/preferences/android')
project(':capacitor-preferences').projectDir = new File('../node_modules/.pnpm/@capacitor+preferences@8.0.1_@capacitor+core@8.3.4/node_modules/@capacitor/preferences/android')
include ':capacitor-push-notifications'
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')
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')
include ':capacitor-share'
project(':capacitor-share').projectDir = new File('../node_modules/.pnpm/@capacitor+share@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor/share/android')
project(':capacitor-share').projectDir = new File('../node_modules/.pnpm/@capacitor+share@8.0.1_@capacitor+core@8.3.4/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.0_@capacitor+core@8.0.1/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.1_@capacitor+core@8.3.4/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.0_@capacitor+core@8.0.1/node_modules/@capawesome/capacitor-badge/android')
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')
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_a3c0fb15d5bfa83f24d0070ca2583fc9/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_fd4b5c957724da9f45e5678eca5c7fd4/node_modules/nostr-signer-capacitor-plugin/android')
+1 -5
View File
@@ -7,22 +7,18 @@ const config: CapacitorConfig = {
ios: {
scheme: "Flotilla Chat",
},
android: {
adjustMarginsForEdgeToEdge: true,
},
plugins: {
CapacitorHttp: {
enabled: true,
},
SystemBars: {
insetsHandling: "enable",
insetsHandling: "css",
},
SplashScreen: {
androidSplashResourceName: "splash",
},
Keyboard: {
style: "DARK",
resizeOnFullScreen: true,
},
Badge: {
persist: true,
+4 -4
View File
@@ -372,7 +372,7 @@
CODE_SIGN_ENTITLEMENTS = "Flotilla Chat.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 38;
CURRENT_PROJECT_VERSION = 39;
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.0;
MARKETING_VERSION = 1.8.1;
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 = 38;
CURRENT_PROJECT_VERSION = 39;
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.0;
MARKETING_VERSION = 1.8.1;
PRODUCT_BUNDLE_IDENTIFIER = social.flotilla;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
+12 -13
View File
@@ -1,4 +1,4 @@
require_relative '../../node_modules/.pnpm/@capacitor+ios@8.0.1_@capacitor+core@8.0.1/node_modules/@capacitor/ios/scripts/pods_helpers'
require_relative '../../node_modules/.pnpm/@capacitor+ios@8.3.4_@capacitor+core@8.3.4/node_modules/@capacitor/ios/scripts/pods_helpers'
platform :ios, '15.0'
use_frameworks!
@@ -9,19 +9,18 @@ use_frameworks!
install! 'cocoapods', :disable_input_output_paths => true
def capacitor_pods
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 '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 'AparajitaCapacitorSecureStorage', :path => '../../node_modules/.pnpm/@aparajita+capacitor-secure-storage@8.0.0/node_modules/@aparajita/capacitor-secure-storage'
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'
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'
end
target 'Flotilla Chat' do
+2 -3
View File
@@ -1,6 +1,6 @@
{
"name": "flotilla",
"version": "1.8.0",
"version": "1.8.1",
"private": true,
"scripts": {
"dev": "vite dev",
@@ -45,7 +45,6 @@
"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",
@@ -63,7 +62,7 @@
"@getalby/sdk": "^5.1.2",
"@hono/node-server": "^2.0.0",
"@noble/curves": "^1.9.7",
"@pomade/core": "^0.3.0",
"@pomade/core": "^0.3.1",
"@poppanator/sveltekit-svg": "^7.0.0",
"@sveltejs/adapter-static": "^3.0.10",
"@tiptap/core": "^2.27.2",
+14 -26
View File
@@ -14,9 +14,6 @@ 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)
@@ -69,8 +66,8 @@ importers:
specifier: ^1.9.7
version: 1.9.7
'@pomade/core':
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))
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))
'@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))
@@ -97,7 +94,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(7683b6be0f65191b839378ceee4e4014)
version: 0.8.16(9e2dd3230191940679c41b23e5e365c3)
'@welshman/content':
specifier: ^0.8.16
version: 0.8.16(nostr-tools@2.23.5(typescript@5.9.3))
@@ -779,11 +776,6 @@ 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:
@@ -1476,9 +1468,9 @@ packages:
'@polka/url@1.0.0-next.29':
resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
'@pomade/core@0.3.0':
resolution: {integrity: sha512-zWx0wJftbW92GSIEdLnOk8oUzaGAd0DbOqCBOoNeyCtgn9i4aNy0QsVmYDwxI8xKtVujsxppqk+fMJvinIiEqA==}
version: 0.3.0
'@pomade/core@0.3.1':
resolution: {integrity: sha512-lNsM60bu2o9JlqPc47JoAz19QACXS5dNYgvoeApLW8LpxuWy7RcMyHDZ3llklVPYd99PXslFtBdVRpbP26oKyQ==}
version: 0.3.1
engines: {node: '>=12.0.0'}
peerDependencies:
'@frostr/bifrost': ^1.0.7
@@ -5847,10 +5839,6 @@ 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
@@ -6013,7 +6001,7 @@ snapshots:
'@emnapi/runtime@1.10.0':
dependencies:
tslib: 2.6.2
tslib: 2.8.1
optional: true
'@esbuild/aix-ppc64@0.25.12':
@@ -6318,7 +6306,7 @@ snapshots:
debug: 4.3.4
signal-exit: 3.0.7
tree-kill: 1.2.2
tslib: 2.6.2
tslib: 2.8.1
transitivePeerDependencies:
- supports-color
@@ -6336,7 +6324,7 @@ snapshots:
'@ionic/utils-stream@3.1.6':
dependencies:
debug: 4.3.4
tslib: 2.6.2
tslib: 2.8.1
transitivePeerDependencies:
- supports-color
@@ -6356,7 +6344,7 @@ snapshots:
'@ionic/utils-terminal': 2.3.4
cross-spawn: 7.0.6
debug: 4.3.4
tslib: 2.6.2
tslib: 2.8.1
transitivePeerDependencies:
- supports-color
@@ -6381,7 +6369,7 @@ snapshots:
slice-ansi: 4.0.0
string-width: 4.2.3
strip-ansi: 6.0.1
tslib: 2.6.2
tslib: 2.8.1
untildify: 4.0.0
wrap-ansi: 7.0.0
transitivePeerDependencies:
@@ -6578,7 +6566,7 @@ snapshots:
'@polka/url@1.0.0-next.29': {}
'@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))':
'@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))':
dependencies:
'@frostr/bifrost': 1.0.7(typescript@5.9.3)
'@noble/hashes': 2.2.0
@@ -7197,9 +7185,9 @@ snapshots:
- workbox-build
- workbox-window
'@welshman/app@0.8.16(7683b6be0f65191b839378ceee4e4014)':
'@welshman/app@0.8.16(9e2dd3230191940679c41b23e5e365c3)':
dependencies:
'@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))
'@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))
'@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)
+8 -3
View File
@@ -85,7 +85,7 @@
}
@utility card2 {
@apply rounded-box text-base-content p-4 sm:p-6;
@apply rounded-box text-base-content border-base-content/20 bg-base-100 border border-solid p-4 shadow-xl/5 sm:p-6;
}
@utility column {
@@ -276,6 +276,11 @@
@apply text-base-content p-2 sm:p-4;
}
.card2 .card2,
.dialog .card2 {
@apply shadow-none;
}
[data-tip]::before {
@apply overflow-hidden text-ellipsis;
}
@@ -414,11 +419,11 @@ progress[value]::-webkit-progress-value {
/* content width for fixed elements */
.left-content {
@apply md:left-[calc(18.5rem+var(--sail))];
@apply left-sai md:left-[calc(18.5rem+var(--sail))];
}
.left-content-full {
@apply md:left-[calc(3.5rem+var(--sail))];
@apply left-sai md:left-[calc(3.5rem+var(--sail))];
}
/* Keyboard open state adjustments */
+1 -3
View File
@@ -4,9 +4,7 @@
<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, interactive-widget=resizes-content" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<meta name="theme-color" content="{ACCENT}" />
<meta name="description" content="{DESCRIPTION}" />
<meta property="og:url" content="{URL}" />
+1 -1
View File
@@ -1,7 +1,7 @@
<script lang="ts">
import type {Snippet} from "svelte"
import {pubkey} from "@welshman/app"
import Dialog from "@lib/components2/Dialog.svelte"
import Dialog from "@lib/components/Dialog.svelte"
import Landing from "@app/components/Landing.svelte"
import Toast from "@app/components/Toast.svelte"
import PrimaryNav from "@app/components/PrimaryNav.svelte"
+2 -3
View File
@@ -1,6 +1,5 @@
<script lang="ts">
import Spinner from "@lib/components2/Spinner.svelte"
import Text from "@lib/components2/Text.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import QRCode from "@app/components/QRCode.svelte"
import type {Nip46Controller} from "@app/nip46"
@@ -20,7 +19,7 @@
{:else}
<div class="flex flex-col items-center gap-2">
<QRCode code={$url} />
<Text size="sm" muted>Scan with your signer to log in, or click to copy.</Text>
<p class="text-sm opacity-75">Scan with your signer to log in, or click to copy.</p>
</div>
{/if}
{/if}
+7 -7
View File
@@ -1,11 +1,11 @@
<script lang="ts">
import {debounce} from "throttle-debounce"
import Scanner from "@lib/components2/Scanner.svelte"
import Button from "@lib/components2/Button.svelte"
import Field from "@lib/components2/Field.svelte"
import Scanner from "@lib/components/Scanner.svelte"
import Button from "@lib/components/Button.svelte"
import Field from "@lib/components/Field.svelte"
import CpuBolt from "@assets/icons/cpu-bolt.svg?dataurl"
import QrCode from "@assets/icons/qr-code.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Icon from "@lib/components/Icon.svelte"
import InfoBunker from "@app/components/InfoBunker.svelte"
import type {Nip46Controller} from "@app/nip46"
import {pushModal} from "@app/modal"
@@ -34,9 +34,9 @@
<p>Bunker Link*</p>
{/snippet}
{#snippet input()}
<label class="input-cl input-cl-group">
<label class="input input-bordered flex w-full items-center gap-2">
<Icon icon={CpuBolt} />
<input disabled={$loading} bind:value={$bunker} placeholder="bunker://" />
<input disabled={$loading} bind:value={$bunker} class="grow" placeholder="bunker://" />
<Button onclick={toggleScanner}>
<Icon icon={QrCode} />
</Button>
@@ -45,7 +45,7 @@
{#snippet info()}
<p>
A login link provided by a nostr signing app.
<Button class="cl-link" onclick={() => pushModal(InfoBunker)}>What is a bunker link?</Button>
<Button class="link" onclick={() => pushModal(InfoBunker)}>What is a bunker link?</Button>
</p>
{/snippet}
</Field>
@@ -3,9 +3,9 @@
import {getTagValue, getAddress} from "@welshman/util"
import {pubkey} from "@welshman/app"
import Pen2 from "@assets/icons/pen-2.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Link from "@lib/components2/Link.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import Link from "@lib/components/Link.svelte"
import RoomName from "@app/components/RoomName.svelte"
import ReactionSummary from "@app/components/ReactionSummary.svelte"
import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte"
@@ -42,11 +42,11 @@
<div class="flex grow flex-wrap justify-end gap-2">
{#if h && showRoom}
<Link href={makeSpacePath(url, h)} class="badge-cl badge-cl-neutral badge-cl-sm">
<Link href={makeSpacePath(url, h)} class="btn btn-neutral btn-xs rounded-full">
Posted in #<RoomName {h} {url} />
</Link>
{/if}
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="cl-tip-left" />
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="tooltip-left" />
<ThunkStatusOrDeleted {event} />
{#if showActivity}
<EventActivity {url} {path} {event} />
@@ -1,7 +1,7 @@
<script lang="ts">
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
import CalendarEventForm from "@app/components/CalendarEventForm.svelte"
type Props = {
+2 -2
View File
@@ -14,10 +14,10 @@
{#if !isNaN(start)}
{@const startDate = secondsToDate(start)}
<div
class="clay-card clay-card-sm cl-surface-alt hidden h-32 w-32 min-w-32 flex-col items-center justify-center gap-1 p-2 sm:flex">
class="hidden h-32 w-32 min-w-32 flex-col items-center justify-center gap-1 rounded-box bg-base-300 p-2 sm:flex">
<strong>{Intl.DateTimeFormat(LOCALE, {month: "short"}).format(startDate)}</strong>
<span class="text-4xl">{Intl.DateTimeFormat(LOCALE, {day: "numeric"}).format(startDate)}</span>
<span class="cl-text-muted text-xs"
<span class="text-xs opacity-75"
>{Intl.DateTimeFormat(LOCALE, {weekday: "long"}).format(startDate)}</span>
</div>
{/if}
+3 -3
View File
@@ -1,9 +1,9 @@
<script lang="ts">
import type {TrustedEvent} from "@welshman/util"
import {getTagValue} from "@welshman/util"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
import CalendarEventForm from "@app/components/CalendarEventForm.svelte"
type Props = {
+18 -17
View File
@@ -9,14 +9,14 @@
import GallerySend from "@assets/icons/gallery-send.svg?dataurl"
import MapPoint from "@assets/icons/map-point.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Field from "@lib/components2/Field.svelte"
import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components2/Spinner.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import DateTimeInput from "@lib/components2/DateTimeInput.svelte"
import Icon from "@lib/components/Icon.svelte"
import Field from "@lib/components/Field.svelte"
import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import DateTimeInput from "@lib/components/DateTimeInput.svelte"
import EditorContent from "@app/editor/EditorContent.svelte"
import {PROTECTED, publishRoomQuote} from "@app/groups"
import {makeEditor} from "@app/editor"
@@ -164,8 +164,8 @@
<p>Title*</p>
{/snippet}
{#snippet input()}
<label class="input-cl input-cl-group">
<input bind:value={title} type="text" />
<label class="input input-bordered flex w-full items-center gap-2">
<input bind:value={title} class="grow" type="text" />
</label>
{/snippet}
</Field>
@@ -174,17 +174,18 @@
<p>Summary</p>
{/snippet}
{#snippet input()}
<div class="cl-surface cl-border-t relative z-feature flex gap-2">
<div
class="relative z-feature flex gap-2 border-t border-solid border-base-100 bg-base-100">
<div class="input-editor grow overflow-hidden">
<EditorContent {editor} />
</div>
<Button
data-tip="Add an image"
circle
class="center btn tooltip"
onclick={selectFiles}
disabled={loading}>
{#if $uploading}
<span class="cl-spinner"></span>
<span class="loading loading-spinner loading-xs"></span>
{:else}
<Icon icon={GallerySend} />
{/if}
@@ -213,19 +214,19 @@
<p>Location (optional)</p>
{/snippet}
{#snippet input()}
<label class="input-cl input-cl-group">
<label class="input input-bordered flex w-full items-center gap-2">
<Icon icon={MapPoint} />
<input bind:value={location} type="text" />
<input bind:value={location} class="grow" type="text" />
</label>
{/snippet}
</Field>
</ModalBody>
<ModalFooter>
<Button variant="ghost" onclick={back} disabled={loading}>
<Button class="btn btn-link" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Button type="submit" variant="primary" disabled={$uploading || loading}>
<Button type="submit" class="btn btn-primary" disabled={$uploading || loading}>
<Spinner loading={$uploading || loading}>Save Event</Spinner>
</Button>
</ModalFooter>
@@ -7,8 +7,7 @@
} from "@welshman/lib"
import type {TrustedEvent} from "@welshman/util"
import ClockCircle from "@assets/icons/clock-circle.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Text from "@lib/components2/Text.svelte"
import Icon from "@lib/components/Icon.svelte"
type Props = {
event: TrustedEvent
@@ -21,12 +20,12 @@
</script>
<div class="flex flex-col justify-between gap-1">
<Text size="lg">{meta.title || meta.name}</Text>
<p class="text-lg">{meta.title || meta.name}</p>
{#if !isNaN(start) && !isNaN(end)}
{@const startDateDisplay = formatTimestampAsDate(start)}
{@const endDateDisplay = formatTimestampAsDate(end)}
{@const isSingleDay = startDateDisplay === endDateDisplay}
<div class="cl-text flex flex-wrap gap-2 text-xs">
<div class="flex flex-wrap gap-2 text-xs">
<div class="flex items-center gap-2">
<Icon icon={ClockCircle} size={4} />
{formatTimestampAsDate(start)}
+3 -5
View File
@@ -1,7 +1,7 @@
<script lang="ts">
import type {TrustedEvent} from "@welshman/util"
import {getTagValue, getAddress} from "@welshman/util"
import Link from "@lib/components2/Link.svelte"
import Link from "@lib/components/Link.svelte"
import CalendarEventActions from "@app/components/CalendarEventActions.svelte"
import CalendarEventHeader from "@app/components/CalendarEventHeader.svelte"
import ProfileLink from "@app/components/ProfileLink.svelte"
@@ -18,12 +18,10 @@
const h = getTagValue("h", event.tags)
</script>
<Link
class="cv clay-card clay-card-interactive flex w-full cursor-pointer flex-col gap-3 p-4 sm:p-6"
href={makeCalendarPath(url, getAddress(event))}>
<Link class="cv col-3 card2 w-full cursor-pointer" 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="cl-text-muted whitespace-nowrap py-1 text-sm">
<span class="whitespace-nowrap py-1 text-sm opacity-75">
Posted by <ProfileLink pubkey={event.pubkey} {url} />
{#if h}
in <RoomLink {url} {h} />
+2 -2
View File
@@ -3,7 +3,7 @@
import type {TrustedEvent} from "@welshman/util"
import UserCircle from "@assets/icons/user-circle.svg?dataurl"
import MapPoint from "@assets/icons/map-point.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Icon from "@lib/components/Icon.svelte"
import ProfileLink from "@app/components/ProfileLink.svelte"
type Props = {
@@ -15,7 +15,7 @@
const meta = $derived(fromPairs(event.tags) as Record<string, string>)
</script>
<div class="cl-text-muted flex min-w-0 flex-col gap-1 text-sm">
<div class="flex min-w-0 flex-col gap-1 text-sm opacity-75">
<span class="flex items-center gap-1">
<Icon icon={UserCircle} size={4} />
Posted by <ProfileLink pubkey={event.pubkey} {url} />
+25 -31
View File
@@ -36,16 +36,12 @@
} from "@welshman/app"
import Danger from "@assets/icons/danger-triangle.svg?dataurl"
import ArrowLeft from "@assets/icons/arrow-left.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Spinner from "@lib/components2/Spinner.svelte"
import PageBar from "@lib/components2/PageBar.svelte"
import PageContent from "@lib/components2/PageContent.svelte"
import Divider from "@lib/components2/Divider.svelte"
import Button from "@lib/components2/Button.svelte"
import Row from "@lib/components2/Row.svelte"
import Col from "@lib/components2/Col.svelte"
import Card from "@lib/components2/Card.svelte"
import Text from "@lib/components2/Text.svelte"
import Icon from "@lib/components/Icon.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import PageBar from "@lib/components/PageBar.svelte"
import PageContent from "@lib/components/PageContent.svelte"
import Divider from "@lib/components/Divider.svelte"
import Button from "@lib/components/Button.svelte"
import ProfileName from "@app/components/ProfileName.svelte"
import ProfileLink from "@app/components/ProfileLink.svelte"
import ProfileCircle from "@app/components/ProfileCircle.svelte"
@@ -253,18 +249,18 @@
<Icon icon={ArrowLeft} size={7} />
</Button>
<div class="flex items-center justify-between gap-4">
<div class="flex items-center gap-4 overflow-hidden text-ellipsis whitespace-nowrap">
<div class="ellipsize flex items-center gap-4 whitespace-nowrap">
<Button class="flex flex-col gap-1 sm:flex-row sm:gap-2" onclick={showMembers}>
{#if others.length === 0}
<Row>
<div class="row-2">
<ProfileCircle pubkey={$pubkey!} size={5} />
<ProfileName pubkey={$pubkey!} />
</Row>
</div>
{:else if others.length === 1}
<Row>
<div class="row-2">
<ProfileCircle pubkey={others[0]} size={5} />
<ProfileName pubkey={others[0]} />
</Row>
</div>
{:else}
<div class="flex items-center gap-2">
<ProfileCircles pubkeys={others} size={5} />
@@ -289,21 +285,19 @@
<PageContent class="flex flex-col-reverse gap-2 py-2 !mb-0">
{#if missingRelayLists.length > 0}
<div class="py-12">
<Card class="m-auto max-w-md text-center">
<Col class="items-center">
<Row class="text-lg cl-text-danger">
<Icon icon={Danger} />
Direct messages are not enabled
</Row>
<Text>
Ask
{#each missingRelayLists as pubkey (pubkey)}
<ProfileLink {pubkey} />
{/each}
to enable direct messaging by opening this conversation in their app.
</Text>
</Col>
</Card>
<div class="card2 col-2 m-auto max-w-md items-center text-center">
<p class="row-2 text-lg text-error">
<Icon icon={Danger} />
Direct messages are not enabled
</p>
<p>
Ask
{#each missingRelayLists as pubkey (pubkey)}
<ProfileLink {pubkey} />
{/each}
to enable direct messaging by opening this conversation in their app.
</p>
</div>
</div>
{/if}
{#each elements as { type, id, value, showPubkey } (id)}
@@ -332,7 +326,7 @@
<div class="h-screen"></div>
</PageContent>
<div class="chat__compose cl-surface-alt">
<div class="chat__compose bg-base-200">
<div>
{#if parent}
<ChatComposeParent event={parent} clear={clearParent} verb="Replying to" />
+5 -9
View File
@@ -6,8 +6,8 @@
import {isMobile, preventDefault} from "@lib/html"
import GallerySend from "@assets/icons/gallery-send.svg?dataurl"
import Plane from "@assets/icons/plane-2.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import EditorContent from "@app/editor/EditorContent.svelte"
import {makeEditor} from "@app/editor"
import {type DraftKey} from "@app/drafts"
@@ -112,14 +112,12 @@
<form class="relative z-feature flex gap-2 p-2" onsubmit={preventDefault(submit)}>
<Button
variant="secondary"
circle
data-tip="Add an image"
class="h-10 w-10 min-w-10"
class="center tooltip tooltip-right h-10 w-10 min-w-10 rounded-box bg-base-300 transition-colors hover:bg-base-200"
disabled={$uploading || disabled}
onclick={uploadFiles}>
{#if $uploading}
<span class="cl-spinner"></span>
<span class="loading loading-spinner loading-xs"></span>
{:else}
<Icon icon={GallerySend} />
{/if}
@@ -128,10 +126,8 @@
<EditorContent {autofocus} {editor} />
</div>
<Button
variant="primary"
circle
data-tip="{window.navigator.platform.includes('Mac') ? 'cmd' : 'ctrl'}+enter to send"
class="absolute right-4 h-10 w-10 min-w-10"
class="center tooltip tooltip-left absolute right-4 h-10 w-10 min-w-10 rounded-full"
disabled={$uploading || disabled}
onclick={submit}>
<Icon icon={Plane} />
+4 -5
View File
@@ -1,8 +1,8 @@
<script lang="ts">
import {slide} from "@lib/transition"
import CloseCircle from "@assets/icons/close-circle.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
const {
clear,
@@ -12,10 +12,9 @@
</script>
<div
class="relative flex h-8 items-center justify-between border-l-2 border-solid px-2 pr-7 text-xs cl-surface-alt cl-text-primary"
style="border-left-color: var(--cl-primary);"
class="relative flex h-8 items-center justify-between border-l-2 border-solid border-primary bg-base-300 px-2 pr-7 text-xs"
transition:slide>
<p>Editing message</p>
<p class="text-primary">Editing message</p>
<Button onclick={clear} class="flex items-center">
<Icon icon={CloseCircle} />
</Button>
+4 -5
View File
@@ -3,8 +3,8 @@
import {displayProfileByPubkey} from "@welshman/app"
import {slide} from "@lib/transition"
import CloseCircle from "@assets/icons/close-circle.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import NoteContentMinimal from "@app/components/NoteContentMinimal.svelte"
const {
@@ -19,10 +19,9 @@
</script>
<div
class="relative border-l-2 border-solid px-2 py-1 pr-8 cl-surface-alt"
style="border-left-color: var(--cl-primary);"
class="relative border-l-2 border-solid border-primary bg-base-300 px-2 py-1 pr-8"
transition:slide>
<p class="text-xs cl-text-primary">{verb} @{displayProfileByPubkey(event.pubkey)}</p>
<p class="text-xs text-primary">{verb} @{displayProfileByPubkey(event.pubkey)}</p>
{#key event.id}
<NoteContentMinimal trimParent {event} />
{/key}
+11 -12
View File
@@ -4,15 +4,14 @@
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"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components2/Spinner.svelte"
import Text from "@lib/components2/Text.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.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 ModalFooter from "@lib/components/ModalFooter.svelte"
import {DEFAULT_RELAYS, DEFAULT_MESSAGING_RELAYS} from "@app/env"
import {pushToast} from "@app/toast"
@@ -58,14 +57,14 @@
<ModalHeader>
<ModalTitle>Enable direct messaging?</ModalTitle>
</ModalHeader>
<Text>Direct messaging isn't currently enabled. Would you like to turn it on?</Text>
<p>Direct messaging isn't currently enabled. Would you like to turn it on?</p>
</ModalBody>
<ModalFooter>
<Button variant="ghost" onclick={back}>
<Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Button type="submit" variant="primary" disabled={loading}>
<Button type="submit" class="btn btn-primary" disabled={loading}>
<Spinner {loading}>Enable direct messaging</Spinner>
<Icon icon={AltArrowRight} />
</Button>
+6 -16
View File
@@ -1,9 +1,3 @@
<style>
.chat-item:hover {
background-color: var(--cl-bg-alt);
}
</style>
<script lang="ts">
import {onMount} from "svelte"
import {page} from "$app/stores"
@@ -11,7 +5,7 @@
import type {TrustedEvent} from "@welshman/util"
import {pubkey, loadMessagingRelayList} from "@welshman/app"
import {fade} from "@lib/transition"
import Button from "@lib/components2/Button.svelte"
import Button from "@lib/components/Button.svelte"
import ProfileName from "@app/components/ProfileName.svelte"
import ProfileCircle from "@app/components/ProfileCircle.svelte"
import ProfileCircles from "@app/components/ProfileCircles.svelte"
@@ -41,8 +35,8 @@
<Button class="flex flex-col justify-start gap-1 w-full" onclick={openChat}>
<div
class="chat-item cursor-pointer cl-border-t px-3 py-2 transition-colors {props.class}"
class:cl-surface-alt={active}>
class="cursor-pointer border-t border-solid border-base-100 px-3 py-2 transition-colors hover:bg-base-100 {props.class}"
class:bg-base-100={active}>
<div class="flex flex-col justify-start gap-1">
<div class="flex items-center justify-between gap-2">
<div class="flex min-w-0 items-center gap-2">
@@ -62,22 +56,18 @@
{/if}
</div>
{#if !active && $notifications.has(path)}
<div
class="h-2 w-2 rounded-full"
style="background-color: var(--cl-primary);"
transition:fade>
</div>
<div class="h-2 w-2 rounded-full bg-primary" transition:fade></div>
{/if}
</div>
<p class="overflow-hidden text-ellipsis whitespace-nowrap text-sm">
<span class="cl-text-muted">
<span class="opacity-70">
{#if props.messages[0].pubkey === $pubkey}
You:
{/if}
</span>
{props.messages[0].content}
</p>
<p class="text-xs cl-text-muted">
<p class="text-xs opacity-70">
{formatTimestamp(props.messages[0].created_at)}
</p>
</div>
+9 -10
View File
@@ -1,11 +1,10 @@
<script lang="ts">
import Button from "@lib/components2/Button.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import Card from "@lib/components2/Card.svelte"
import Button from "@lib/components/Button.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import Profile from "@app/components/Profile.svelte"
interface Props {
@@ -22,13 +21,13 @@
</ModalHeader>
<div class="flex flex-col gap-2">
{#each pubkeys as pubkey (pubkey)}
<Card sm pad={false} class="p-3">
<div class="card2 bg-alt">
<Profile {pubkey} />
</Card>
</div>
{/each}
</div>
</ModalBody>
<ModalFooter>
<Button variant="primary" onclick={() => history.back()}>Got it</Button>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button>
</ModalFooter>
</Modal>
+7 -7
View File
@@ -3,10 +3,10 @@
import Check from "@assets/icons/check.svg?dataurl"
import Bell from "@assets/icons/bell.svg?dataurl"
import BellOff from "@assets/icons/bell-off.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import {setChecked} from "@app/notifications"
import {notificationSettings} from "@app/settings"
@@ -23,17 +23,17 @@
<Modal>
<ModalBody>
<div class="flex flex-col gap-2">
<Button variant="secondary" onclick={markAsRead}>
<Button class="btn btn-neutral" onclick={markAsRead}>
<Icon size={5} icon={Check} />
Mark all read
</Button>
{#if $notificationSettings.messages}
<Button variant="secondary" onclick={disableAlerts}>
<Button class="btn btn-neutral" onclick={disableAlerts}>
<Icon size={4} icon={BellOff} />
Disable alerts
</Button>
{:else}
<Button variant="secondary" onclick={enableAlerts}>
<Button class="btn btn-neutral" onclick={enableAlerts}>
<Icon size={4} icon={Bell} />
Enable alerts
</Button>
+15 -10
View File
@@ -5,10 +5,10 @@
import {thunks, mergeThunks, pubkey, deriveProfileDisplay, sendWrapped} from "@welshman/app"
import {isMobile} from "@lib/html"
import MenuDots from "@assets/icons/menu-dots.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Tippy from "@lib/components2/Tippy.svelte"
import TapTarget from "@lib/components2/TapTarget.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import Tippy from "@lib/components/Tippy.svelte"
import TapTarget from "@lib/components/TapTarget.svelte"
import ProfileCircle from "@app/components/ProfileCircle.svelte"
import Content from "@app/components/Content.svelte"
import ReactionSummary from "@app/components/ReactionSummary.svelte"
@@ -71,8 +71,10 @@
{/if}
<div
data-event={event.id}
class="group flex items-center justify-end gap-1 px-2"
class:flex-row-reverse={!isOwn}>
class="group chat flex items-center justify-end gap-1 px-2"
class:chat-start={!isOwn}
class:flex-row-reverse={!isOwn}
class:chat-end={isOwn}>
{#if !isMobile}
<Tippy
bind:popover
@@ -99,13 +101,16 @@
{/if}
<div class="flex min-w-0 flex-col" class:items-end={isOwn}>
<TapTarget
class="cl-surface-alt mx-1 mb-2 flex min-w-[100px] cursor-auto flex-col gap-1 rounded-2xl px-4 py-3 text-left lg:max-w-2xl"
class="bg-alt chat-bubble mx-1 mb-2 flex cursor-auto flex-col gap-1 text-left lg:max-w-2xl min-w-[100px]"
onTap={showMobileMenu}>
{#if showPubkey}
<div class="flex items-center gap-2">
{#if !isOwn}
<Button onclick={openProfile} class="flex items-center gap-1">
<ProfileCircle pubkey={event.pubkey} class="cl-border" size={4} />
<ProfileCircle
pubkey={event.pubkey}
class="border border-solid border-base-content"
size={4} />
<div class="flex items-center gap-2">
<Button onclick={openProfile} class="text-sm font-bold" style="color: {colorValue}">
{$profileDisplay}
@@ -113,7 +118,7 @@
</div>
</Button>
{/if}
<span class="cl-text-subtle whitespace-nowrap text-xs"
<span class="whitespace-nowrap text-xs opacity-50"
>{formatTimestampAsTime(event.created_at)}</span>
</div>
{/if}
@@ -121,7 +126,7 @@
<Content showEntire {event} />
</div>
</TapTarget>
<div class="z-feature -mt-4 ml-4 flex items-center gap-2">
<div class="row-2 z-feature -mt-4 ml-4">
<ReactionSummary {event} {deleteReaction} {createReaction} noTooltip />
</div>
</div>
@@ -3,8 +3,8 @@
import type {TrustedEvent} from "@welshman/util"
import {sendWrapped} from "@welshman/app"
import SmileCircle from "@assets/icons/smile-circle.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import EmojiButton from "@lib/components2/EmojiButton.svelte"
import Icon from "@lib/components/Icon.svelte"
import EmojiButton from "@lib/components/EmojiButton.svelte"
import {makeReaction} from "@app/reactions"
interface Props {
@@ -22,6 +22,6 @@
})
</script>
<EmojiButton {onEmoji} class="btn-cl-sm">
<EmojiButton {onEmoji} class="btn join-item btn-xs">
<Icon icon={SmileCircle} size={4} />
</EmojiButton>
+7 -8
View File
@@ -1,7 +1,6 @@
<script lang="ts">
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Row from "@lib/components2/Row.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import ChatMessageEmojiButton from "@app/components/ChatMessageEmojiButton.svelte"
import EventInfo from "@app/components/EventInfo.svelte"
import {pushModal} from "@app/modal"
@@ -20,19 +19,19 @@
}
</script>
<Row gap={1} class="cl-surface cl-border rounded-full px-1 py-1 text-xs">
<div class="join border border-solid border-neutral text-xs">
<ChatMessageEmojiButton {event} {pubkeys} />
{#if replyTo}
<Button size="sm" circle onclick={reply}>
<Button class="btn join-item btn-xs" onclick={reply}>
<Icon size={4} icon={Reply} />
</Button>
{/if}
{#if edit}
<Button size="sm" circle onclick={onEdit}>
<Button class="btn join-item btn-xs" onclick={onEdit}>
<Icon size={4} icon={Pen} />
</Button>
{/if}
<Button size="sm" circle onclick={showInfo}>
<Button class="btn join-item btn-xs" onclick={showInfo}>
<Icon size={4} icon={Code2} />
</Button>
</Row>
</div>
+12 -13
View File
@@ -7,12 +7,11 @@
import Reply from "@assets/icons/reply-2.svg?dataurl"
import Copy from "@assets/icons/copy.svg?dataurl"
import Code2 from "@assets/icons/code-2.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import Button from "@lib/components2/Button.svelte"
import Col from "@lib/components2/Col.svelte"
import EmojiPicker from "@lib/components2/EmojiPicker.svelte"
import Icon from "@lib/components/Icon.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import Button from "@lib/components/Button.svelte"
import EmojiPicker from "@lib/components/EmojiPicker.svelte"
import EventInfo from "@app/components/EventInfo.svelte"
import {makeReaction} from "@app/reactions"
import {pushModal} from "@app/modal"
@@ -58,29 +57,29 @@
<Modal>
<ModalBody>
<Col gap={2}>
<Button variant="secondary" onclick={showInfo}>
<div class="flex flex-col gap-2">
<Button class="btn btn-neutral" onclick={showInfo}>
<Icon size={4} icon={Code2} />
Message Info
</Button>
<Button variant="secondary" block onclick={copyText}>
<Button class="btn btn-neutral w-full" onclick={copyText}>
<Icon size={4} icon={Copy} />
Copy Text
</Button>
<Button variant="secondary" block onclick={sendReply}>
<Button class="btn btn-neutral w-full" onclick={sendReply}>
<Icon size={4} icon={Reply} />
Send Reply
</Button>
{#if edit}
<Button variant="secondary" block onclick={sendEdit}>
<Button class="btn btn-neutral w-full" onclick={sendEdit}>
<Icon size={4} icon={Pen} />
Edit Message
</Button>
{/if}
<Button variant="primary" block onclick={showEmojiPicker}>
<Button class="btn btn-primary w-full" onclick={showEmojiPicker}>
<Icon size={4} icon={SmileCircle} />
Send Reaction
</Button>
</Col>
</div>
</ModalBody>
</Modal>
+11 -11
View File
@@ -6,17 +6,17 @@
import {fromNostrURI} from "@welshman/util"
import {loadMessagingRelayList} from "@welshman/app"
import {preventDefault} from "@lib/html"
import Field from "@lib/components2/Field.svelte"
import Button from "@lib/components2/Button.svelte"
import Field from "@lib/components/Field.svelte"
import Button from "@lib/components/Button.svelte"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.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 ProfileMultiSelect from "@app/components/ProfileMultiSelect.svelte"
import {goToChat} from "@app/routes"
@@ -73,11 +73,11 @@
</Field>
</ModalBody>
<ModalFooter>
<Button variant="ghost" onclick={back}>
<Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Button type="submit" variant="primary" disabled={pubkeys.length === 0}>
<Button type="submit" class="btn btn-primary" disabled={pubkeys.length === 0}>
Create Chat
<Icon icon={AltArrowRight} />
</Button>
+7 -10
View File
@@ -5,10 +5,9 @@
import {pubkey} from "@welshman/app"
import Pen2 from "@assets/icons/pen-2.svg?dataurl"
import {normalizeTopic} from "@lib/util"
import Link from "@lib/components2/Link.svelte"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Badge from "@lib/components2/Badge.svelte"
import Link from "@lib/components/Link.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import RoomName from "@app/components/RoomName.svelte"
import ReactionSummary from "@app/components/ReactionSummary.svelte"
import ClassifiedStatus from "@app/components/ClassifiedStatus.svelte"
@@ -47,20 +46,18 @@
<div class="flex grow flex-wrap justify-end gap-2">
{#if h && showRoom}
<Link href={makeSpacePath(url, h)}>
<Badge variant="neutral" sm>
Posted in #<RoomName {h} {url} />
</Badge>
<Link href={makeSpacePath(url, h)} class="btn btn-neutral btn-xs rounded-full">
Posted in #<RoomName {h} {url} />
</Link>
{/if}
<div class="flex min-w-0 flex-wrap gap-2">
{#each uniq(topics) as topic (topic)}
<button type="button" class="badge-cl badge-cl-neutral badge-cl-sm">
<button type="button" class="btn btn-xs rounded-full font-normal">
#{normalizeTopic(topic)}
</button>
{/each}
</div>
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="cl-tip-left" />
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="tooltip-left" />
<ThunkStatusOrDeleted {event}>
<ClassifiedStatus {event} />
</ThunkStatusOrDeleted>
+3 -3
View File
@@ -1,7 +1,7 @@
<script lang="ts">
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
import ClassifiedForm from "@app/components/ClassifiedForm.svelte"
type Props = {
+3 -3
View File
@@ -2,9 +2,9 @@
import {fromPairs} from "@welshman/lib"
import type {TrustedEvent} from "@welshman/util"
import {getTag, getTagValues} from "@welshman/util"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
import ClassifiedForm from "@app/components/ClassifiedForm.svelte"
type Props = {
+29 -28
View File
@@ -6,18 +6,14 @@
import {isMobile, preventDefault} from "@lib/html"
import {normalizeTopic} from "@lib/util"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Field from "@lib/components2/Field.svelte"
import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components2/Spinner.svelte"
import Col from "@lib/components2/Col.svelte"
import Grid from "@lib/components2/Grid.svelte"
import Input from "@lib/components2/Input.svelte"
import Select from "@lib/components2/Select.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ImagesInput from "@lib/components2/ImagesInput.svelte"
import Icon from "@lib/components/Icon.svelte"
import Field from "@lib/components/Field.svelte"
import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ImagesInput from "@lib/components/ImagesInput.svelte"
import CurrencyInput from "@app/components/CurrencyInput.svelte"
import TopicMultiSelect from "@app/components/TopicMultiSelect.svelte"
import EditorContent from "@app/editor/EditorContent.svelte"
@@ -168,18 +164,21 @@
<Modal tag="form" onsubmit={preventDefault(submit)}>
<ModalBody>
{@render header?.()}
<Col gap={8} class="relative">
<div class="col-8 relative">
<Field>
{#snippet label()}
<p>Title*</p>
{/snippet}
{#snippet input()}
<!-- svelte-ignore a11y_autofocus -->
<Input
autofocus={!isMobile}
bind:value={title}
type="text"
placeholder="What is this listing for?" />
<label class="input input-bordered flex w-full items-center gap-2">
<!-- svelte-ignore a11y_autofocus -->
<input
autofocus={!isMobile}
bind:value={title}
class="grow"
type="text"
placeholder="What is this listing for?" />
</label>
{/snippet}
</Field>
<Field>
@@ -205,10 +204,12 @@
<p>Price*</p>
{/snippet}
{#snippet input()}
<Grid cols={2} gap={2}>
<Input bind:value={price} type="number" />
<CurrencyInput bind:value={currency} />
</Grid>
<div class="join grid grid-cols-2">
<label class="join-item input input-bordered flex w-full items-center gap-2">
<input bind:value={price} class="grow w-32" type="number" />
</label>
<CurrencyInput class="join-item" bind:value={currency} />
</div>
{/snippet}
</Field>
{#if initialValues}
@@ -217,10 +218,10 @@
<p>Status*</p>
{/snippet}
{#snippet input()}
<Select bind:value={status}>
<select class="select select-bordered w-full" bind:value={status}>
<option value="active">Active</option>
<option value="sold">Sold</option>
</Select>
</select>
{/snippet}
</Field>
{/if}
@@ -232,14 +233,14 @@
<ImagesInput bind:value={images} />
{/snippet}
</Field>
</Col>
</div>
</ModalBody>
<ModalFooter>
<Button variant="ghost" onclick={back} disabled={loading}>
<Button class="btn btn-link" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Button type="submit" variant="primary" disabled={loading}>
<Button type="submit" class="btn btn-primary" disabled={loading}>
<Spinner {loading}>Save Listing</Spinner>
</Button>
</ModalFooter>
+7 -7
View File
@@ -2,8 +2,8 @@
import {formatTimestamp} from "@welshman/lib"
import type {TrustedEvent} from "@welshman/util"
import {getTag, getAddress, getTagValue, getTagValues} from "@welshman/util"
import Link from "@lib/components2/Link.svelte"
import CurrencySymbol from "@lib/components2/CurrencySymbol.svelte"
import Link from "@lib/components/Link.svelte"
import CurrencySymbol from "@lib/components/CurrencySymbol.svelte"
import ContentLinkBlock from "@app/components/ContentLinkBlock.svelte"
import Content from "@app/components/Content.svelte"
import ProfileLink from "@app/components/ProfileLink.svelte"
@@ -25,20 +25,20 @@
</script>
<Link
class="clay-card cl-surface-alt flex w-full cursor-pointer flex-col gap-2 p-4 sm:p-6"
class="cv col-2 card2 w-full cursor-pointer"
href={makeClassifiedPath(url, getAddress(event))}>
{#if title}
<div class="flex w-full items-center justify-between gap-2">
<p class="cl-text text-xl">
<p class="text-xl">
{title}
<CurrencySymbol code={currency} />{price}
</p>
<p class="cl-text-muted text-sm">
<p class="text-sm opacity-75">
{formatTimestamp(event.created_at)}
</p>
</div>
{:else}
<p class="cl-text-muted mb-3 h-0 text-xs">
<p class="mb-3 h-0 text-xs opacity-75">
{formatTimestamp(event.created_at)}
</p>
{/if}
@@ -49,7 +49,7 @@
{/each}
</div>
<div class="flex w-full flex-col items-end justify-between gap-2 sm:flex-row">
<span class="cl-text-muted whitespace-nowrap py-1 text-sm">
<span class="whitespace-nowrap py-1 text-sm opacity-75">
Posted by
<ProfileLink pubkey={event.pubkey} {url} />
{#if h}
+3 -3
View File
@@ -1,8 +1,8 @@
<script lang="ts">
import cx from "classnames"
import type {TrustedEvent} from "@welshman/util"
import {getTagValue} from "@welshman/util"
import {ucFirst} from "@lib/util"
import Badge from "@lib/components2/Badge.svelte"
type Props = {
event: TrustedEvent
@@ -14,7 +14,7 @@
</script>
{#if status}
<Badge sm variant={status !== "active" ? "primary" : "neutral"}>
<div class={cx("btn btn-xs rounded-full", {"btn-primary": status !== "active"})}>
{ucFirst(status)}
</Badge>
</div>
{/if}
+1 -1
View File
@@ -31,7 +31,7 @@
<div class="flex flex-wrap items-center justify-between gap-2">
<div class="flex grow flex-wrap justify-end gap-2">
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="cl-tip-left" />
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="tooltip-left" />
<ThunkStatusOrDeleted {event} />
{#if showActivity}
<EventActivity {url} {path} {event} />
+8 -8
View File
@@ -5,8 +5,8 @@
import NotesMinimalistic from "@assets/icons/notes-minimalistic.svg?dataurl"
import CaseMinimalistic from "@assets/icons/case-minimalistic.svg?dataurl"
import Revote from "@assets/icons/revote.svg?dataurl"
import Button from "@lib/components2/Button.svelte"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import Icon from "@lib/components/Icon.svelte"
import {pushModal} from "@app/modal"
import CalendarEventCreate from "@app/components/CalendarEventCreate.svelte"
import ThreadCreate from "@app/components/ThreadCreate.svelte"
@@ -39,33 +39,33 @@
})
</script>
<ul class="clay-card flex flex-col gap-1 whitespace-nowrap p-2" bind:this={ul}>
<ul class="menu whitespace-nowrap rounded-box bg-base-100 p-2 shadow-md" bind:this={ul}>
<li>
<Button block class="justify-start" onclick={createGoal}>
<Button onclick={createGoal}>
<Icon size={4} icon={StarFallMinimalistic} />
Funding Goal
</Button>
</li>
<li>
<Button block class="justify-start" onclick={createCalendarEvent}>
<Button onclick={createCalendarEvent}>
<Icon size={4} icon={CalendarMinimalistic} />
Calendar Event
</Button>
</li>
<li>
<Button block class="justify-start" onclick={createClassified}>
<Button onclick={createClassified}>
<Icon size={4} icon={CaseMinimalistic} />
Classified Listing
</Button>
</li>
<li>
<Button block class="justify-start" onclick={createThread}>
<Button onclick={createThread}>
<Icon size={4} icon={NotesMinimalistic} />
Create Thread
</Button>
</li>
<li>
<Button block class="justify-start" onclick={createPoll}>
<Button onclick={createPoll}>
<Icon size={4} icon={Revote} />
Ask a Question
</Button>
+15 -16
View File
@@ -21,12 +21,10 @@
} from "@welshman/content"
import type {Parsed} from "@welshman/content"
import {preventDefault, stopPropagation} from "@lib/html"
import Link from "@lib/components2/Link.svelte"
import Link from "@lib/components/Link.svelte"
import Danger from "@assets/icons/danger-triangle.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Alert from "@lib/components2/Alert.svelte"
import Row from "@lib/components2/Row.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import ContentToken from "@app/components/ContentToken.svelte"
import ContentEmoji from "@app/components/ContentEmoji.svelte"
import ContentEmail from "@app/components/ContentEmail.svelte"
@@ -146,15 +144,13 @@
<div class="relative">
{#if warning}
<Alert variant="warning">
<Row gap={2}>
<Icon icon={Danger} />
<p>
This note has been flagged by the author as "{warning}".<br />
<Button class="cl-link" onclick={ignoreWarning}>Show anyway</Button>
</p>
</Row>
</Alert>
<div class="card2 card2-sm bg-alt row-2">
<Icon icon={Danger} />
<p>
This note has been flagged by the author as "{warning}".<br />
<Button class="link" onclick={ignoreWarning}>Show anyway</Button>
</p>
</div>
{:else}
<div
class="overflow-hidden text-ellipsis wrap-break-word"
@@ -208,9 +204,12 @@
</div>
{#if expandBlock}
<div class="relative z-feature -mt-6 flex justify-center py-2">
<Button variant="secondary" onclick={stopPropagation(preventDefault(expand))}>
<button
type="button"
class="btn btn-neutral"
onclick={stopPropagation(preventDefault(expand))}>
See more
</Button>
</button>
</div>
{/if}
{/if}
+1 -1
View File
@@ -3,7 +3,7 @@
</script>
<code
class="cl-surface-alt cl-text w-full overflow-auto whitespace-pre rounded px-1"
class="w-full overflow-auto whitespace-pre rounded bg-neutral px-1 text-neutral-content"
class:block={isBlock}>
{value.trim()}
</code>
+2 -2
View File
@@ -1,7 +1,7 @@
<script lang="ts">
import LinkRound from "@assets/icons/link-round.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Link from "@lib/components2/Link.svelte"
import Icon from "@lib/components/Icon.svelte"
import Link from "@lib/components/Link.svelte"
export let value: string
</script>
+12 -20
View File
@@ -3,8 +3,7 @@
import {isRelayUrl, getTagValue} from "@welshman/util"
import {Capacitor} from "@capacitor/core"
import {preventDefault, stopPropagation} from "@lib/html"
import Link from "@lib/components2/Link.svelte"
import Center from "@lib/components2/Center.svelte"
import Link from "@lib/components/Link.svelte"
import ContentLinkDetail from "@app/components/ContentLinkDetail.svelte"
import ContentLinkUrl from "@app/components/ContentLinkUrl.svelte"
import ContentLinkBlockImage from "@app/components/ContentLinkBlockImage.svelte"
@@ -54,45 +53,38 @@
{#if isRoomOrRelay}
<div>
<ContentLinkUrl
{url}
class="cl-surface-alt cl-text inline-block max-w-full overflow-hidden text-ellipsis whitespace-nowrap rounded px-1" />
<ContentLinkUrl {url} class="link-content whitespace-nowrap" />
</div>
{:else}
<Link {external} {href} class="my-2 block">
<div class="overflow-hidden" style="border-radius: var(--cl-r-card)">
<div class="overflow-hidden rounded-box">
{#if url.match(/\.(mov|webm|mp4)$/) || VIDEO_CONTENT_TYPES.includes(fileType)}
<video
controls
src={url}
poster={getVideoPoster(url)}
preload="metadata"
class="max-h-96 object-contain object-center"
style="border-radius: var(--cl-r-card)">
class="max-h-96 rounded-box object-contain object-center">
<track kind="captions" />
</video>
{:else if url.match(/\.(jpe?g|png|gif|webp)$/) || IMAGE_CONTENT_TYPES.includes(fileType)}
<button type="button" onclick={stopPropagation(preventDefault(expand))}>
<ContentLinkBlockImage
{value}
{event}
class="m-auto max-h-96"
style="border-radius: var(--cl-r-card)" />
<ContentLinkBlockImage {value} {event} class="m-auto max-h-96 rounded-box" />
</button>
{:else}
{#await loadPreview()}
<Center class="my-12 w-full">
<span class="cl-spinner"></span>
</Center>
<div class="center my-12 w-full">
<span class="loading loading-spinner"></span>
</div>
{:then preview}
<div class="cl-surface-alt flex max-w-xl flex-col leading-normal">
<div
class="border border-solid border-base-content/20 flex max-w-xl flex-col leading-normal rounded-box">
{#if preview.image && !hideImage}
<img
alt=""
onerror={onError}
src={preview.image}
class="cl-surface-alt max-h-72 object-contain object-center"
style="border-top-left-radius: var(--cl-r-card); border-top-right-radius: var(--cl-r-card)" />
class="bg-alt max-h-72 rounded-t-box object-contain object-center" />
{/if}
<div class="flex flex-col gap-2 p-4">
<strong class="overflow-hidden text-ellipsis whitespace-nowrap"
@@ -101,7 +93,7 @@
</div>
</div>
{:catch}
<p class="cl-surface-alt p-12 text-center leading-normal">
<p class="border border-solid border-base-content/20 p-12 text-center leading-normal">
Unable to load a preview for {url}
</p>
{/await}
@@ -11,7 +11,7 @@
} from "@welshman/util"
import {signer} from "@welshman/app"
import LinkRound from "@assets/icons/link-round.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Icon from "@lib/components/Icon.svelte"
const {value, event, ...props} = $props()
@@ -87,9 +87,7 @@
</script>
{#if hasError}
<a
href={url}
class="cl-surface-alt inline-flex max-w-full items-center gap-1 overflow-hidden rounded px-1 whitespace-nowrap text-ellipsis">
<a href={url} class="link-content whitespace-nowrap">
<Icon icon={LinkRound} size={3} class="inline-block" />
{displayUrl(url)}
</a>
+2 -6
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import ContentLinkBlockImage from "@app/components/ContentLinkBlockImage.svelte"
import Button from "@lib/components2/Button.svelte"
import Button from "@lib/components/Button.svelte"
const {value, event} = $props()
@@ -8,9 +8,5 @@
</script>
<Button class="m-auto h-screen w-screen cursor-pointer p-4" onclick={back}>
<ContentLinkBlockImage
{value}
{event}
class="m-auto max-h-full max-w-full"
style="border-radius: var(--cl-r-card);" />
<ContentLinkBlockImage {value} {event} class="m-auto max-h-full max-w-full rounded-box" />
</Button>
+3 -5
View File
@@ -3,7 +3,7 @@
import {getTagValue} from "@welshman/util"
import {preventDefault, stopPropagation} from "@lib/html"
import LinkRound from "@assets/icons/link-round.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Icon from "@lib/components/Icon.svelte"
import ContentLinkDetail from "@app/components/ContentLinkDetail.svelte"
import ContentLinkUrl from "@app/components/ContentLinkUrl.svelte"
import {pushModal} from "@app/modal"
@@ -21,13 +21,11 @@
<!-- Use a real link so people can copy the href -->
<a
href={url}
class="cl-surface-alt inline-flex max-w-full items-center gap-1 overflow-hidden rounded px-1 whitespace-nowrap text-ellipsis"
class="link-content whitespace-nowrap"
onclick={stopPropagation(preventDefault(expand))}>
<Icon icon={LinkRound} size={3} class="inline-block" />
{displayUrl(url)}
</a>
{:else}
<ContentLinkUrl
{url}
class="cl-surface-alt inline-flex max-w-full items-center gap-1 overflow-hidden rounded px-1 whitespace-nowrap text-ellipsis" />
<ContentLinkUrl {url} class="link-content whitespace-nowrap" />
{/if}
+4 -4
View File
@@ -2,8 +2,8 @@
import {call, displayUrl} from "@welshman/lib"
import {displayRelayUrl, isRelayUrl, normalizeRelayUrl} from "@welshman/util"
import LinkRound from "@assets/icons/link-round.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Link from "@lib/components2/Link.svelte"
import Icon from "@lib/components/Icon.svelte"
import Link from "@lib/components/Link.svelte"
import {PLATFORM_URL} from "@app/env"
import {displayRoom, isRoomId, splitRoomId} from "@app/groups"
import {makeRoomPath, makeSpacePath} from "@app/routes"
@@ -49,10 +49,10 @@
<Link {external} {href} class={className}>
{#if roomReference}
~<span class="cl-text-primary">{displayRelayUrl(roomReference.url)}</span> /
~<span class="text-primary">{displayRelayUrl(roomReference.url)}</span> /
{displayRoom(roomReference.url, roomReference.h)}
{:else if relayReference}
<span class="cl-text-primary">{displayRelayUrl(relayReference)}</span>
<span class="text-primary">{displayRelayUrl(relayReference)}</span>
{:else}
<Icon icon={LinkRound} size={3} class="inline-block" />
{displayUrl(url)}
+2 -2
View File
@@ -2,7 +2,7 @@
import {removeUndefined} from "@welshman/lib"
import type {ProfilePointer} from "@welshman/content"
import {deriveProfileDisplay} from "@welshman/app"
import Button from "@lib/components2/Button.svelte"
import Button from "@lib/components/Button.svelte"
import ProfileDetail from "@app/components/ProfileDetail.svelte"
import {pushModal} from "@app/modal"
@@ -18,6 +18,6 @@
const openProfile = () => pushModal(ProfileDetail, {pubkey: value.pubkey, url})
</script>
<Button onclick={openProfile} class="cl-link">
<Button onclick={openProfile} class="link-content">
@{$display}
</Button>
+19 -10
View File
@@ -1,4 +1,5 @@
<script lang="ts">
import cx from "classnames"
import {fromNostrURI} from "@welshman/util"
import {nthEq} from "@welshman/lib"
import {
@@ -19,11 +20,10 @@
isNewline,
} from "@welshman/content"
import type {Parsed} from "@welshman/content"
import Link from "@lib/components2/Link.svelte"
import Link from "@lib/components/Link.svelte"
import Danger from "@assets/icons/danger-triangle.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Alert from "@lib/components2/Alert.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import ContentToken from "@app/components/ContentToken.svelte"
import ContentEmoji from "@app/components/ContentEmoji.svelte"
import ContentEmail from "@app/components/ContentEmail.svelte"
@@ -38,10 +38,11 @@
interface Props {
event: any
trimParent?: boolean
singleLine?: boolean
url?: string
}
const {event, trimParent = false, url}: Props = $props()
const {event, trimParent = false, singleLine = false, url}: Props = $props()
const fullContent = parse(event)
@@ -97,18 +98,26 @@
<div class="relative">
{#if warning}
<Alert variant="warning" class="items-center">
<div class="card2 card2-sm bg-alt row-2">
<Icon icon={Danger} />
<p>
This note has been flagged by the author as "{warning}".<br />
<Button class="cl-link" onclick={ignoreWarning}>Show anyway</Button>
<Button class="link" onclick={ignoreWarning}>Show anyway</Button>
</p>
</Alert>
</div>
{:else}
<div class="overflow-hidden text-ellipsis wrap-break-word">
<div
class={cx(
"overflow-hidden text-ellipsis",
singleLine ? "whitespace-nowrap" : "wrap-break-word",
)}>
{#each shortContent as parsed, i}
{#if isNewline(parsed)}
<ContentNewline value={parsed.value} />
{#if singleLine}
{" "}
{:else}
<ContentNewline value={parsed.value} />
{/if}
{:else if isTopic(parsed)}
<ContentTopic value={parsed.value} />
{:else if isEmoji(parsed)}
+12 -10
View File
@@ -3,8 +3,8 @@
import {Router} from "@welshman/router"
import type {TrustedEvent} from "@welshman/util"
import {Address, MESSAGE} from "@welshman/util"
import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components2/Spinner.svelte"
import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import NoteCard from "@app/components/NoteCard.svelte"
import NoteContent from "@app/components/NoteContent.svelte"
import NoteContentMinimal from "@app/components/NoteContentMinimal.svelte"
@@ -48,19 +48,21 @@
<NoteContent {url} event={$quote} />
{:else if $quote.kind === MESSAGE}
<div
class="cl-surface-alt py-1 pl-2 opacity-90"
style="border-left: 2px solid var(--cl-primary);">
class="border-l-2 border-solid border-l-primary py-1 pl-2 opacity-90"
style="background-color: color-mix(in srgb, var(--color-primary) 10%, var(--color-base-300) 90%);">
<NoteContentMinimal trimParent {url} event={$quote} />
</div>
{:else}
<div class="cl-surface-alt overflow-hidden" style="border-radius: var(--cl-r-card);">
<NoteCard noShadow event={$quote} {url} class="p-4">
<NoteContentMinimal {url} event={$quote} />
</NoteCard>
</div>
<NoteCard
noShadow
event={$quote}
{url}
class="border border-solid border-base-content/20 rounded-box p-4">
<NoteContentMinimal {url} event={$quote} />
</NoteCard>
{/if}
{:else}
<div class="cl-surface-alt p-4" style="border-radius: var(--cl-r-card);">
<div class="rounded-box p-4">
<Spinner loading>Loading event...</Spinner>
</div>
{/if}
+3 -3
View File
@@ -1,7 +1,7 @@
<script lang="ts">
import Bolt from "@assets/icons/bolt.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import {clip} from "@app/toast"
const {value} = $props()
@@ -9,7 +9,7 @@
const copy = () => clip(value)
</script>
<Button onclick={copy} variant="secondary" size="sm" class="max-w-full truncate align-middle">
<Button onclick={copy} class="link-content">
<Icon icon={Bolt} size={3} class="inline-block translate-y-px" />
{value.slice(0, 16)}...
</Button>
+2 -4
View File
@@ -1,9 +1,7 @@
<script lang="ts">
import Badge from "@lib/components2/Badge.svelte"
const {value} = $props()
</script>
<Badge variant="neutral">
<span class="link-content">
#{value}
</Badge>
</span>
+10 -6
View File
@@ -6,11 +6,11 @@
import {preventDefault} from "@lib/html"
import {createSearch} from "@welshman/app"
import {currencyOptions, displayCurrency} from "@lib/currency"
import Suggestions from "@lib/components2/Suggestions.svelte"
import Suggestions from "@lib/components/Suggestions.svelte"
import CurrencySuggestion from "@app/components/CurrencySuggestion.svelte"
import AltArrowDown from "@assets/icons/alt-arrow-down.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Tippy from "@lib/components2/Tippy.svelte"
import Icon from "@lib/components/Icon.svelte"
import Tippy from "@lib/components/Tippy.svelte"
interface Props {
value: string
@@ -66,18 +66,22 @@
</script>
<button
class={cx(props.class, "input-cl input-cl-group cursor-pointer", {"cl-surface-alt": currency})}
class={cx(
props.class,
{"bg-base-200": currency},
"input input-bordered flex items-center gap-2 cursor-pointer",
)}
bind:this={wrapper}
onfocus={preventDefault(clearAndFocus)}
onclick={preventDefault(clearAndFocus)}>
<Icon icon={AltArrowDown} />
{#if currency}
<span class="overflow-hidden text-ellipsis whitespace-nowrap text-sm">
<span class="text-sm ellipsize whitespace-nowrap">
{displayCurrency(currency)}
</span>
{:else}
<!-- svelte-ignore a11y_autofocus -->
<input {autofocus} class="input-cl-bare grow" type="text" bind:value={$term} onkeydown={onKeyDown} />
<input {autofocus} class="grow" type="text" bind:value={$term} onkeydown={onKeyDown} />
{/if}
<Tippy
bind:popover
@@ -0,0 +1,79 @@
<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>
+9 -10
View File
@@ -6,12 +6,11 @@
import Bolt from "@assets/icons/bolt.svg?dataurl"
import SmileCircle from "@assets/icons/smile-circle.svg?dataurl"
import MenuDots from "@assets/icons/menu-dots.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Tippy from "@lib/components2/Tippy.svelte"
import Button from "@lib/components2/Button.svelte"
import Row from "@lib/components2/Row.svelte"
import Icon from "@lib/components/Icon.svelte"
import Tippy from "@lib/components/Tippy.svelte"
import Button from "@lib/components/Button.svelte"
import ZapButton from "@app/components/ZapButton.svelte"
import EmojiButton from "@lib/components2/EmojiButton.svelte"
import EmojiButton from "@lib/components/EmojiButton.svelte"
import EventMenu from "@app/components/EventMenu.svelte"
import {ENABLE_ZAPS} from "@app/env"
import {publishReaction} from "@app/reactions"
@@ -44,13 +43,13 @@
let popover: Instance | undefined = $state()
</script>
<Row gap={1} class="cl-surface-alt cl-border rounded-full px-1 py-1">
<div class="join items-center rounded-full">
{#if ENABLE_ZAPS && !hideZap}
<ZapButton {url} {event} class="btn-cl-sm">
<ZapButton {url} {event} class="btn join-item btn-neutral btn-xs">
<Icon icon={Bolt} size={4} />
</ZapButton>
{/if}
<EmojiButton {onEmoji} class="btn-cl-sm">
<EmojiButton {onEmoji} class="btn join-item btn-neutral btn-xs">
<Icon icon={SmileCircle} size={4} />
</EmojiButton>
<Tippy
@@ -59,8 +58,8 @@
component={EventMenu}
props={{url, noun, event, customActions, onClick: hidePopover}}
params={{trigger: "manual", interactive: true}}>
<Button class="btn-cl-sm" onclick={showPopover}>
<Button class="btn join-item btn-neutral btn-xs" onclick={showPopover}>
<Icon icon={MenuDots} size={4} />
</Button>
</Tippy>
</Row>
</div>
+7 -8
View File
@@ -8,8 +8,7 @@
import {repository} from "@welshman/app"
import {deriveChecked} from "@app/notifications"
import Reply from "@assets/icons/reply-2.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Badge from "@lib/components2/Badge.svelte"
import Icon from "@lib/components/Icon.svelte"
const {url, path, event}: {url: string; path: string; event: TrustedEvent} = $props()
@@ -23,13 +22,13 @@
})
</script>
<Badge sm>
<Icon icon={Reply} size={4} />
<div class="flex-inline btn btn-neutral btn-xs gap-1 rounded-full">
<Icon icon={Reply} />
<span>{$replies.length} {$replies.length === 1 ? "reply" : "replies"}</span>
</Badge>
<Badge sm>
</div>
<div class="btn btn-neutral btn-xs relative rounded-full">
{#if gt(lastActive, $checked)}
<div class="h-2 w-2 rounded-full" style="background-color: var(--cl-primary);"></div>
<div class="h-2 w-2 rounded-full bg-primary"></div>
{/if}
Active {formatTimestampRelative(lastActive)}
</Badge>
</div>
+1 -1
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import type {TrustedEvent} from "@welshman/util"
import Confirm from "@lib/components2/Confirm.svelte"
import Confirm from "@lib/components/Confirm.svelte"
import {publishDelete} from "@app/deletes"
import {canEnforceNip70} from "@app/relays"
import {clearModals} from "@app/modal"
+20 -22
View File
@@ -8,16 +8,15 @@
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"
import Icon from "@lib/components2/Icon.svelte"
import FieldInline from "@lib/components2/FieldInline.svelte"
import Button from "@lib/components2/Button.svelte"
import Badge from "@lib/components2/Badge.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import Icon from "@lib/components/Icon.svelte"
import FieldInline from "@lib/components/FieldInline.svelte"
import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
import {clip} from "@app/toast"
type Props = {
@@ -61,13 +60,13 @@
<p>Event Link</p>
{/snippet}
{#snippet input()}
<div class="input-cl input-cl-group w-full">
<label class="input input-bordered flex w-full items-center gap-2">
<Icon icon={FileText} />
<input type="text" class="input-cl-bare overflow-hidden text-ellipsis" value={nevent1} />
<input type="text" class="ellipsize min-w-0 grow" value={nevent1} />
<Button onclick={copyLink} class="flex items-center">
<Icon icon={Copy} />
</Button>
</div>
</label>
{/snippet}
</FieldInline>
<FieldInline>
@@ -75,13 +74,13 @@
<p>Author Pubkey</p>
{/snippet}
{#snippet input()}
<div class="input-cl input-cl-group w-full">
<label class="input input-bordered flex w-full items-center gap-2">
<Icon icon={UserCircle} />
<input type="text" class="input-cl-bare overflow-hidden text-ellipsis" value={npub1} />
<input type="text" class="ellipsize min-w-0 grow" value={npub1} />
<Button onclick={copyPubkey} class="flex items-center">
<Icon icon={Copy} />
</Button>
</div>
</label>
{/snippet}
</FieldInline>
{#if !url && seenOn.size > 0}
@@ -92,25 +91,24 @@
{#snippet input()}
<div class="flex flex-wrap gap-2">
{#each seenOn as url, i (url)}
<Badge>
<span class="bg-alt badge flex gap-1">
{displayRelayUrl(url)}
</Badge>
</span>
{/each}
</div>
{/snippet}
</FieldInline>
{/if}
<div class="relative">
<pre
class="cl-surface-alt cl-border overflow-auto rounded-2xl p-4 text-xs"><code>{json}</code></pre>
<pre class="card2 card2-sm bg-alt overflow-auto text-xs"><code>{json}</code></pre>
<p class="absolute right-2 top-2 flex grow items-center justify-between">
<Button variant="secondary" size="sm" onclick={copyJson} class="flex items-center">
<Button onclick={copyJson} class="btn btn-neutral btn-sm flex items-center">
<Icon icon={Copy} /> Copy
</Button>
</p>
</div>
</ModalBody>
<ModalFooter>
<Button variant="primary" class="grow" onclick={() => history.back()}>Got it</Button>
<Button class="btn btn-primary grow" onclick={() => history.back()}>Got it</Button>
</ModalFooter>
</Modal>
+34 -24
View File
@@ -10,9 +10,9 @@
import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl"
import Danger from "@assets/icons/danger.svg?dataurl"
import {setKey} from "@lib/implicit"
import Button from "@lib/components2/Button.svelte"
import Confirm from "@lib/components2/Confirm.svelte"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import Confirm from "@lib/components/Confirm.svelte"
import Icon from "@lib/components/Icon.svelte"
import EventInfo from "@app/components/EventInfo.svelte"
import Report from "@app/components/Report.svelte"
import EventShare from "@app/components/EventShare.svelte"
@@ -78,33 +78,43 @@
})
</script>
<div class="clay-card flex flex-col gap-1 whitespace-nowrap p-2" bind:this={ul}>
<ul class="menu whitespace-nowrap rounded-box bg-base-100 p-2 shadow-md" bind:this={ul}>
{#if isRoot}
<Button block onclick={share}>
<Icon size={4} icon={ShareCircle} />
Share to Chat
</Button>
<li>
<Button onclick={share}>
<Icon size={4} icon={ShareCircle} />
Share to Chat
</Button>
</li>
{/if}
<Button block onclick={showInfo}>
<Icon size={4} icon={Code2} />
{noun} Details
</Button>
<li>
<Button onclick={showInfo}>
<Icon size={4} icon={Code2} />
{noun} Details
</Button>
</li>
{@render customActions?.()}
{#if event.pubkey === $pubkey}
<Button block variant="danger" onclick={showDelete}>
<Icon size={4} icon={TrashBin2} />
Delete {noun}
</Button>
{:else}
<Button block variant="danger" onclick={report}>
<Icon size={4} icon={Danger} />
Report Content
</Button>
{#if $userIsAdmin}
<Button block variant="danger" onclick={showAdminDelete}>
<li>
<Button onclick={showDelete} class="text-error">
<Icon size={4} icon={TrashBin2} />
Delete {noun}
</Button>
</li>
{:else}
<li>
<Button class="text-error" onclick={report}>
<Icon size={4} icon={Danger} />
Report Content
</Button>
</li>
{#if $userIsAdmin}
<li>
<Button class="text-error" onclick={showAdminDelete}>
<Icon size={4} icon={TrashBin2} />
Delete {noun}
</Button>
</li>
{/if}
{/if}
</div>
</ul>
+7 -8
View File
@@ -5,8 +5,8 @@
import {isMobile, preventDefault} from "@lib/html"
import {fly} from "@lib/transition"
import Paperclip from "@assets/icons/paperclip-2.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import EditorContent from "@app/editor/EditorContent.svelte"
import ChatComposeParent from "@app/components/ChatComposeParent.svelte"
import {publishComment} from "@app/comments"
@@ -101,7 +101,7 @@
bind:this={form}
onsubmit={preventDefault(submit)}
class="left-content bottom-sai right-sai fixed z-feature mb-14 md:mb-0 w-full md:w-auto pr-2">
<div class="clay-card mx-2 my-2 p-4">
<div class="card2 mx-2 my-2 bg-alt shadow-md">
{#if parent}
<ChatComposeParent event={parent} clear={() => onClearParent?.()} verb="Replying to" />
{/if}
@@ -111,19 +111,18 @@
</div>
<Button
data-tip="Add an image"
circle
class="absolute bottom-1 right-2"
class="tooltip tooltip-left absolute bottom-1 right-2"
onclick={selectFiles}>
{#if $uploading}
<span class="cl-spinner"></span>
<span class="loading loading-spinner loading-xs"></span>
{:else}
<Icon icon={Paperclip} size={3} />
{/if}
</Button>
</div>
<div class="flex justify-between pt-3">
<Button onclick={onClose}>Cancel</Button>
<Button type="submit" variant="primary">Post Reply</Button>
<Button class="btn btn-link" onclick={onClose}>Cancel</Button>
<Button type="submit" class="btn btn-primary">Post Reply</Button>
</div>
</div>
</form>
+16 -13
View File
@@ -5,14 +5,14 @@
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import {setKey} from "@lib/implicit"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.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 Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import RoomName from "@app/components/RoomName.svelte"
import {roomsByUrl} from "@app/groups"
import {makeRoomPath} from "@app/routes"
@@ -41,20 +41,23 @@
</ModalHeader>
<div class="grid grid-cols-3 gap-2">
{#each $roomsByUrl.get(url) || [] as room (room.h)}
<Button
variant={selection === room.h ? "primary" : "secondary"}
<button
type="button"
class="btn"
class:btn-neutral={selection !== room.h}
class:btn-primary={selection === room.h}
onclick={() => toggleRoom(room.h)}>
#<RoomName {...room} />
</Button>
</button>
{/each}
</div>
</ModalBody>
<ModalFooter>
<Button onclick={back}>
<Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Button type="submit" variant="primary" disabled={!selection}>
<Button type="submit" class="btn btn-primary" disabled={!selection}>
Share {noun}
<Icon icon={AltArrowRight} />
</Button>
+3 -3
View File
@@ -1,7 +1,7 @@
<script lang="ts">
import type {TrustedEvent, EventContent} from "@welshman/util"
import {getTagValue} from "@welshman/util"
import Link from "@lib/components2/Link.svelte"
import Link from "@lib/components/Link.svelte"
import ReactionSummary from "@app/components/ReactionSummary.svelte"
import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte"
import EventActivity from "@app/components/EventActivity.svelte"
@@ -34,11 +34,11 @@
<div class="flex grow flex-wrap justify-end gap-2">
{#if h && showRoom}
<Link href={makeSpacePath(url, h)} class="badge-cl badge-cl-neutral badge-cl-sm">
<Link href={makeSpacePath(url, h)} class="btn btn-neutral btn-xs rounded-full">
Posted in #<RoomName {h} {url} />
</Link>
{/if}
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="cl-tip-left" />
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="tooltip-left" />
<ThunkStatusOrDeleted {event} />
{#if showActivity}
<EventActivity {url} {path} {event} />
+22 -22
View File
@@ -6,17 +6,17 @@
import Paperclip from "@assets/icons/paperclip-2.svg?dataurl"
import Bolt from "@assets/icons/bolt.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Field from "@lib/components2/Field.svelte"
import FieldInline from "@lib/components2/FieldInline.svelte"
import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components2/Spinner.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import Icon from "@lib/components/Icon.svelte"
import Field from "@lib/components/Field.svelte"
import FieldInline from "@lib/components/FieldInline.svelte"
import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.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 Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import EditorContent from "@app/editor/EditorContent.svelte"
import {pushToast} from "@app/toast"
import {PROTECTED, publishRoomQuote} from "@app/groups"
@@ -145,17 +145,18 @@
<ModalTitle>Create a Funding Goal</ModalTitle>
<ModalSubtitle>Request contributions for your fundraiser.</ModalSubtitle>
</ModalHeader>
<div class="relative flex flex-col gap-8">
<div class="col-8 relative">
<Field>
{#snippet label()}
<p>Title*</p>
{/snippet}
{#snippet input()}
<label class="input-cl input-cl-group">
<label class="input input-bordered flex w-full items-center gap-2">
<!-- svelte-ignore a11y_autofocus -->
<input
autofocus={!isMobile}
bind:value={title}
class="grow"
type="text"
placeholder="What do funds go towards?" />
</label>
@@ -174,11 +175,11 @@
</Field>
<Button
data-tip="Add an image"
class="absolute bottom-1 right-2"
class="tooltip tooltip-left absolute bottom-1 right-2"
onclick={selectFiles}
disabled={loading}>
{#if $uploading}
<span class="cl-spinner"></span>
<span class="loading loading-spinner loading-xs"></span>
{:else}
<Icon icon={Paperclip} size={3} />
{/if}
@@ -191,17 +192,16 @@
{/snippet}
{#snippet input()}
<div class="flex grow justify-end">
<label class="input-cl input-cl-group w-auto">
<label class="input input-bordered flex w-auto items-center gap-2">
<Icon icon={Bolt} />
<input bind:value={amount} type="number" class="input-cl-bare w-28" />
<p class="cl-text-subtle shrink-0">sats</p>
<input bind:value={amount} type="number" class="w-28 grow" />
<p class="shrink-0 opacity-50">sats</p>
</label>
</div>
{/snippet}
</FieldInline>
<input
class="-mt-2 w-full"
style="accent-color: var(--cl-primary);"
class="range range-primary -mt-2 w-full"
type="range"
min="1000"
max="100000"
@@ -211,11 +211,11 @@
</div>
</ModalBody>
<ModalFooter>
<Button variant="ghost" onclick={back} disabled={loading}>
<Button class="btn btn-link" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Button type="submit" variant="primary" disabled={$uploading || loading}>
<Button type="submit" class="btn btn-primary" disabled={$uploading || loading}>
<Spinner {loading}>Create Goal</Spinner>
</Button>
</ModalFooter>
+19 -26
View File
@@ -1,9 +1,7 @@
<script lang="ts">
import type {TrustedEvent} from "@welshman/util"
import {getTagValue} from "@welshman/util"
import Link from "@lib/components2/Link.svelte"
import Col from "@lib/components2/Col.svelte"
import Text from "@lib/components2/Text.svelte"
import Link from "@lib/components/Link.svelte"
import Content from "@app/components/Content.svelte"
import ProfileLink from "@app/components/ProfileLink.svelte"
import GoalActions from "@app/components/GoalActions.svelte"
@@ -22,27 +20,22 @@
const h = getTagValue("h", event.tags)
</script>
<Link class="w-full" href={makeGoalPath(url, event.id)}>
<Col
gap={2}
class="clay-card clay-card-interactive cl-surface-alt w-full p-4 sm:p-6"
style="content-visibility: auto;">
<p class="text-2xl">{event.content}</p>
<Content
event={{content: summary, tags: event.tags}}
{url}
expandMode="inline"
minLength={50}
maxLength={300} />
<GoalSummary {url} {event} />
<div class="flex w-full flex-col items-end justify-between gap-2 sm:flex-row">
<Text size="sm" muted class="whitespace-nowrap py-1">
Posted by <ProfileLink pubkey={event.pubkey} {url} />
{#if h}
in <RoomLink {url} {h} />
{/if}
</Text>
<GoalActions showActivity {url} {event} />
</div>
</Col>
<Link class="cv col-2 card2 w-full cursor-pointer" href={makeGoalPath(url, event.id)}>
<p class="text-2xl">{event.content}</p>
<Content
event={{content: summary, tags: event.tags}}
{url}
expandMode="inline"
minLength={50}
maxLength={300} />
<GoalSummary {url} {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">
Posted by <ProfileLink pubkey={event.pubkey} {url} />
{#if h}
in <RoomLink {url} {h} />
{/if}
</span>
<GoalActions showActivity {url} {event} />
</div>
</Link>
+19 -16
View File
@@ -5,11 +5,7 @@
import {deriveItemsByKey, deriveArray} from "@welshman/store"
import {repository, getValidZap} from "@welshman/app"
import Bolt from "@assets/icons/bolt.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Stat from "@lib/components2/Stat.svelte"
import Row from "@lib/components2/Row.svelte"
import Col from "@lib/components2/Col.svelte"
import Progress from "@lib/components2/Progress.svelte"
import Icon from "@lib/components/Icon.svelte"
import ZapButton from "@app/components/ZapButton.svelte"
type Props = {
@@ -35,17 +31,24 @@
const daysOld = Math.ceil((now() - event.created_at) / DAY)
</script>
<Col gap={8} class={props.class}>
<Row gap={8} class="items-start">
<Stat value="{zapAmount} sats" label="funded of {goalAmount} sats" gradient />
<Stat
value={contributorsCount}
label={contributorsCount === 1 ? "contributor" : "contributors"} />
<Stat value={daysOld} label="{daysOld === 1 ? 'day' : 'days'} old" />
</Row>
<Progress value={zapAmount} max={goalAmount} />
<ZapButton {url} {event} class="btn-cl btn-cl-primary lg:m-auto lg:px-20">
<div class="flex flex-col gap-8 {props.class}">
<div class="flex gap-8">
<div>
<p class="text-xl text-primary">{zapAmount} sats</p>
<p class="text-sm opacity-75">funded of {goalAmount} sats</p>
</div>
<div>
<p class="text-xl">{contributorsCount}</p>
<p class="text-sm opacity-75">{contributorsCount === 1 ? "contributor" : "contributors"}</p>
</div>
<div>
<p class="text-xl">{daysOld}</p>
<p class="text-sm opacity-75">{daysOld === 1 ? "day" : "days"} old</p>
</div>
</div>
<progress class="progress progress-primary" value={zapAmount} max={goalAmount}></progress>
<ZapButton {url} {event} class="btn btn-primary lg:m-auto lg:px-20">
<Icon icon={Bolt} />
Contribute to this goal
</ZapButton>
</Col>
</div>
+5 -17
View File
@@ -1,18 +1,6 @@
<style>
.icon-tile {
color: var(--cl-text);
border-radius: var(--cl-r-icon);
transition: all 0.2s ease;
}
.icon-tile:hover {
background: var(--cl-primary);
color: var(--cl-primary-content);
}
</style>
<script lang="ts">
import {createSearch} from "@welshman/app"
import Icon from "@lib/components2/Icon.svelte"
import Icon from "@lib/components/Icon.svelte"
import Magnifier from "@assets/icons/magnifier.svg?dataurl"
const iconModules = import.meta.glob("@assets/icons/*.svg", {
@@ -55,9 +43,9 @@
}
</script>
<label class="input-cl input-cl-group">
<label class="input input-bordered flex w-full items-center gap-2">
<Icon icon={Magnifier} />
<input bind:value={searchTerm} class="input-cl-bare" type="text" placeholder="Search icons..." />
<input bind:value={searchTerm} class="grow" type="text" placeholder="Search icons..." />
</label>
<div class="mt-2 max-h-80 overflow-y-auto">
<div class="grid grid-cols-8 gap-2 p-2">
@@ -65,9 +53,9 @@
<button
type="button"
title={icon.name}
class="icon-tile flex aspect-square items-center justify-center"
class="flex aspect-square items-center justify-center rounded-box transition-colors hover:bg-primary hover:text-primary-content"
onclick={() => handleSelect(icon.url)}>
<Icon icon={icon.url} size={6} />
<Icon icon={icon.url} class="h-6 w-6" />
</button>
{/each}
</div>
+2 -2
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import IconPicker from "@app/components/IconPicker.svelte"
type Props = {
+2 -3
View File
@@ -1,5 +1,4 @@
<script lang="ts">
import Card from "@lib/components2/Card.svelte"
import IconPicker from "@app/components/IconPicker.svelte"
type Props = {
@@ -9,6 +8,6 @@
const {onSelect}: Props = $props()
</script>
<Card class="w-96">
<div class="w-96 rounded-box bg-base-100 p-4 shadow-2xl">
<IconPicker {onSelect} />
</Card>
</div>
+27 -28
View File
@@ -1,42 +1,41 @@
<script lang="ts">
import Link from "@lib/components2/Link.svelte"
import Button from "@lib/components2/Button.svelte"
import Text from "@lib/components2/Text.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import Link from "@lib/components/Link.svelte"
import Button from "@lib/components/Button.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 {PLATFORM_NAME} from "@app/env"
</script>
<Modal>
<ModalBody>
<Modal
><ModalBody>
<ModalHeader>
<ModalTitle>What is a bunker link?</ModalTitle>
</ModalHeader>
<Text>
<Link external styled href="https://nostr.com/">Nostr</Link> uses "keys" instead of passwords
to identify users. This allows users to own their social identity instead of renting it from a
tech company, and can bring it with them from app to app.
</Text>
<Text>
A good way to manage your keys is to use a remote signing application. These apps can hold your
keys and log you in remotely to as many applications as you like, without risking loss or theft
of your keys.
</Text>
<Text>
<p>
<Link external class="link" href="https://nostr.com/">Nostr</Link> uses "keys" instead of passwords
to identify users. This allows users to own their social identity instead of renting it from a tech
company, and can bring it with them from app to app.
</p>
<p>
A good way to manage your keys is to use a remote signing application. These apps can hold
your keys and log you in remotely to as many applications as you like, without risking loss or
theft of your keys.
</p>
<p>
One way to log in with a remote signer is using a "bunker link" which is more secure and
decentralized than other solutions. Check your signer for a link beginning with "bunker://",
copy it into {PLATFORM_NAME}, and you should be good to go!
</Text>
<Text>
If you don't have a signer yet, <Link external styled href="https://nsec.app/">nsec.app</Link>
</p>
<p>
If you don't have a signer yet, <Link external class="link" href="https://nsec.app/"
>nsec.app</Link>
is a great way to get started. You can find more signers on <Link
external
styled
class="link"
href="https://nostrapps.com#signers">nostrapps.com</Link
>.
</Text>
<Button variant="primary" onclick={() => history.back()}>Got it</Button>
</ModalBody>
</Modal>
</p>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button>
</ModalBody></Modal>
+19 -19
View File
@@ -1,31 +1,31 @@
<script lang="ts">
import Button from "@lib/components2/Button.svelte"
import Link from "@lib/components2/Link.svelte"
import Text from "@lib/components2/Text.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import Button from "@lib/components/Button.svelte"
import Link from "@lib/components/Link.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 {PLATFORM_NAME} from "@app/env"
</script>
<Modal>
<ModalBody>
<Modal
><ModalBody>
<ModalHeader>
<ModalTitle>What is a nostr address?</ModalTitle>
</ModalHeader>
<Text>
{PLATFORM_NAME} hosts spaces on the <Link external styled href="https://nostr.com/"
<p>
{PLATFORM_NAME} hosts spaces on the <Link external href="https://nostr.com/" class="underline"
>Nostr protocol</Link
>. Nostr uses "nostr addresses" to make it easier for people to find you, without having to
memorize your public key (your user id).
</Text>
<Text>
</p>
<p>
There are several providers of nostr addresses, including several clients. You can find a list
and more information on <Link external styled href="https://nostr.how/en/guides/get-verified"
>nostr.how</Link
and more information on <Link
external
href="https://nostr.how/en/guides/get-verified"
class="underline">nostr.how</Link
>.
</Text>
<Button variant="primary" onclick={() => history.back()}>Got it</Button>
</ModalBody>
</Modal>
</p>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button>
</ModalBody></Modal>
+19 -20
View File
@@ -1,16 +1,15 @@
<script lang="ts">
import {session} from "@welshman/app"
import Link from "@lib/components2/Link.svelte"
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"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Text from "@lib/components2/Text.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.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 ModalFooter from "@lib/components/ModalFooter.svelte"
import KeyRecoveryRequest from "@app/components/KeyRecoveryRequest.svelte"
import {PLATFORM_NAME} from "@app/env"
import {pushModal} from "@app/modal"
@@ -25,36 +24,36 @@
<ModalHeader>
<ModalTitle>What is a private key?</ModalTitle>
</ModalHeader>
<Text>
<p>
Most online services keep track of users by giving them a username and password. This gives
the service <strong>total control</strong> over their users, allowing them to ban them at any time,
or sell their activity.
</Text>
<Text>
On <Link external styled href="https://nostr.com/">Nostr</Link>, <strong>you</strong> control your
</p>
<p>
On <Link external href="https://nostr.com/">Nostr</Link>, <strong>you</strong> control your
own identity and social data, through the magic of cryptography. The basic idea is that you
have a
<strong>public key</strong>, which acts as your user ID, and a
<strong>private key</strong> which allows you to prove your identity.
</Text>
</p>
{#if $session?.email}
<Text>
<p>
It's very important to keep private keys safe, but this can sometimes be tricky, which is
why {PLATFORM_NAME}
supports a traditional account-based login for new users.
</Text>
<Text>If you'd like to switch to self-custody, please click below to get started.</Text>
</p>
<p>If you'd like to switch to self-custody, please click below to get started.</p>
{:else}
<Button variant="primary" onclick={back}>Got it</Button>
<Button class="btn btn-primary" onclick={back}>Got it</Button>
{/if}
</ModalBody>
{#if $session?.email}
<ModalFooter>
<Button onclick={back}>
<Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Button variant="primary" onclick={startRecoveryRequest}>
<Button class="btn btn-primary" onclick={startRecoveryRequest}>
<Icon icon={CheckCircle} />
I want to hold my own keys
</Button>
+16 -17
View File
@@ -1,11 +1,10 @@
<script lang="ts">
import Link from "@lib/components2/Link.svelte"
import Button from "@lib/components2/Button.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import Text from "@lib/components2/Text.svelte"
import Link from "@lib/components/Link.svelte"
import Button from "@lib/components/Button.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"
</script>
<Modal
@@ -13,21 +12,21 @@
<ModalHeader>
<ModalTitle>What is nostr?</ModalTitle>
</ModalHeader>
<Text>
<Link external styled href="https://nostr.com/">Nostr</Link> is way to build social apps that
<p>
<Link external href="https://nostr.com/" class="link">Nostr</Link> is way to build social apps that
talk to each other. Users own their social identity instead of renting it from a tech company, and
can take it with them.
</Text>
<Text>
</p>
<p>
If you'd like to learn more about what other apps exist in the nostr ecosystem, please visit <Link
external
styled
class="link"
href="https://nostrapps.com/">nostrapps.com</Link
>.
</Text>
<Text>
</p>
<p>
To learn more about how to manage your keys, or to set up an account, try
<Link external styled href="https://nosta.me/">nosta.me</Link>.
</Text>
<Button variant="primary" onclick={() => history.back()}>Got it</Button>
<Link external class="link" href="https://nosta.me/">nosta.me</Link>.
</p>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button>
</ModalBody></Modal>
+13 -14
View File
@@ -1,12 +1,11 @@
<script lang="ts">
import Button from "@lib/components2/Button.svelte"
import Link from "@lib/components2/Link.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import Text from "@lib/components2/Text.svelte"
import Button from "@lib/components/Button.svelte"
import Link from "@lib/components/Link.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import {PLATFORM_NAME} from "@app/env"
</script>
@@ -15,19 +14,19 @@
<ModalHeader>
<ModalTitle>What is a relay?</ModalTitle>
</ModalHeader>
<Text>
{PLATFORM_NAME} hosts spaces on the <Link external styled href="https://nostr.com/"
<p>
{PLATFORM_NAME} hosts spaces on the <Link external href="https://nostr.com/" class="underline"
>Nostr protocol</Link
>. Nostr uses "relays" to host data, which are special-purpose servers that speak nostr's
language. This means that anyone can host their own data, making the web more decentralized
and resilient.
</Text>
<Text>
</p>
<p>
Different relays have different policies for access control and content retention. Be sure to
double check that you have access to the relays you try to use by visiting their website.
</Text>
</p>
</ModalBody>
<ModalFooter>
<Button variant="primary" onclick={() => history.back()}>Got it</Button>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button>
</ModalFooter>
</Modal>
+14 -15
View File
@@ -1,11 +1,10 @@
<script lang="ts">
import Link from "@lib/components2/Link.svelte"
import Button from "@lib/components2/Button.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import Text from "@lib/components2/Text.svelte"
import Link from "@lib/components/Link.svelte"
import Button from "@lib/components/Button.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"
const back = () => history.back()
</script>
@@ -15,21 +14,21 @@
<ModalHeader>
<ModalTitle>What are digital signatures?</ModalTitle>
</ModalHeader>
<Text>
<p>
Most online services ask their users to trust them that they're being honest, and they usually
are. However, traditional social media platforms have the ability to <strong
>create forged content</strong> that can appear to be genuinely authored, but which are actually
counterfeit.
</Text>
<Text>
On <Link external styled href="https://nostr.com/">Nostr</Link>, all your content is authenticated
</p>
<p>
On <Link external href="https://nostr.com/">Nostr</Link>, all your content is authenticated
using <strong>digital signatures</strong>, which cryptographically tie a particular person to
a given post or message.
</Text>
<Text>
</p>
<p>
The result is that you don't normally have to trust service providers not to tamper with the
information flowing through the network — instead, your client software can prove that a given
piece of data is authentic.
</Text>
<Button variant="primary" onclick={back}>Got it</Button>
</p>
<Button class="btn btn-primary" onclick={back}>Got it</Button>
</ModalBody></Modal>
+9 -9
View File
@@ -1,13 +1,13 @@
<script lang="ts">
import {deriveZapperForPubkey} from "@welshman/app"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ProfileLink from "@app/components/ProfileLink.svelte"
const {pubkey} = $props()
@@ -23,7 +23,7 @@
<ModalTitle>Unable to Zap</ModalTitle>
</ModalHeader>
<p>
Zapping <ProfileLink {pubkey} class="cl-text-primary" /> isn't possible right now because
Zapping <ProfileLink {pubkey} class="text-primary!" /> isn't possible right now because
{#if $zapper}
their zap receiver isn't correctly set up.
{:else}
@@ -32,7 +32,7 @@
</p>
</ModalBody>
<ModalFooter>
<Button variant="ghost" onclick={back}>
<Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
@@ -4,7 +4,7 @@
import CloseCircle from "@assets/icons/close-circle.svg?dataurl"
import AddCircle from "@assets/icons/add-circle.svg?dataurl"
import GallerySend from "@assets/icons/gallery-send.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Icon from "@lib/components/Icon.svelte"
import {uploadFile} from "@app/uploads"
interface Props {
@@ -79,28 +79,28 @@
<label
for={id}
aria-label="Drag and drop files here."
style="background-image: url({url}); background-color: var(--cl-bg-alt); border-color: {active
? 'var(--cl-primary)'
: 'var(--cl-border)'};"
class="relative flex h-24 w-24 shrink-0 cursor-pointer items-center justify-center rounded-full border-2 border-solid bg-cover bg-center transition-all"
style="background-image: url({url});"
class="relative flex h-24 w-24 shrink-0 cursor-pointer items-center justify-center rounded-full border-2 border-solid border-base-content bg-base-300 bg-cover bg-center transition-all"
class:transparent={!url}
class:border-primary={active}
ondragenter={stopPropagation(preventDefault(onDragEnter))}
ondragover={stopPropagation(preventDefault(onDragOver))}
ondragleave={stopPropagation(preventDefault(onDragLeave))}
ondrop={stopPropagation(preventDefault(onDrop))}>
<div
class="absolute right-0 top-0 h-5 w-5 overflow-hidden rounded-full"
style="background-color: {url ? 'var(--cl-danger)' : 'var(--cl-primary)'};">
class="absolute right-0 top-0 h-5 w-5 overflow-hidden rounded-full bg-primary"
class:bg-error={url}
class:bg-primary={!url}>
{#if url}
<span
role="button"
tabindex="-1"
onmousedown={stopPropagation(onClear)}
ontouchstart={stopPropagation(onClear)}>
<Icon icon={CloseCircle} class="scale-150 cl-surface-alt" />
<Icon icon={CloseCircle} class="scale-150 bg-base-300!" />
</span>
{:else}
<Icon icon={AddCircle} class="scale-150 cl-surface-alt" />
<Icon icon={AddCircle} class="scale-150 bg-base-300!" />
{/if}
</div>
{#if !url}
+15 -15
View File
@@ -7,14 +7,14 @@
import ArrowDown from "@assets/icons/arrow-down.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Field from "@lib/components2/Field.svelte"
import Button from "@lib/components2/Button.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Icon from "@lib/components/Icon.svelte"
import Field from "@lib/components/Field.svelte"
import Button from "@lib/components/Button.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 ModalFooter from "@lib/components/ModalFooter.svelte"
import ProgressBar from "@app/components/ProgressBar.svelte"
import {pushToast} from "@app/toast"
import {PLATFORM_NAME} from "@app/env"
@@ -129,9 +129,9 @@
Password*
{/snippet}
{#snippet input()}
<label class="input-cl input-cl-group w-full">
<label class="input input-bordered flex w-full items-center gap-2">
<Icon icon={Key} />
<input bind:value={password} onchange={onPasswordChange} type="password" />
<input bind:value={password} onchange={onPasswordChange} class="grow" type="password" />
</label>
{/snippet}
{#snippet info()}
@@ -139,12 +139,12 @@
{/snippet}
</Field>
{/if}
<div class="flex flex-col gap-2">
<Button variant={didDownload ? "secondary" : "primary"} onclick={downloadKey}>
<div class="flex flex-col">
<Button class="btn {didDownload ? 'btn-neutral' : 'btn-primary'}" onclick={downloadKey}>
Download my key
<Icon icon={ArrowDown} />
</Button>
<Button variant="ghost" onclick={toggleUsePassword}>
<Button class="btn btn-link no-underline" onclick={toggleUsePassword}>
{#if usePassword}
Nevermind, I want to download the plain version
{:else}
@@ -157,11 +157,11 @@
<ProgressBar current={step} total={totalSteps} />
{/if}
<ModalFooter>
<Button variant="ghost" onclick={back}>
<Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Button disabled={!didDownload} variant="primary" type="submit">
<Button disabled={!didDownload} class="btn btn-primary" type="submit">
{submitText}
<Icon icon={AltArrowRight} />
</Button>
+12 -12
View File
@@ -6,16 +6,16 @@
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"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components2/Spinner.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import StringMultiInput from "@lib/components2/StringMultiInput.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.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 StringMultiInput from "@lib/components/StringMultiInput.svelte"
import KeyDownload from "@app/components/KeyDownload.svelte"
import {pushToast} from "@app/toast"
import {pushModal, clearModals} from "@app/modal"
@@ -87,11 +87,11 @@
<StringMultiInput bind:value={otps} placeholder="Enter your recovery codes..." />
</ModalBody>
<ModalFooter>
<Button variant="ghost" onclick={back}>
<Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Button type="submit" variant="primary" disabled={loading || otps.length < 2}>
<Button type="submit" class="btn btn-primary" disabled={loading || otps.length < 2}>
<Spinner {loading}>Confirm recovery</Spinner>
<Icon icon={AltArrowRight} />
</Button>
+11 -11
View File
@@ -5,15 +5,15 @@
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"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components2/Spinner.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.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 {pushModal} from "@app/modal"
import KeyRecoveryConfirm from "@app/components/KeyRecoveryConfirm.svelte"
@@ -59,11 +59,11 @@
</p>
</ModalBody>
<ModalFooter>
<Button variant="ghost" onclick={back}>
<Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Button type="submit" variant="primary" disabled={loading}>
<Button type="submit" class="btn btn-primary" disabled={loading}>
<Spinner {loading}>Request recovery</Spinner>
<Icon icon={AltArrowRight} />
</Button>
+15 -17
View File
@@ -1,14 +1,12 @@
<script lang="ts">
import Login from "@assets/icons/login-3.svg?dataurl"
import AddCircle from "@assets/icons/add-circle.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Link from "@lib/components2/Link.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import CardButton from "@lib/components2/CardButton.svelte"
import Heading from "@lib/components2/Heading.svelte"
import Text from "@lib/components2/Text.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import Link from "@lib/components/Link.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import CardButton from "@lib/components/CardButton.svelte"
import LogIn from "@app/components/LogIn.svelte"
import SignUp from "@app/components/SignUp.svelte"
import {PLATFORM_TERMS, PLATFORM_PRIVACY, PLATFORM_NAME} from "@app/env"
@@ -22,11 +20,11 @@
<Modal>
<ModalBody>
<div class="py-2">
<Heading level={1} class="text-center">Welcome to {PLATFORM_NAME}!</Heading>
<Text class="text-center">The chat app built for self-hosted communities.</Text>
<h1 class="heading">Welcome to {PLATFORM_NAME}!</h1>
<p class="text-center">The chat app built for self-hosted communities.</p>
</div>
<Button onclick={logIn} block class="!p-0">
<CardButton>
<Button onclick={logIn}>
<CardButton class="btn-primary">
{#snippet icon()}
<div><Icon icon={Login} size={7} /></div>
{/snippet}
@@ -38,7 +36,7 @@
{/snippet}
</CardButton>
</Button>
<Button onclick={signUp} block class="!p-0">
<Button onclick={signUp} class="btn-neutral">
<CardButton>
{#snippet icon()}
<div><Icon icon={AddCircle} size={7} /></div>
@@ -51,10 +49,10 @@
{/snippet}
</CardButton>
</Button>
<Text size="sm" muted class="text-center">
<p class="text-center text-xs opacity-75">
By using {PLATFORM_NAME}, you consent to our
<Link external styled href={PLATFORM_TERMS}>Terms of Service</Link> and
<Link external styled href={PLATFORM_PRIVACY}>Privacy Policy</Link>.
</Text>
<Link external class="link" href={PLATFORM_TERMS}>Terms of Service</Link> and
<Link external class="link" href={PLATFORM_PRIVACY}>Privacy Policy</Link>.
</p>
</ModalBody>
</Modal>
+23 -27
View File
@@ -8,13 +8,11 @@
import Cpu from "@assets/icons/cpu-bolt.svg?dataurl"
import Compass from "@assets/icons/compass-big.svg?dataurl"
import Key from "@assets/icons/key.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Link from "@lib/components2/Link.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import Button from "@lib/components2/Button.svelte"
import Heading from "@lib/components2/Heading.svelte"
import Text from "@lib/components2/Text.svelte"
import Icon from "@lib/components/Icon.svelte"
import Link from "@lib/components/Link.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import Button from "@lib/components/Button.svelte"
import SignUp from "@app/components/SignUp.svelte"
import InfoNostr from "@app/components/InfoNostr.svelte"
import LogInBunker from "@app/components/LogInBunker.svelte"
@@ -96,17 +94,16 @@
<Modal>
<ModalBody>
<Heading level={1} class="text-center">Log in with Nostr</Heading>
<Text class="m-auto max-w-sm text-center">
<h1 class="heading">Log in with Nostr</h1>
<p class="m-auto max-w-sm text-center">
{PLATFORM_NAME} is built using the
<Button variant="ghost" class="inline cl-link" onclick={() => pushModal(InfoNostr)}
>nostr protocol</Button
>, which allows you to own your social identity.
</Text>
<Button class="link" onclick={() => pushModal(InfoNostr)}>nostr protocol</Button>, which
allows you to own your social identity.
</p>
{#if getNip07()}
<Button variant="primary" block {disabled} onclick={loginWithNip07}>
<Button {disabled} onclick={loginWithNip07} class="btn btn-primary">
{#if loading === "nip07"}
<span class="cl-spinner mr-3"></span>
<span class="loading loading-spinner mr-3"></span>
{:else}
<Icon icon={Widget} />
{/if}
@@ -114,9 +111,9 @@
</Button>
{/if}
{#each signers as app}
<Button variant="primary" block {disabled} onclick={() => loginWithNip55(app)}>
<Button {disabled} class="btn btn-primary" onclick={() => loginWithNip55(app)}>
{#if loading === "nip55"}
<span class="cl-spinner mr-3"></span>
<span class="loading loading-spinner mr-3"></span>
{:else}
<img src={app.iconUrl} alt={app.name} width="20" height="20" />
{/if}
@@ -124,27 +121,26 @@
</Button>
{/each}
{#if hasPomade && !hasSigner}
<Button variant="primary" block {disabled} onclick={loginWithEmail}>
<Button {disabled} onclick={loginWithEmail} class="btn btn-primary">
<Icon icon={Letter} />
Log in with Email
</Button>
{/if}
<Button
variant={hasSigner || hasPomade ? "secondary" : "primary"}
block
onclick={loginWithBunker}
{disabled}>
{disabled}
class="btn {hasSigner || hasPomade ? 'btn-neutral' : 'btn-primary'}">
<Icon icon={Cpu} />
Log in with Remote Signer
</Button>
{#if hasPomade && hasSigner}
<Button variant="ghost" block {disabled} onclick={loginWithEmail}>
<Button {disabled} onclick={loginWithEmail} class="btn">
<Icon icon={Letter} />
Log in with Email
</Button>
{/if}
{#if !hasSigner}
<Button variant="secondary" block {disabled} onclick={loginWithKey}>
<Button {disabled} onclick={loginWithKey} class="btn btn-neutral">
<Icon icon={Key} />
Log in with Key
</Button>
@@ -154,14 +150,14 @@
external
{disabled}
href="https://nostrapps.com#signers"
class="btn-cl btn-cl-block {hasSigner || hasPomade ? 'btn-cl-ghost' : 'btn-cl-secondary'}">
class="btn {hasSigner || hasPomade ? '' : 'btn-neutral'}">
<Icon icon={Compass} />
Browse Signer Apps
</Link>
{/if}
<Text size="sm">
<div class="text-sm">
Need an account?
<Button variant="ghost" class="inline cl-link" onclick={signUp}>Register instead</Button>
</Text>
<Button class="link" onclick={signUp}>Register instead</Button>
</div>
</ModalBody>
</Modal>
+13 -13
View File
@@ -6,17 +6,17 @@
import {makeSecret} from "@welshman/util"
import {loginWithNip01, loginWithNip46} from "@welshman/app"
import {preventDefault} from "@lib/html"
import Spinner from "@lib/components2/Spinner.svelte"
import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import Button from "@lib/components/Button.svelte"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.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 BunkerConnect from "@app/components/BunkerConnect.svelte"
import BunkerUrl from "@app/components/BunkerUrl.svelte"
import {Nip46Controller} from "@app/nip46"
@@ -151,20 +151,20 @@
<BunkerConnect {controller} />
{:else}
<BunkerUrl {controller} />
<Button variant={$bunker ? "secondary" : "primary"} onclick={selectConnect}
<Button class="btn {$bunker ? 'btn-neutral' : 'btn-primary'}" onclick={selectConnect}
>Log in with a QR code instead</Button>
{#if isIos}
<Button variant="secondary" onclick={openSigner}>Open in Signer</Button>
<Button class="btn btn-neutral" onclick={openSigner}>Open in Signer</Button>
{/if}
{/if}
</ModalBody>
<ModalFooter>
<Button variant="ghost" onclick={back} disabled={$loading}>
<Button class="btn btn-link" onclick={back} disabled={$loading}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
{#if mode === "bunker"}
<Button type="submit" variant="primary" disabled={$loading || !$bunker}>
<Button type="submit" class="btn btn-primary" disabled={$loading || !$bunker}>
<Spinner loading={$loading}>Next</Spinner>
<Icon icon={AltArrowRight} />
</Button>
+17 -17
View File
@@ -2,20 +2,20 @@
import {uniq} from "@welshman/lib"
import {Client} from "@pomade/core"
import {preventDefault} from "@lib/html"
import Spinner from "@lib/components2/Spinner.svelte"
import Button from "@lib/components2/Button.svelte"
import FieldInline from "@lib/components2/FieldInline.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import Button from "@lib/components/Button.svelte"
import FieldInline from "@lib/components/FieldInline.svelte"
import Letter from "@assets/icons/letter.svg?dataurl"
import Key from "@assets/icons/key.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.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 LogInOTP from "@app/components/LogInOTP.svelte"
import LogInSelect from "@app/components/LogInSelect.svelte"
import {deleteDeactivatedPomadeSessions, loginWithPomade} from "@app/pomade"
@@ -96,9 +96,9 @@
<p>Email*</p>
{/snippet}
{#snippet input()}
<label class="input-cl input-cl-group">
<label class="input input-bordered flex w-full items-center gap-2">
<Icon icon={Letter} />
<input type="email" class="input-cl-bare" bind:value={email} />
<input type="email" bind:value={email} />
</label>
{/snippet}
</FieldInline>
@@ -107,24 +107,24 @@
<p>Password*</p>
{/snippet}
{#snippet input()}
<label class="input-cl input-cl-group">
<label class="input input-bordered flex w-full items-center gap-2">
<Icon icon={Key} />
<input type="password" class="input-cl-bare" bind:value={password} />
<input type="password" bind:value={password} />
</label>
{/snippet}
</FieldInline>
<p class="text-sm">
Forgot your password? <Button class="cl-link p-0" onclick={loginWithOTP}
Forgot your password? <Button class="link" onclick={loginWithOTP}
>Log in with a one-time access code</Button
>.
</p>
</ModalBody>
<ModalFooter>
<Button variant="ghost" onclick={back} disabled={loading}>
<Button class="btn btn-link" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Button type="submit" variant="primary" disabled={loading || !email || !password}>
<Button type="submit" class="btn btn-primary" disabled={loading || !email || !password}>
<Spinner {loading}>Log in</Spinner>
<Icon icon={AltArrowRight} />
</Button>
+18 -19
View File
@@ -4,22 +4,21 @@
import {decrypt} from "nostr-tools/nip49"
import {preventDefault} from "@lib/html"
import {nsecDecode} from "@lib/util"
import Spinner from "@lib/components2/Spinner.svelte"
import Link from "@lib/components2/Link.svelte"
import Button from "@lib/components2/Button.svelte"
import FieldInline from "@lib/components2/FieldInline.svelte"
import Alert from "@lib/components2/Alert.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import Link from "@lib/components/Link.svelte"
import Button from "@lib/components/Button.svelte"
import FieldInline from "@lib/components/FieldInline.svelte"
import Key from "@assets/icons/key.svg?dataurl"
import Danger from "@assets/icons/danger-triangle.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.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 {clearModals} from "@app/modal"
import {setChecked} from "@app/notifications"
import {pushToast} from "@app/toast"
@@ -86,7 +85,7 @@
<p>Your Key*</p>
{/snippet}
{#snippet input()}
<label class="input-cl input-cl-group w-full">
<label class="input input-bordered flex w-full items-center gap-2">
<Icon icon={Key} />
<input type="password" bind:value={keyInput} placeholder="nsec1..." />
</label>
@@ -98,31 +97,31 @@
<p>Password*</p>
{/snippet}
{#snippet input()}
<label class="input-cl input-cl-group w-full">
<label class="input input-bordered flex w-full items-center gap-2">
<Icon icon={Key} />
<input type="password" bind:value={password} placeholder="Your password" />
</label>
{/snippet}
</FieldInline>
{/if}
<Alert variant="warning" class="flex-col text-sm">
<div class="card2 card2-sm bg-alt flex flex-col gap-2 text-sm">
<strong class="flex items-center gap-2">
<Icon icon={Danger} />
Please note!
</strong>
<p>
Logging in this way is not a best practice. For better security, please consider using a
<Link external styled href="https://nostrapps.com#signers">signer app</Link>
<Link external href="https://nostrapps.com#signers" class="link">signer app</Link>
to keep your keys safe.
</p>
</Alert>
</div>
</ModalBody>
<ModalFooter>
<Button variant="ghost" onclick={back} disabled={loading}>
<Button class="btn btn-link" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Button type="submit" variant="primary" disabled={!canSubmit}>
<Button type="submit" class="btn btn-primary" disabled={!canSubmit}>
<Spinner {loading}>Log in</Spinner>
<Icon icon={AltArrowRight} />
</Button>
+13 -13
View File
@@ -1,19 +1,19 @@
<script lang="ts">
import {Client} from "@pomade/core"
import {preventDefault} from "@lib/html"
import Spinner from "@lib/components2/Spinner.svelte"
import Button from "@lib/components2/Button.svelte"
import FieldInline from "@lib/components2/FieldInline.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import Button from "@lib/components/Button.svelte"
import FieldInline from "@lib/components/FieldInline.svelte"
import Letter from "@assets/icons/letter.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.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 LogInOTPConfirm from "@app/components/LogInOTPConfirm.svelte"
import {POMADE_NETWORK_ERROR_MESSAGE} from "@app/pomade"
import {pushModal} from "@app/modal"
@@ -69,7 +69,7 @@
<p>Email*</p>
{/snippet}
{#snippet input()}
<label class="input-cl input-cl-group w-full">
<label class="input input-bordered flex w-full items-center gap-2">
<Icon icon={Letter} />
<input type="email" bind:value={email} />
</label>
@@ -77,11 +77,11 @@
</FieldInline>
</ModalBody>
<ModalFooter>
<Button variant="ghost" onclick={back} disabled={loading}>
<Button class="btn btn-link" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Button type="submit" variant="primary" disabled={loading || !email}>
<Button type="submit" class="btn btn-primary" disabled={loading || !email}>
<Spinner {loading}>Log in</Spinner>
<Icon icon={AltArrowRight} />
</Button>
+12 -12
View File
@@ -2,18 +2,18 @@
import {uniq} from "@welshman/lib"
import {Client} from "@pomade/core"
import {preventDefault} from "@lib/html"
import Spinner from "@lib/components2/Spinner.svelte"
import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import Button from "@lib/components/Button.svelte"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import StringMultiInput from "@lib/components2/StringMultiInput.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 StringMultiInput from "@lib/components/StringMultiInput.svelte"
import LogInSelect from "@app/components/LogInSelect.svelte"
import {pushModal, clearModals} from "@app/modal"
import {setChecked} from "@app/notifications"
@@ -99,11 +99,11 @@
<StringMultiInput bind:value={otps} placeholder="Enter your login codes..." />
</ModalBody>
<ModalFooter>
<Button variant="ghost" onclick={back} disabled={loading}>
<Button class="btn btn-link" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Button type="submit" variant="primary" disabled={loading || otps.length < 3}>
<Button type="submit" class="btn btn-primary" disabled={loading || otps.length < 3}>
<Spinner {loading}>Log In</Spinner>
<Icon icon={AltArrowRight} />
</Button>
+11 -12
View File
@@ -2,16 +2,16 @@
import type {AccountOption} from "@pomade/core"
import {Client} from "@pomade/core"
import {uniqBy} from "@welshman/lib"
import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components2/Spinner.svelte"
import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.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 Profile from "@app/components/Profile.svelte"
import {deleteDeactivatedPomadeSessions, loginWithPomade} from "@app/pomade"
import {getPomadeLoginFailureMessage, POMADE_NETWORK_ERROR_MESSAGE} from "@app/pomade"
@@ -73,17 +73,16 @@
<div class="flex flex-col gap-2">
{#each uniqBy(o => o.pubkey, options) as option (option.pubkey)}
<Button
variant="secondary"
onclick={() => selectAccount(option)}
disabled={loading}
class="flex w-full items-center p-3 text-left">
class="card2 bg-alt flex w-full items-center p-3 text-left">
<Profile inert pubkey={option.pubkey} />
</Button>
{/each}
</div>
</ModalBody>
<ModalFooter>
<Button variant="ghost" onclick={back} disabled={loading}>
<Button class="btn btn-link" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
+11 -12
View File
@@ -1,15 +1,14 @@
<script lang="ts">
import {preventDefault} from "@lib/html"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components2/Spinner.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Text from "@lib/components2/Text.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.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 ModalFooter from "@lib/components/ModalFooter.svelte"
import {logout} from "@app/session"
const back = () => history.back()
@@ -33,14 +32,14 @@
<ModalHeader>
<ModalTitle>Are you sure you want<br />to log out?</ModalTitle>
</ModalHeader>
<Text class="text-center">Your local database will be cleared.</Text>
<p class="text-center">Your local database will be cleared.</p>
</ModalBody>
<ModalFooter>
<Button variant="ghost" onclick={back}>
<Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
<Button type="submit" variant="primary" disabled={loading}>
<Button type="submit" class="btn btn-primary" disabled={loading}>
<Spinner {loading}>Log Out</Spinner>
</Button>
</ModalFooter>
+13 -14
View File
@@ -6,12 +6,11 @@
import Shield from "@assets/icons/shield-minimalistic.svg?dataurl"
import Bell from "@assets/icons/bell.svg?dataurl"
import Wallet from "@assets/icons/wallet.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Link from "@lib/components2/Link.svelte"
import Button from "@lib/components2/Button.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import Grid from "@lib/components2/Grid.svelte"
import Icon from "@lib/components/Icon.svelte"
import Link from "@lib/components/Link.svelte"
import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import Profile from "@app/components/Profile.svelte"
import LogOut from "@app/components/LogOut.svelte"
import {pushModal} from "@app/modal"
@@ -29,11 +28,11 @@
<Profile inert pubkey={$pubkey} />
</Link>
{/if}
<Grid cols={3} gap={3} class="w-full">
<div class="grid grid-cols-3 gap-3 w-full">
<Link
replaceState
href="/settings/alerts"
class="clay-card clay-card-sm clay-card-interactive aspect-square flex flex-col gap-2 items-center justify-center text-center p-3 cl-text">
class="aspect-square btn h-[unset] btn-neutral flex flex-col gap-2 text-center">
<Icon icon={Bell} size={5} />
Alerts
</Link>
@@ -41,7 +40,7 @@
<Link
replaceState
href="/settings/wallet"
class="clay-card clay-card-sm clay-card-interactive aspect-square flex flex-col gap-2 items-center justify-center text-center p-3 cl-text">
class="aspect-square btn h-[unset] btn-neutral flex flex-col gap-2 text-center">
<Icon icon={Wallet} size={5} />
Wallet
</Link>
@@ -49,29 +48,29 @@
<Link
replaceState
href="/settings/relays"
class="clay-card clay-card-sm clay-card-interactive aspect-square flex flex-col gap-2 items-center justify-center text-center p-3 cl-text">
class="aspect-square btn h-[unset] btn-neutral flex flex-col gap-2 text-center">
<Icon icon={Server} size={5} />
Relays
</Link>
<Link
replaceState
href="/settings/content"
class="clay-card clay-card-sm clay-card-interactive aspect-square flex flex-col gap-2 items-center justify-center text-center p-3 cl-text">
class="aspect-square btn h-[unset] btn-neutral flex flex-col gap-2 text-center">
<Icon icon={GalleryMinimalistic} size={5} />
Content
</Link>
<Link
replaceState
href="/settings/privacy"
class="clay-card clay-card-sm clay-card-interactive aspect-square flex flex-col gap-2 items-center justify-center text-center p-3 cl-text">
class="aspect-square btn h-[unset] btn-neutral flex flex-col gap-2 text-center">
<Icon icon={Shield} size={5} />
Privacy
</Link>
</Grid>
</div>
<div class="flex gap-3 items-center opacity-75 text-sm">
<Button onclick={toggleTheme}>Theme</Button>
/
<Link replaceState styled href="/settings/about">About</Link>
<Link replaceState href="/settings/about">About</Link>
/
<Button onclick={logout}>Log Out</Button>
</div>
+2 -2
View File
@@ -1,7 +1,7 @@
<script lang="ts">
import {onMount, mount, unmount} from "svelte"
import Drawer from "@lib/components2/Drawer.svelte"
import Dialog from "@lib/components2/Dialog.svelte"
import Drawer from "@lib/components/Drawer.svelte"
import Dialog from "@lib/components/Dialog.svelte"
import {modal, modalStack, popModal} from "@app/modal"
const closeModal = () => {
+5 -6
View File
@@ -4,9 +4,8 @@
import {formatTimestamp} from "@welshman/lib"
import type {TrustedEvent} from "@welshman/util"
import Danger from "@assets/icons/danger-triangle.svg?dataurl"
import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components2/Button.svelte"
import Row from "@lib/components2/Row.svelte"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import Profile from "@app/components/Profile.svelte"
import ProfileName from "@app/components/ProfileName.svelte"
import {goToEvent} from "@app/routes"
@@ -40,11 +39,11 @@
<div class="flex flex-col gap-2 {restProps.class}" class:shadow-md={!noShadow}>
{#if muted}
<div class="flex items-center justify-between">
<Row class="relative">
<div class="row-2 relative">
<Icon icon={Danger} class="mt-1" />
<p>You have muted this person.</p>
</Row>
<Button class="cl-link ml-8" onclick={ignoreMute}>Show anyway</Button>
</div>
<Button class="link ml-8" onclick={ignoreMute}>Show anyway</Button>
</div>
{:else}
<div class="flex items-start justify-between gap-2">
@@ -1,7 +1,7 @@
<script lang="ts">
import type {ComponentProps} from "svelte"
import {getTag, getTagValue, getTagValues} from "@welshman/util"
import CurrencySymbol from "@lib/components2/CurrencySymbol.svelte"
import CurrencySymbol from "@lib/components/CurrencySymbol.svelte"
import Content from "@app/components/Content.svelte"
import ContentLinkBlock from "@app/components/ContentLinkBlock.svelte"
@@ -11,8 +11,8 @@
<CalendarEventDate event={props.event} />
<div class="flex grow flex-col">
<CalendarEventHeader event={props.event} />
<div class="flex py-2">
<div class="cl-divider-soft grow"></div>
<div class="flex py-2 opacity-50">
<div class="h-px grow bg-base-content opacity-25"></div>
</div>
<Content {...props} />
</div>

Some files were not shown because too many files have changed in this diff Show More