|
@@ -10,13 +10,22 @@ const highlightJs = require("highlight.js");
|
|
|
const prettyMs = require("pretty-ms");
|
|
|
|
|
|
const updater = require("../updater.js");
|
|
|
-
|
|
|
-global.updaterequired = "";
|
|
|
-global.ck = updater.getRemoteVersion(async function(checkversion){
|
|
|
- if (checkversion === "required"){
|
|
|
- ck = "required";
|
|
|
+async function checkForUpdate() {
|
|
|
+ try {
|
|
|
+ await updater.getRemoteVersion();
|
|
|
+ if (global.ck === "required") {
|
|
|
+ global.updaterequired = form(
|
|
|
+ { action: "/update", method: "post" },
|
|
|
+ button({ type: "submit" }, i18n.updateit)
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ console.log("\noasis@version: no updates required.\n");
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("\noasis@version: error fetching package.json:", error.message, "\n");
|
|
|
}
|
|
|
-});
|
|
|
+}
|
|
|
+checkForUpdate();
|
|
|
|
|
|
const {
|
|
|
a,
|
|
@@ -51,8 +60,14 @@ const {
|
|
|
select,
|
|
|
span,
|
|
|
summary,
|
|
|
+ table,
|
|
|
+ tbody,
|
|
|
+ td,
|
|
|
textarea,
|
|
|
+ th,
|
|
|
+ thead,
|
|
|
title,
|
|
|
+ tr,
|
|
|
ul,
|
|
|
} = require("hyperaxe");
|
|
|
|
|
@@ -133,12 +148,14 @@ const template = (titlePrefix, ...elements) => {
|
|
|
ul(
|
|
|
//navLink({ href: "/imageSearch", emoji: "✧", text: i18n.imageSearch }),
|
|
|
navLink({ href: "/mentions", emoji: "✺", text: i18n.mentions }),
|
|
|
- navLink({ href: "/public/latest", emoji: "☄", text: i18n.latest }),
|
|
|
- navLink({ href: "/public/latest/summaries", emoji: "※", text: i18n.summaries }),
|
|
|
- navLink({ href: "/public/latest/topics", emoji: "ϟ", text: i18n.topics }),
|
|
|
- navLink({ href: "/public/latest/extended", emoji: "∞", text: i18n.extended }),
|
|
|
navLink({ href: "/public/popular/day", emoji: "⌘", text: i18n.popular }),
|
|
|
+ hr,
|
|
|
+ navLink({ href: "/public/latest/topics", emoji: "ϟ", text: i18n.topics }),
|
|
|
+ navLink({ href: "/public/latest/summaries", emoji: "※", text: i18n.summaries }),
|
|
|
+ navLink({ href: "/public/latest", emoji: "☄", text: i18n.latest }),
|
|
|
navLink({ href: "/public/latest/threads", emoji: "♺", text: i18n.threads }),
|
|
|
+ hr,
|
|
|
+ navLink({ href: "/public/latest/extended", emoji: "∞", text: i18n.extended }),
|
|
|
)
|
|
|
),
|
|
|
main({ id: "content" }, elements),
|
|
@@ -147,9 +164,12 @@ const template = (titlePrefix, ...elements) => {
|
|
|
navLink({ href: "/publish", emoji: "❂",text: i18n.publish }),
|
|
|
navLink({ href: "/search", emoji: "✦", text: i18n.search }),
|
|
|
navLink({ href: "/inbox", emoji: "☂", text: i18n.private }),
|
|
|
+ hr,
|
|
|
navLink({ href: "/profile", emoji: "⚉", text: i18n.profile }),
|
|
|
- navLink({ href: "/invites", emoji: "❄", text: i18n.invites }),
|
|
|
+ navLink({ href: "/wallet", emoji: "❄", text: i18n.wallet }),
|
|
|
+ navLink({ href: "/invites", emoji: "ꔹ", text: i18n.invites }),
|
|
|
navLink({ href: "/peers", emoji: "⧖", text: i18n.peers }),
|
|
|
+ hr,
|
|
|
navLink({ href: "/settings", emoji: "⚙", text: i18n.settings })
|
|
|
)
|
|
|
)
|
|
@@ -1128,7 +1148,7 @@ exports.invitesView = ({ invites }) => {
|
|
|
);
|
|
|
};
|
|
|
|
|
|
-exports.settingsView = ({ theme, themeNames, version }) => {
|
|
|
+exports.settingsView = ({ theme, themeNames, version, walletUrl, walletUser, walletFee }) => {
|
|
|
const themeElements = themeNames.map((cur) => {
|
|
|
const isCurrentTheme = cur === theme;
|
|
|
if (isCurrentTheme) {
|
|
@@ -1173,20 +1193,14 @@ exports.settingsView = ({ theme, themeNames, version }) => {
|
|
|
button({ type: "submit" }, i18n.rebuildName)
|
|
|
);
|
|
|
|
|
|
- if (ck === "required"){
|
|
|
- updaterequired = form(
|
|
|
- { action: "/update", method: "post" },
|
|
|
- button({ type: "submit"}, i18n.updateit)
|
|
|
- );
|
|
|
- };
|
|
|
-
|
|
|
return template(
|
|
|
i18n.settings,
|
|
|
section(
|
|
|
{ class: "message" },
|
|
|
h1(i18n.settings),
|
|
|
p(a({ href:snhUrl, target: "_blank" }, i18n.settingsIntro({ version }))),
|
|
|
- p(updaterequired),
|
|
|
+ p(global.updaterequired),
|
|
|
+ hr,
|
|
|
h2(i18n.theme),
|
|
|
p(i18n.themeIntro),
|
|
|
form(
|
|
@@ -1194,6 +1208,7 @@ exports.settingsView = ({ theme, themeNames, version }) => {
|
|
|
select({ name: "theme" }, ...themeElements),
|
|
|
button({ type: "submit" }, i18n.setTheme)
|
|
|
),
|
|
|
+ hr,
|
|
|
h2(i18n.language),
|
|
|
p(i18n.languageDescription),
|
|
|
form(
|
|
@@ -1207,6 +1222,25 @@ exports.settingsView = ({ theme, themeNames, version }) => {
|
|
|
]),
|
|
|
button({ type: "submit" }, i18n.setLanguage)
|
|
|
),
|
|
|
+ hr,
|
|
|
+ h2(i18n.wallet),
|
|
|
+ p(i18n.walletSettingsDescription),
|
|
|
+ form(
|
|
|
+ { action: "/settings/wallet", method: "POST" },
|
|
|
+ label({ for: "wallet_url" }, i18n.walletAddress),
|
|
|
+ input({ type: "text", id: "wallet_url", name: "wallet_url", placeholder: walletUrl, value: walletUrl }),
|
|
|
+ label({ for: "wallet_user" }, i18n.walletUser),
|
|
|
+ input({ type: "text", id: "wallet_user", name: "wallet_user", placeholder: walletUser, value: walletUser }),
|
|
|
+
|
|
|
+ label({ for: "wallet_pass" }, i18n.walletPass),
|
|
|
+ input({ type: "password", id: "wallet_pass", name: "wallet_pass" }),
|
|
|
+
|
|
|
+ label({ for: "wallet_fee" }, i18n.walletFee),
|
|
|
+ input({ type: "text", id: "wallet_fee", name: "wallet_fee", placeholder: walletFee, value: walletFee }),
|
|
|
+
|
|
|
+ button({ type: "submit" }, i18n.walletConfiguration)
|
|
|
+ ),
|
|
|
+ hr,
|
|
|
h2(i18n.indexes),
|
|
|
p(i18n.indexesDescription),
|
|
|
rebuildButton,
|
|
@@ -1546,3 +1580,182 @@ exports.indexingView = ({ percent }) => {
|
|
|
|
|
|
return result;
|
|
|
};
|
|
|
+
|
|
|
+const walletViewRender = (balance, ...elements) => {
|
|
|
+ return template(
|
|
|
+ i18n.walletTitle,
|
|
|
+ section(
|
|
|
+ h1(i18n.walletTitle),
|
|
|
+ p(i18n.walletDescription),
|
|
|
+ ),
|
|
|
+ section(
|
|
|
+ div(
|
|
|
+ {class: "div-center"},
|
|
|
+ span(
|
|
|
+ {class: "wallet-balance"},
|
|
|
+ i18n.walletBalanceLine({ balance })
|
|
|
+ ),
|
|
|
+ span(
|
|
|
+ { class: "form-button-group-center" },
|
|
|
+ a({ href: "/wallet/send", class: "button-like-link" }, i18n.walletSend),
|
|
|
+ a({ href: "/wallet/receive", class: "button-like-link" }, i18n.walletReceive),
|
|
|
+ a({ href: "/wallet/history", class: "button-like-link" }, i18n.walletHistory),
|
|
|
+ )
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ elements.length > 0 ? section(...elements) : null
|
|
|
+ )
|
|
|
+};
|
|
|
+
|
|
|
+exports.walletView = async (balance) => {
|
|
|
+ return walletViewRender(balance)
|
|
|
+}
|
|
|
+
|
|
|
+exports.walletHistoryView = async (balance, transactions) => {
|
|
|
+ return walletViewRender(
|
|
|
+ balance,
|
|
|
+ table(
|
|
|
+ { class: "wallet-history" },
|
|
|
+ thead(
|
|
|
+ tr(
|
|
|
+ { class: "full-center" },
|
|
|
+ th({ class: "col-10" }, i18n.walletCnfrs),
|
|
|
+ th(i18n.walletDate),
|
|
|
+ th(i18n.walletType),
|
|
|
+ th(i18n.walletAmount),
|
|
|
+ th({ class: "col-30" }, i18n.walletTxId)
|
|
|
+ )
|
|
|
+ ),
|
|
|
+ tbody(
|
|
|
+ ...transactions.map((tx) => {
|
|
|
+ const date = new Date(tx.time * 1000);
|
|
|
+ const amount = Number(tx.amount);
|
|
|
+ const fee = Number(tx.fee) || 0;
|
|
|
+ const totalAmount = Number(amount + fee);
|
|
|
+
|
|
|
+ return tr(
|
|
|
+ td({ class: "full-center" }, tx.confirmations),
|
|
|
+ td(date.toLocaleDateString(), br(), date.toLocaleTimeString()),
|
|
|
+ td(tx.category),
|
|
|
+ td(totalAmount.toFixed(2)),
|
|
|
+ td({ width: "30%", class: "tcell-ellipsis" },
|
|
|
+ a({
|
|
|
+ href: `https://ecoin.03c8.net/blockexplorer/search?q=${tx.txid}`,
|
|
|
+ target: "_blank",
|
|
|
+ }, tx.txid)
|
|
|
+ )
|
|
|
+ )
|
|
|
+ })
|
|
|
+ )
|
|
|
+ )
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+exports.walletReceiveView = async (balance, address) => {
|
|
|
+ const QRCode = require('qrcode');
|
|
|
+ const qrImage = await QRCode.toString(address, { type: 'svg' });
|
|
|
+ const qrContainer = address + qrImage
|
|
|
+
|
|
|
+ return walletViewRender(
|
|
|
+ balance,
|
|
|
+ div(
|
|
|
+ {class: 'div-center qr-code', innerHTML: qrContainer},
|
|
|
+ ),
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+exports.walletSendFormView = async (balance, destination, amount, fee, statusMessages) => {
|
|
|
+ const { type, title, messages } = statusMessages || {};
|
|
|
+ const statusBlock = div({ class: `wallet-status-${type}` },);
|
|
|
+
|
|
|
+ if (messages?.length > 0) {
|
|
|
+ statusBlock.appendChild(
|
|
|
+ span(
|
|
|
+ i18n.walletStatusMessages[title]
|
|
|
+ )
|
|
|
+ )
|
|
|
+ statusBlock.appendChild(
|
|
|
+ ul(
|
|
|
+ ...messages.map(error => li(i18n.walletStatusMessages[error]))
|
|
|
+ )
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ return walletViewRender(
|
|
|
+ balance,
|
|
|
+ div(
|
|
|
+ {class: "div-center"},
|
|
|
+ messages?.length > 0 ? statusBlock : null,
|
|
|
+ form(
|
|
|
+ { action: '/wallet/send', method: 'POST' },
|
|
|
+ label({ for: 'destination' }, i18n.walletAddress),
|
|
|
+ input({ type: 'text', id: 'destination', name: 'destination', placeholder: 'ELH8RJGy3s7sCPqQUyN8on2gD5Fdn3BpyC', value: destination }),
|
|
|
+ label({ for: 'amount' }, i18n.walletAmount),
|
|
|
+ input({ type: 'text', id: 'amount', name: 'amount', placeholder: '0.25', value: amount }),
|
|
|
+ label({ for: 'fee' }, i18n.walletFee),
|
|
|
+ input({ type: 'text', id: 'fee', name: 'fee', placeholder: '0.01', value: fee }),
|
|
|
+ input({ type: 'hidden', name: 'action', value: 'confirm' }),
|
|
|
+ div({ class: 'form-button-group-center' },
|
|
|
+ button({ type: 'submit' }, i18n.walletSend),
|
|
|
+ button({ type: 'reset' }, i18n.walletReset)
|
|
|
+ )
|
|
|
+ )
|
|
|
+ )
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+exports.walletSendConfirmView = async (balance, destination, amount, fee) => {
|
|
|
+ const totalCost = amount + fee;
|
|
|
+
|
|
|
+ return walletViewRender(
|
|
|
+ balance,
|
|
|
+ p(
|
|
|
+ i18n.walletAddressLine({ address: destination }), br(),
|
|
|
+ i18n.walletAmountLine({ amount }), br(),
|
|
|
+ i18n.walletFeeLine({ fee }), br(),
|
|
|
+ i18n.walletTotalCostLine({ totalCost }),
|
|
|
+ ),
|
|
|
+ form(
|
|
|
+ { action: '/wallet/send', method: 'POST' },
|
|
|
+ input({ type: 'hidden', name: 'action', value: 'send' }),
|
|
|
+ input({ type: 'hidden', name: 'destination', value: destination }),
|
|
|
+ input({ type: 'hidden', name: 'amount', value: amount }),
|
|
|
+ input({ type: 'hidden', name: 'fee', value: fee }),
|
|
|
+ div({ class: 'form-button-group-center' },
|
|
|
+ button({ type: 'submit' }, i18n.walletConfirm),
|
|
|
+ a ({ href: `/wallet/send`, class: "button-like-link" }, i18n.walletBack),
|
|
|
+ )
|
|
|
+ ),
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+exports.walletErrorView = async (error) => {
|
|
|
+ return template(
|
|
|
+ i18n.walletTitle,
|
|
|
+ section(
|
|
|
+ h1(i18n.walletTitle),
|
|
|
+ p(i18n.walletDescription),
|
|
|
+ ),
|
|
|
+ section(
|
|
|
+ h2(i18n.walletStatus),
|
|
|
+ p(i18n.walletDisconnected),
|
|
|
+ )
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+exports.walletSendResultView = async (balance, destination, amount, txId) => {
|
|
|
+ return walletViewRender(
|
|
|
+ balance,
|
|
|
+ p(
|
|
|
+ i18n.walletSentToLine({ destination, amount }), br(),
|
|
|
+ `${i18n.walletTransactionId}: `,
|
|
|
+ a(
|
|
|
+ {
|
|
|
+ href: `https://ecoin.03c8.net/blockexplorer/search?q=${txId}`,
|
|
|
+ target: "_blank",
|
|
|
+ },
|
|
|
+ txId
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ )
|
|
|
+}
|