aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2025-07-08 10:16:22 -0700
committerAdam Soltys <[email protected]>2025-07-08 10:16:22 -0700
commit2d9d01d6e8d63ee223078874aa3b101b016367ac (patch)
tree0a5a7d90c15aadcd22a75e65aafa2c69287442c0
parent3c63c47f51f0b86f530ce2381a44a05cb1e4abf1 (diff)
downloadcoinos-ui-2d9d01d6e8d63ee223078874aa3b101b016367ac.tar.gz
coinos-ui-2d9d01d6e8d63ee223078874aa3b101b016367ac.zip
auto pay
-rw-r--r--src/locales/en.json3
-rw-r--r--src/routes/(app)/fund/[id]/+page.svelte2
-rw-r--r--src/routes/(app)/invoice/[id]/tip/+page.server.ts21
-rw-r--r--src/routes/(app)/send/[...text]/+page.svelte37
-rw-r--r--src/routes/(app)/send/invoice/[id]/+page.server.ts14
-rw-r--r--src/routes/(app)/send/invoice/[id]/+page.svelte21
-rw-r--r--src/routes/(app)/settings/account/+page.svelte15
7 files changed, 97 insertions, 16 deletions
diff --git a/src/locales/en.json b/src/locales/en.json
index c4ca5e17..922d24b3 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -296,6 +296,8 @@
"placeholder": "Enter an address, invoice or username"
},
"settings": {
+ "tip": "Default tip",
+ "tipDesc": "Default tip percentage when auto-paying trusted users",
"nostr": "Nostr",
"name": "Name",
"integrations": "Integrations",
@@ -398,6 +400,7 @@
}
},
"payments": {
+ "trustUser": "Send and enable auto-pay",
"sweep": "Sweep link",
"lockedBalance": "Locked balance",
"insufficientFunds": "Insufficient funds",
diff --git a/src/routes/(app)/fund/[id]/+page.svelte b/src/routes/(app)/fund/[id]/+page.svelte
index 614616af..7f465512 100644
--- a/src/routes/(app)/fund/[id]/+page.svelte
+++ b/src/routes/(app)/fund/[id]/+page.svelte
@@ -112,7 +112,7 @@
<div class="my-auto">{$t("payments.shareLink")}</div>
</a>
<button
- on:click={() => copy(`${$page.url.href}/sweep`)}
+ onclick={() => copy(`${$page.url.href}/sweep`)}
class="btn !w-auto grow"
>
<iconify-icon noobserver icon="ph:copy-bold" width="32"
diff --git a/src/routes/(app)/invoice/[id]/tip/+page.server.ts b/src/routes/(app)/invoice/[id]/tip/+page.server.ts
index c3be68f0..de24c639 100644
--- a/src/routes/(app)/invoice/[id]/tip/+page.server.ts
+++ b/src/routes/(app)/invoice/[id]/tip/+page.server.ts
@@ -1,12 +1,29 @@
import invoice from "$lib/invoice";
import getRates from "$lib/rates";
+import { auth, get, post } from "$lib/utils";
import { redirect } from "@sveltejs/kit";
-export async function load({ parent }) {
+export async function load({ cookies, parent }) {
const rates = await getRates();
- const { invoice, subject } = await parent();
+ let { invoice, subject, user } = await parent();
if (!invoice.amount) redirect(307, `/invoice/${invoice.id}`);
+ const trust = await get("/trust", auth(cookies));
+ const trusted = trust.includes(invoice.uid);
+ if (trusted) {
+ if (invoice.prompt && invoice.tip === null && user.tip > 0) {
+ invoice.tip = Math.round(invoice.amount * (user.tip / 100));
+ invoice = await post(
+ "/invoice",
+ { invoice, user: subject },
+ auth(cookies),
+ );
+ }
+
+ const p = await post("/payments", invoice, auth(cookies));
+ redirect(307, `/sent/${p.id}`);
+ }
+
const rate = rates[subject?.currency];
const invoiceRate = rates[invoice.currency];
return { rate, invoiceRate };
diff --git a/src/routes/(app)/send/[...text]/+page.svelte b/src/routes/(app)/send/[...text]/+page.svelte
index e5c77647..ae718f7e 100644
--- a/src/routes/(app)/send/[...text]/+page.svelte
+++ b/src/routes/(app)/send/[...text]/+page.svelte
@@ -51,6 +51,20 @@
invalidate("app:contacts");
};
+ let trust = async (e, { id, trusted }) => {
+ e.preventDefault();
+ e.stopPropagation();
+
+ if (trusted) {
+ await post("/post/trust/delete", { id });
+ } else {
+ await post("/post/trust", { id });
+ }
+
+ if (all) all = await get("/contacts");
+ invalidate("app:contacts");
+ };
+
$effect(() => {
if (browser && pasted && text) el.click() && (pasted = false);
});
@@ -73,7 +87,7 @@
</div>
</div>
{/if}
-
+
<div class="flex gap-2">
<a href="/scan" class="contents">
<button type="button" class="btn !w-auto flex-grow">
@@ -101,7 +115,6 @@
autocapitalize="none"
></textarea>
-
<button bind:this={el} type="submit" class="btn btn-accent">
<iconify-icon noobserver icon="ph:paper-plane-right-bold" width="32"
></iconify-icon>
@@ -140,12 +153,20 @@
<div class="my-auto text-left">
<p class="ml-1 text-lg break-words">{c.username}</p>
</div>
- <button class="ml-auto" onclick={(e) => pin(e, c)}>
- <iconify-icon
- icon={c.pinned ? "ph:push-pin-fill" : "ph:push-pin-bold"}
- width={32}
- ></iconify-icon>
- </button>
+ <div class="flex ml-auto gap-1">
+ <button onclick={(e) => pin(e, c)}>
+ <iconify-icon
+ icon={c.pinned ? "ph:push-pin-fill" : "ph:push-pin-bold"}
+ width={32}
+ ></iconify-icon>
+ </button>
+ <button class="ml-auto" onclick={(e) => trust(e, c)}>
+ <iconify-icon
+ icon={c.trusted ? "ph:star-fill" : "ph:star-bold"}
+ width={32}
+ ></iconify-icon>
+ </button>
+ </div>
</div>
</a>
{/each}
diff --git a/src/routes/(app)/send/invoice/[id]/+page.server.ts b/src/routes/(app)/send/invoice/[id]/+page.server.ts
index 3ef933d4..4bb7ded5 100644
--- a/src/routes/(app)/send/invoice/[id]/+page.server.ts
+++ b/src/routes/(app)/send/invoice/[id]/+page.server.ts
@@ -2,11 +2,19 @@ import getRates from "$lib/rates";
import { auth, fd, get, post, types } from "$lib/utils";
import { error, redirect } from "@sveltejs/kit";
-export async function load({ cookies, params: { id }, parent }) {
+export async function load({ cookies, depends, params: { id }, parent }) {
+ depends("app:trust");
const { user } = await parent();
const aid = cookies.get("aid") || user.id;
- const invoice = await get(`/invoice/${id}`);
+ let invoice = await get(`/invoice/${id}`);
+
+ const trust = await get("/trust", auth(cookies));
+ const trusted = trust.includes(invoice.uid);
+ if (trusted) {
+ const p = await post("/payments", invoice, auth(cookies));
+ redirect(307, `/sent/${p.id}`);
+ }
if (invoice.amount && invoice.prompt && invoice.tip === null)
redirect(307, `/invoice/${id}/tip`);
@@ -31,7 +39,7 @@ export async function load({ cookies, params: { id }, parent }) {
const invoiceRate = rates[invoice.currency];
const { balance } = await get(`/account/${aid}`, auth(cookies));
- return { balance, invoice, user, rate, invoiceRate };
+ return { balance, invoice, user, rate, invoiceRate, trusted };
}
export const actions = {
diff --git a/src/routes/(app)/send/invoice/[id]/+page.svelte b/src/routes/(app)/send/invoice/[id]/+page.svelte
index 7d167f41..9aac5c8d 100644
--- a/src/routes/(app)/send/invoice/[id]/+page.svelte
+++ b/src/routes/(app)/send/invoice/[id]/+page.svelte
@@ -1,4 +1,5 @@
<script>
+ import { invalidate } from "$app/navigation";
import { untrack } from "svelte";
import handler from "$lib/handler";
import { onDestroy, onMount } from "svelte";
@@ -26,7 +27,7 @@
} from "$lib/utils";
let { data, form } = $props();
- let { balance, invoice, user } = $state(data);
+ let { trusted, balance, invoice, user } = $state(data);
let { address, hash, payreq, user: recipient, tip } = $state(invoice);
let { currency } = $derived(user);
let locale = $derived(loc(user));
@@ -64,6 +65,19 @@
});
};
+ let toggleTrust = async (e) => {
+ e.preventDefault();
+ e.stopPropagation();
+
+ if (trusted) {
+ await post("/post/trust/delete", { id: recipient.id });
+ } else {
+ await post("/post/trust", { id: recipient.id });
+ }
+
+ invalidate("app:trust");
+ };
+
$effect(() => {
if (form?.message?.includes("pin")) $pin = undefined;
submitting = false;
@@ -193,5 +207,10 @@
<button type="button" class="btn" onclick={external}
>{$t("payments.moreOptions")}</button
>
+ <button type="button" class="btn" onclick={toggleTrust}>
+ <iconify-icon icon={trusted ? "ph:star-fill" : "ph:star-bold"} width={32}
+ ></iconify-icon>
+ {$t("payments.trustUser")}</button
+ >
</form>
</div>
diff --git a/src/routes/(app)/settings/account/+page.svelte b/src/routes/(app)/settings/account/+page.svelte
index c5c75d88..481c8de7 100644
--- a/src/routes/(app)/settings/account/+page.svelte
+++ b/src/routes/(app)/settings/account/+page.svelte
@@ -14,7 +14,7 @@
let { data } = $props();
let { user } = $state(data);
let { rates, subscriptions } = data;
- let { currency, email, verified } = $state(user);
+ let { currency, email, tip, verified } = $state(user);
let rate = rates[currency];
let fiats = Object.keys(rates).sort((a, b) => a.localeCompare(b));
@@ -181,6 +181,19 @@
</p>
</div>
+<div class="space-y-1 relative">
+ <label for="tip" class="font-bold block">{$t("user.settings.tip")}</label>
+ <p class="text-secondary">
+ {$t("user.settings.tipDesc")}
+ </p>
+
+ <label
+ class="input input-bordered border-primary input-lg rounded-2xl flex items-center gap-2"
+ >
+ <input type="text" name="tip" class="clean" bind:value={tip} />
+ </label>
+</div>
+
<div>
<div class="flex justify-between items-center">
<span class="font-bold">{$t("user.settings.autoWithdraw")}</span>