Skip to content

Commit

Permalink
Prompt receipt
Browse files Browse the repository at this point in the history
* initial commit

Optional post-accept receipt window popup
TODO: Iterate through visualized params vs the result JSON

* removing code

* Implemented receipt prompt

Receipt prompt functionality fully implemented

* UX

Show request header
move example file

* Update lang-select.vue

Provide translated locale keys in the lang select component

* Update BitShares.js

Reject prompt if some of the prompt contents fail to render

* Fixes

Fix lang select
Fix max url char limit bug via ipcrenderer data passthrough

* Fixes

Change script name
Create documentation
Fix type errors in popup & receipt components

* Create bitshares beautify function

Avoid bloating the Bitshares blockchain class

---------

Co-authored-by: CM <grctestemail@gmail.com>
  • Loading branch information
sschiessl-bcp and grctest committed Aug 29, 2023
1 parent 62330b6 commit 36fa580
Show file tree
Hide file tree
Showing 40 changed files with 8,146 additions and 3,405 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Thumbs.db
/app/app.js
/app/modal.js
/app/background.js
/app/receipt.js
/app/**/*.map
/app/*.ttf
/app/*.woff
Expand Down
12 changes: 12 additions & 0 deletions app/receipt.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body class="text-center">
<div class="main" id="receipt">
<Receipt ref="receiptComp"></Receipt>
</div>
<script src="receipt.js"></script>
</body>
</html>
7 changes: 6 additions & 1 deletion app/translations/operations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@
"accept_btn": "Sign & Broadcast",
"sign_and_broadcast_btn": "Sign & Broadcast",
"sign_btn": "Sign",
"reject_btn": "Ignore"
"reject_btn": "Ignore",
"receipt": {
"title": "Do you want a receipt?",
"yes": "Yes, I want a receipt.",
"no": "No, I don't want a receipt."
}
},
"whitelist": {
"prompt": "Whitelist subsequent '{{method}}' requests from this app?"
Expand Down
1 change: 1 addition & 0 deletions build/webpack.app.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module.exports = env => {
entry: {
background: "./src/background.js",
modal: "./src/modal.js",
receipt: "./src/receipt.js",
app: "./src/app.js"
},
output: {
Expand Down
1,499 changes: 861 additions & 638 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "beet",
"productName": "Beet Blockchain Companion",
"version": "0.16.0",
"version": "0.20.0",
"apiversion": 3,
"description": "Beet is a stand-alone key-manager and signing app for blockchains like BitShares, Bitcoin and others.",
"author": "clockworkgr <alex@clockwork.gr>",
Expand Down
116 changes: 100 additions & 16 deletions src/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import * as Actions from './lib/Actions';
let mainWindow;
let modalWindows = {};
let modalRequests = {};

let receiptWindows = {};
var timeout;

var isDevMode = process.execPath.match(/[\\/]electron/);
Expand Down Expand Up @@ -70,17 +72,14 @@ const createModal = async (arg, modalEvent) => {
}

modalRequests[id] = {request: request, event: modalEvent};

let targetURL = `file://${__dirname}/modal.html?`
+ `id=${encodeURIComponent(id)}`
+ `&type=${encodeURIComponent(type)}`
+ `&request=${encodeURIComponent(JSON.stringify(request))}`;
let targetURL = `file://${__dirname}/modal.html?id=${encodeURIComponent(id)}`;
let modalData = { id, type, request };

if (type === Actions.REQUEST_LINK) {
let existingLinks = arg.existingLinks;
if (existingLinks) {
modalRequests[id]['existingLinks'] = existingLinks;
targetURL += `&existingLinks=${encodeURIComponent(JSON.stringify(existingLinks))}`;
modalData['existingLinks'] = existingLinks;
}
}

Expand All @@ -92,8 +91,8 @@ const createModal = async (arg, modalEvent) => {
}
modalRequests[id]['visualizedAccount'] = visualizedAccount;
modalRequests[id]['visualizedParams'] = visualizedParams;
targetURL += `&visualizedAccount=${encodeURIComponent(visualizedAccount)}`;
targetURL += `&visualizedParams=${encodeURIComponent(visualizedParams)}`;
modalData['visualizedAccount'] = visualizedAccount;
modalData['visualizedParams'] = visualizedParams;
}

if ([Actions.VOTE_FOR].includes(type)) {
Expand All @@ -102,7 +101,7 @@ const createModal = async (arg, modalEvent) => {
throw 'Missing required payload field'
}
modalRequests[id]['payload'] = payload;
targetURL += `&payload=${encodeURIComponent(JSON.stringify(payload))}`;
modalData['payload'] = payload;
}

if ([
Expand All @@ -117,7 +116,7 @@ const createModal = async (arg, modalEvent) => {
throw 'Missing required accounts field'
}
modalRequests[id]['accounts'] = accounts;
targetURL += `&accounts=${encodeURIComponent(JSON.stringify(accounts))}`;
modalData['accounts'] = accounts;
}

if ([Actions.TRANSFER].includes(type)) {
Expand All @@ -136,22 +135,27 @@ const createModal = async (arg, modalEvent) => {
let target = arg.target;
modalRequests[id]['target'] = target;

targetURL += `&chain=${encodeURIComponent(chain)}`;
targetURL += `&accountName=${encodeURIComponent(accountName)}`;
targetURL += `&target=${encodeURIComponent(target)}`;
targetURL += `&toSend=${encodeURIComponent(toSend)}`;
modalData['chain'] = chain;
modalData['accountName'] = accountName;
modalData['target'] = target;
modalData['toSend'] = toSend;
}

if ([Actions.INJECTED_CALL, Actions.TRANSFER].includes(type)) {
if (arg.isBlockedAccount) {
modalRequests[id]['warning'] = true;
targetURL += `&warning=blockedAccount`;
modalData['warning'] = "blockedAccount";
} else if (arg.serverError) {
modalRequests[id]['warning'] = true;
targetURL += `&warning=serverError`;
modalData['warning'] = "serverError";
}
}

ipcMain.on(`get:prompt:${id}`, (event) => {
// The modal window is ready to receive data
event.reply(`respond:prompt:${id}`, modalData);
});

modalWindows[id] = new BrowserWindow({
parent: mainWindow,
title: 'Beet prompt',
Expand Down Expand Up @@ -193,6 +197,75 @@ const createModal = async (arg, modalEvent) => {
}
});
delete modalRequests[id];
modalData = {};
}
});
}

/*
* Creating an optional receipt browser window popup
*/
const createReceipt = async (arg, modalEvent) => {
let modalHeight = 600;
let modalWidth = 800;
if (!mainWindow) {
logger.debug(`No window`);
throw 'No main window';
}

let request = arg.request;
let id = request.id;
let result = arg.result;
let receipt = arg.receipt;
let notifyTXT = arg.notifyTXT;
if (!request || !request.id || !result || !notifyTXT || !receipt) {
logger.debug(`No request`);
throw 'No request';
}

if (receiptWindows[id]) {
throw 'Receipt window exists already!';
}

let targetURL = `file://${__dirname}/receipt.html?id=${encodeURIComponent(id)}`;

ipcMain.on(`get:receipt:${id}`, (event) => {
// The modal window is ready to receive data
event.reply(
`respond:receipt:${id}`,
{ id, request, result, receipt, notifyTXT }
);
});

receiptWindows[id] = new BrowserWindow({
parent: mainWindow,
title: 'Beet receipt',
width: modalWidth,
height: modalHeight,
minWidth: modalWidth,
minHeight: modalHeight,
maxWidth: modalWidth,
maximizable: true,
maxHeight: modalHeight,
useContentSize: true,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true
},
icon: __dirname + '/img/beet-taskbar.png'
});

receiptWindows[id].loadURL(targetURL);

receiptWindows[id].once('ready-to-show', () => {
console.log('ready to show modal')
receiptWindows[id].show();
})

receiptWindows[id].on('closed', () => {
if (receiptWindows[id]) {
delete receiptWindows[id];
}
});
}
Expand Down Expand Up @@ -314,6 +387,17 @@ const createWindow = async () => {
}
})

/*
* Create receipt popup & wait for user response
*/
ipcMain.on('createReceipt', async (event, arg) => {
try {
await createReceipt(arg, event);
} catch (error) {
console.log(error);
}
})

ipcMain.on('notify', (event, arg) => {
logger.debug("notify");
const NOTIFICATION_TITLE = 'Beet wallet notification';
Expand Down
37 changes: 19 additions & 18 deletions src/components/lang-select.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup>
import { ref, onMounted, computed, inject } from 'vue';
import { ref, onMounted, computed, inject, defineProps } from 'vue';
import { useI18n } from 'vue-i18n';
import { locales, defaultLocale, selectLocales, menuLocales } from "../config/i18n.js";
import { defaultLocale, selectLocales, menuLocales } from "../config/i18n.js";
import RendererLogger from "../lib/RendererLogger";
import store from '../store/index';
Expand All @@ -19,16 +19,12 @@
}
});
let localesRef = computed(() => {
return menuLocales;
});
let location = computed(() => {
return props.location;
});
let selected = ref(
store.state.SettingsStore.settings.locale.iso ?? defaultLocale.iso
store.state.SettingsStore.settings.locale?.iso ?? defaultLocale.iso
);
let open = ref(false);
Expand All @@ -42,14 +38,14 @@
}
function onSelected(locale) {
emitter.emit('i18n', locale.value);
store.dispatch("SettingsStore/setLocale", {locale: locale.value});
selected.value = locale.value;
const detectedLocale = selectLocales[locale.index].value
emitter.emit('i18n', detectedLocale);
store.dispatch("SettingsStore/setLocale", {locale: detectedLocale});
selected.value = detectedLocale;
open.value = false;
}
</script>
<template>
<ui-menu-anchor
v-if="location === 'prompt'"
Expand All @@ -64,11 +60,18 @@
</ui-button>
<ui-menu
v-model="open"
style="border: 1px solid #C7088E;"
style="border: 1px solid #C7088E; color: black;"
position="BOTTOM_START"
:items="localesRef"
@selected="onSelected"
/>
>
<ui-menuitem
v-for="item in selectLocales"
:key="item.value"
:value="item.value"
>
{{ item.label }}
</ui-menuitem>
</ui-menu>
</ui-menu-anchor>
<ui-menu-anchor
v-else
Expand All @@ -89,11 +92,9 @@
<ui-menuitem
v-for="locale in selectLocales"
:key="locale.value"
:value="locale.value"
:value="locale.label"
>
<ui-menuitem-text>
{{ locale.label }}
</ui-menuitem-text>
{{ locale.label }}
</ui-menuitem>
</ui-menu>
</ui-menu-anchor>
Expand Down
Loading

0 comments on commit 36fa580

Please sign in to comment.