From f4b3cf831e9a0ae372f213a5c545ac3b23a94752 Mon Sep 17 00:00:00 2001 From: Bojan Mojsilovic Date: Fri, 5 Apr 2024 15:16:45 +0200 Subject: [PATCH] Add lnbc to DMs --- src/components/Lnbc/Lnbc.module.scss | 164 +++++++++++++++++++++++++++ src/components/Lnbc/Lnbc.tsx | 13 ++- src/pages/Messages.module.scss | 12 +- src/pages/Messages.tsx | 102 +++++++++++++---- 4 files changed, 267 insertions(+), 24 deletions(-) diff --git a/src/components/Lnbc/Lnbc.module.scss b/src/components/Lnbc/Lnbc.module.scss index 0fd0588..af8e7c2 100644 --- a/src/components/Lnbc/Lnbc.module.scss +++ b/src/components/Lnbc/Lnbc.module.scss @@ -150,6 +150,170 @@ } } } + + &.noBack { + background-color: unset; + } +} + +.lnbcAlter { + width: 100%; + min-height: 158px; + background-color: none; + border-radius: var(--border-radius-small); + display: flex; + flex-direction: column; + gap: 6px; + padding: 12px 0; + position: relative; + + .paymentOverlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: var(--background-site); + opacity: 0.6; + display: flex; + justify-content: center; + align-items: center; + } + + .header { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + height: 20px; + + .title { + display: flex; + justify-content: flex-start; + align-items: center; + + color: white; + + font-size: 15px; + font-weight: 700; + line-height: 16px; + } + + .headerActions { + display: flex; + justify-content: flex-end; + align-items: center; + gap: 2px; + + button { + .qrIcon { + width: 18px; + height: 18px; + display: inline-block; + margin: 0px; + background-color: white; + -webkit-mask: url(../../assets/icons/qr_code.svg) no-repeat 0px / 18px; + mask: url(../../assets/icons/qr_code.svg) no-repeat 0px / 18px; + } + .copyIcon { + width: 18px; + height: 18px; + display: inline-block; + margin: 0px; + background-color: white; + -webkit-mask: url(../../assets/icons/copy_border.svg) no-repeat 0px / 18px; + mask: url(../../assets/icons/copy_border.svg) no-repeat 0px / 18px; + } + + &:hover { + .qrIcon, .copyIcon { + background-color: white; + } + } + } + + .copyDone { + width: 30px; + height: 30px; + display: flex; + justify-content: center; + align-items: center; + + .checkIcon { + width: 18px; + height: 18px; + display: inline-block; + margin: 0px; + background-color: var(--success-bright); + -webkit-mask: url(../../assets/icons/check.svg) no-repeat 0px / 18px; + mask: url(../../assets/icons/check.svg) no-repeat 0px / 18px; + } + } + } + } + + .body { + display: flex; + flex-direction: column; + flex-grow: 1; + gap: 8px; + + .description { + color: white; + + font-size: 15px; + font-weight: 400; + line-height: 18px; + } + + .amount { + color: white; + + font-size: 24px; + font-weight: 600; + line-height: 24px; + } + } + + .footer { + height: 36px; + width: 100%; + display: flex; + justify-content: space-between; + align-items: flex-end; + + .expiryDate { + color: white; + + font-size: 15px; + font-weight: 400; + line-height: 18px; + letter-spacing: 0.15px; + } + .expiredDate { + color: white; + + font-size: 15px; + font-weight: 400; + line-height: 18px; + letter-spacing: 0.15px; + } + + .payAction { + height: 36px; + min-width: 120px; + button { + width: 100%; + height: 100%; + color: var(--accent); + background-color: white; + } + } + } + + &.noBack { + background-color: unset; + } } .lnIcon { diff --git a/src/components/Lnbc/Lnbc.tsx b/src/components/Lnbc/Lnbc.tsx index c8e83bb..b60b96c 100644 --- a/src/components/Lnbc/Lnbc.tsx +++ b/src/components/Lnbc/Lnbc.tsx @@ -22,7 +22,7 @@ import { useIntl } from '@cookbook/solid-intl'; import { lnInvoice } from '../../translations'; -const Lnbc: Component< { id?: string, lnbc: string } > = (props) => { +const Lnbc: Component< { id?: string, lnbc: string, alternative?: boolean, noBack?: boolean } > = (props) => { const app = useAppContext(); const toast = useToastContext(); @@ -151,8 +151,17 @@ const Lnbc: Component< { id?: string, lnbc: string } > = (props) => { } }; + const klass = () => { + let k = props.alternative ? styles.lnbcAlter : styles.lnbc; + if (props.noBack) { + k += ` ${styles.noBack}` + } + + return k; + } + return ( -
+
diff --git a/src/pages/Messages.module.scss b/src/pages/Messages.module.scss index 6c6280b..ba99cb3 100644 --- a/src/pages/Messages.module.scss +++ b/src/pages/Messages.module.scss @@ -26,7 +26,7 @@ align-items: flex-start; max-width: calc(100% - 48px); - .message { + .message, .messageLn { @include messageContent(); @if $align-end { @@ -46,12 +46,18 @@ background-color: var(--subtile-devider); } } + .messageLn { + display: flex; + width: calc(500px + 12px - 40px) !important; + } + .threadTime { color: var(--text-tertiary-2); font-weight: 400; font-size: 12px; line-height: 16px; } + } .messagesContent { @@ -258,7 +264,7 @@ .myThread { @include thread(true); .threadMessages { - .message { + .message, .messageLn { color: var(--text-primary-button); background-color: var(--accent); border-radius: 12px 0px 0px 12px; @@ -279,7 +285,7 @@ .theirThread { @include thread(false); .threadMessages { - .message { + .message, .messageLn { background-color: var(--background-input); border-radius: 0px 12px 12px 0px; &:last-child { diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx index d7ea831..40d5637 100644 --- a/src/pages/Messages.tsx +++ b/src/pages/Messages.tsx @@ -1,11 +1,11 @@ import { useIntl } from '@cookbook/solid-intl'; import { nip19 } from 'nostr-tools'; -import { Component, createEffect, createSignal, For, onCleanup, onMount, Show } from 'solid-js'; +import { Component, createEffect, createSignal, For, JSXElement, Match, onCleanup, onMount, Show, Switch } from 'solid-js'; import Avatar from '../components/Avatar/Avatar'; import { useAccountContext } from '../contexts/AccountContext'; import { useMessagesContext } from '../contexts/MessagesContext'; import { nip05Verification, truncateNpub, userName } from '../stores/profile'; -import { PrimalNote, PrimalUser } from '../types/primal'; +import { DirectMessage, DirectMessageThread, PrimalNote, PrimalUser } from '../types/primal'; import { date } from '../lib/dates'; import styles from './Messages.module.scss'; @@ -20,7 +20,7 @@ import SearchOption from '../components/Search/SearchOption'; import { debounce, isVisibleInContainer, uuidv4 } from '../utils'; import { useSearchContext } from '../contexts/SearchContext'; import { createStore } from 'solid-js/store'; -import { editMentionRegex, emojiSearchLimit } from '../constants'; +import { editMentionRegex, emojiSearchLimit, linebreakRegex } from '../constants'; import Search from '../components/Search/Search'; import { useProfileContext } from '../contexts/ProfileContext'; import Paginator from '../components/Paginator/Paginator'; @@ -35,6 +35,7 @@ import { import PageCaption from '../components/PageCaption/PageCaption'; import { useMediaContext } from '../contexts/MediaContext'; import PageTitle from '../components/PageTitle/PageTitle'; +import Lnbc from '../components/Lnbc/Lnbc'; type AutoSizedTextArea = HTMLTextAreaElement & { _baseScrollHeight: number }; @@ -294,6 +295,7 @@ const Messages: Component = () => { if (!messages) { return message; } + return parseNoteLinks( parseNpubLinks( highlightHashtags( @@ -831,6 +833,13 @@ const Messages: Component = () => { newMessageInput.dispatchEvent(e); }; + const msgHasInvoice = (msg: DirectMessage) => { + const r =/(\s+|\r\n|\r|\n|^)lnbc[a-zA-Z0-9]+/; + const test = r.test(msg.content); + + return test + }; + createEffect(() => { if (account?.hasPublicKey()) { profile?.actions.setProfileKey(account.publicKey) @@ -884,6 +893,75 @@ const Messages: Component = () => { newMessageInput && setMessage(newMessageInput.value) } + const renderMessage = (msg: DirectMessage, thread: DirectMessageThread) => { + if (!msgHasInvoice(msg)) { + return ( +
+ ); + }; + + let sections: string[] = []; + + let content = msg.content.replace(linebreakRegex, ' __LB__ ').replace(/\s+/g, ' __SP__ '); + + let tokens: string[] = content.split(/[\s]+/); + + let sectionIndex = 0; + tokens.forEach((t) => { + if (t.startsWith('lnbc')) { + if (sections[sectionIndex]) sectionIndex++; + + sections[sectionIndex] = t; + + sectionIndex++; + } + else { + let c = t; + const prev = sections[sectionIndex] || ''; + + if (t === '__SP__') { + c = prev.length === 0 ? '' : ' '; + } + + if (t === '__LB__') { + c = prev.length === 0 ? '' : '\r'; + } + + sections[sectionIndex] = prev + c; + } + }); + + return ( + + {section => ( +
+ }> + +
+ +
+
+ + )} + + ); + }; + return (
@@ -1064,14 +1142,7 @@ const Messages: Component = () => {
- {(msg) => ( -
- )} + {msg => renderMessage(msg, thread)}
@@ -1091,14 +1162,7 @@ const Messages: Component = () => {
- {(msg) => ( -
- )} + {msg => renderMessage(msg, thread)}