📦 Add Linux packaging (AppImage/Flatpak/DEB)

🧹 Minor Codebase cleanup
 Implement automatic starting of the relay
This commit is contained in:
Danny Morabito 2025-02-24 21:48:11 +01:00
parent 89fcaa9aa6
commit f402ff04ab
Signed by: dannym
GPG key ID: 7CC8056A5A04557E
19 changed files with 519 additions and 119 deletions

View file

@ -1,12 +1,14 @@
import { LitElement, html, css } from "lit";
import { customElement, property, query, state } from "lit/decorators.js";
import { customElement, state } from "lit/decorators.js";
import { animate } from "@lit-labs/motion";
import * as nostrTools from "nostr-tools/pure";
import * as nip06 from "nostr-tools/nip06";
import * as nip19 from "nostr-tools/nip19";
import * as nip49 from "nostr-tools/nip49";
import * as nostrTools from "@nostr/tools/pure";
import * as nip06 from "@nostr/tools/nip06";
import * as nip19 from "@nostr/tools/nip19";
import * as nip49 from "@nostr/tools/nip49";
import { ndk, setSigner } from "@/ndk";
import { NDKEvent, NDKKind, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
import { encodeBase64 } from "@std/encoding/base64";
import { randomBytes } from "@noble/ciphers/webcrypto";
@customElement("arx-initial-setup")
export class InitialSetup extends LitElement {
@ -17,6 +19,15 @@ export class InitialSetup extends LitElement {
@state() private profileImage = "";
@state() private lightningAddress = "";
get encryptionPassphrase() {
let encryptionPassphrase = localStorage.getItem("encryption_key");
if (!encryptionPassphrase) {
encryptionPassphrase = encodeBase64(randomBytes(32));
localStorage.setItem("encryption_key", encryptionPassphrase);
}
return encryptionPassphrase;
}
static override styles = css`
:host {
display: block;
@ -409,32 +420,9 @@ export class InitialSetup extends LitElement {
`;
}
private getSetupCode() {
const userAgent = navigator.userAgent.toLowerCase();
if (userAgent.includes("mac")) {
return `
mkdir -p ~/.config/arx/eve && cd ~/.config/arx/eve
echo "${this.seedPhrase}" > ccn.seed
launchctl load ~/Library/LaunchAgents/com.user.eve-relay.plist
launchctl start com.user.eve-relay
`
.split("\n")
.map((x) => x.trim())
.join("\n");
}
if (userAgent.includes("linux")) {
return `
mkdir -p ~/.config/arx/eve && cd ~/.config/arx/eve
echo "${this.seedPhrase}" > ccn.seed
systemctl --user enable eve-relay.service
systemctl --user start eve-relay.service
`
.split("\n")
.map((x) => x.trim())
.join("\n");
}
return "Unsupported OS";
private async startRelay() {
await window.relay.writeSeed(this.seedPhrase);
await window.relay.start(this.encryptionPassphrase);
}
private renderPageThree() {
@ -446,11 +434,10 @@ export class InitialSetup extends LitElement {
During this alpha phase, manual relay configuration is required.
This process will be automated in future releases.
</p>
<p>Open your terminal and run following commands:</p>
<pre>
<code>${this.getSetupCode()}</code>
</pre
>
<p>Please press the button below to start the relay.</p>
<button @click=${() => this.startRelay()} class="button primary">
Start Relay
</button>
<p>
Having trouble? Our team is here to help if you encounter any
issues.
@ -586,15 +573,11 @@ export class InitialSetup extends LitElement {
}
private async goToFinalStep() {
let encryptionPassphrase = localStorage.getItem("encryption_key");
if (!encryptionPassphrase) {
encryptionPassphrase =
Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15);
localStorage.setItem("encryption_key", encryptionPassphrase);
}
const randomPrivateKey = nostrTools.generateSecretKey();
const encryptedNsec = nip49.encrypt(randomPrivateKey, encryptionPassphrase);
const encryptedNsec = nip49.encrypt(
randomPrivateKey,
this.encryptionPassphrase
);
const npub = nip19.npubEncode(nostrTools.getPublicKey(randomPrivateKey));
if (!this.lightningAddress) this.lightningAddress = `${npub}@npub.cash`;
@ -602,6 +585,7 @@ export class InitialSetup extends LitElement {
localStorage.setItem("ncryptsec", encryptedNsec);
setSigner(new NDKPrivateKeySigner(randomPrivateKey));
await ndk.connect(5000);
const event = new NDKEvent(ndk);
event.kind = NDKKind.Metadata;

View file

@ -1,18 +1,18 @@
import { css, LitElement } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import MarkdownIt, { type StateCore, type Token } from 'markdown-it';
import { css, LitElement } from "lit";
import { customElement, property } from "lit/decorators.js";
import { unsafeHTML } from "lit/directives/unsafe-html.js";
import MarkdownIt, { type StateCore, type Token } from "markdown-it";
function nostrPlugin(md: MarkdownIt): void {
const npubRegex = /(npub[0-9a-zA-Z]{59})/g;
md.core.ruler.after('inline', 'nostr_npub', (state: StateCore): boolean => {
md.core.ruler.after("inline", "nostr_npub", (state: StateCore): boolean => {
for (const token of state.tokens) {
if (token.type === 'inline' && token.children) {
if (token.type === "inline" && token.children) {
for (let i = 0; i < token.children.length; i++) {
const child = token.children[i];
if (child.type === 'text') {
if (child.type === "text") {
const matches = child.content.match(npubRegex);
if (!matches) continue;
@ -21,28 +21,29 @@ function nostrPlugin(md: MarkdownIt): void {
child.content.replace(
npubRegex,
// @ts-ignore this is an issue with the types
(match: string, npub: string, offset: number) => {
if (offset > lastIndex) {
const textToken = new state.Token('text', '', 0);
const textToken = new state.Token("text", "", 0);
textToken.content = child.content.slice(lastIndex, offset);
newTokens.push(textToken);
}
const linkOpen = new state.Token('link_open', 'a', 1);
linkOpen.attrs = [['href', `nostr:${npub}`]];
const linkOpen = new state.Token("link_open", "a", 1);
linkOpen.attrs = [["href", `nostr:${npub}`]];
const text = new state.Token('text', '', 0);
const text = new state.Token("text", "", 0);
text.content = npub;
const linkClose = new state.Token('link_close', 'a', -1);
const linkClose = new state.Token("link_close", "a", -1);
newTokens.push(linkOpen, text, linkClose);
lastIndex = offset + match.length;
},
}
);
if (lastIndex < child.content.length) {
const textToken = new state.Token('text', '', 0);
const textToken = new state.Token("text", "", 0);
textToken.content = child.content.slice(lastIndex);
newTokens.push(textToken);
}
@ -58,7 +59,7 @@ function nostrPlugin(md: MarkdownIt): void {
});
}
@customElement('arx-markdown-content')
@customElement("arx-markdown-content")
export class MarkdownContent extends LitElement {
private md = new MarkdownIt({
html: false,
@ -68,7 +69,7 @@ export class MarkdownContent extends LitElement {
});
@property({ type: String })
content = '';
content = "";
static override styles = [
css`
@ -94,7 +95,16 @@ export class MarkdownContent extends LitElement {
display: contents;
}
h1, h2, h3, h4, h5, h6, code, ul, ol, blockquote {
h1,
h2,
h3,
h4,
h5,
h6,
code,
ul,
ol,
blockquote {
width: 100%;
margin: 0;
display: block;