Skip to content

Commit 7e01407

Browse files
committed
Merge branch 'dev' into feat/spinner-when-restore
2 parents 7b73a91 + feeb952 commit 7e01407

File tree

18 files changed

+594
-329
lines changed

18 files changed

+594
-329
lines changed

.github/workflows/pwa-testnet.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: PWA Testnet Workflow
2+
3+
on:
4+
push:
5+
branches:
6+
- dev
7+
8+
env:
9+
SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }}
10+
PREVIEW_DOMAIN: https://msg-adamant-testnet.surge.sh
11+
12+
jobs:
13+
build-and-deploy-to-surge:
14+
name: Build and Deploy with Testnet ADM nodes to surge
15+
runs-on: ubuntu-latest
16+
environment: testnet
17+
steps:
18+
- name: Checkout repository 🛎️
19+
uses: actions/checkout@v4
20+
21+
- name: Setup Node version 🍀
22+
uses: actions/setup-node@v4
23+
with:
24+
node-version: '20'
25+
26+
- name: Install dependencies ⚙️
27+
run: npm ci
28+
29+
- name: Build PWA 🛠️
30+
run: |
31+
npm run schema:generate
32+
npm run build:testnet
33+
34+
- name: Archive artifacts 📁
35+
uses: actions/upload-artifact@v4
36+
with:
37+
path: dist
38+
39+
- name: Deploy to surge 🚀
40+
run: |
41+
npm install --global surge
42+
surge ./dist ${{ env.PREVIEW_DOMAIN }} --token ${{ secrets.SURGE_TOKEN }}

electron-builder.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ mac:
4343
- arm64
4444

4545
afterSign: 'scripts/electron/notarize.cjs'
46+
afterPack: 'scripts/electron/sandboxFix.mjs'
47+
4648

4749
# Config for OSX dmg
4850
dmg:

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@
1010
"serve": "vite preview --config vite-pwa.config.ts",
1111
"dev": "vite --config vite-pwa.config.ts",
1212
"dev:localnet": "vite --host 0.0.0.0 --config vite-pwa.config.ts",
13-
"serve:test": "cross-env ADM_CONFIG_FILE=test vue-cli-service serve",
13+
"dev:testnet": "vite --config vite-pwa.config.ts --mode testnet",
14+
"dev:tor": "vite --config vite-pwa.config.ts --mode tor",
1415
"wallets:generate": "npm run wallets:data:generate && npm run wallets:types:generate",
1516
"wallets:data:generate": "node scripts/wallets.mjs",
1617
"wallets:types:generate": "swagger-typescript-api -p ./adamant-wallets/specification/openapi.json -o ./src/types/wallets -n index.ts --no-client",
1718
"build": "vue-tsc && vite build --config vite-pwa.config.ts",
19+
"build:testnet": "vue-tsc && vite build --config vite-pwa.config.ts --mode testnet",
20+
"build:tor": "vue-tsc && vite build --config vite-pwa.config.ts --mode tor",
1821
"lint": "eslint --ext .ts,.js,.vue --fix ./src",
1922
"prettify": "prettier --write src/",
2023
"typecheck": "vue-tsc --noEmit",

scripts/electron/sandboxFix.mjs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// copied and modified from https://github.com/gergof/electron-builder-sandbox-fix/blob/master/lib/index.js
2+
3+
import fs from 'fs/promises'
4+
import path from 'path'
5+
import chalk from 'chalk'
6+
7+
const log = (message, dotFormatting = chalk.blue) => {
8+
console.log(` ${dotFormatting('•')} ${message}`)
9+
}
10+
11+
const afterPackHook = async (params) => {
12+
if (params.electronPlatformName !== 'linux') {
13+
// this fix is only required on linux
14+
return
15+
}
16+
17+
const executable = path.join(params.appOutDir, params.packager.executableName)
18+
19+
const binPath = path.join(path.dirname(executable), `${params.packager.executableName}.bin`)
20+
21+
const loaderScript = `#!/usr/bin/env bash
22+
exec "${binPath}" "--no-sandbox" "$@"
23+
`
24+
try {
25+
await fs.rename(executable, executable + '.bin')
26+
await fs.writeFile(executable, loaderScript)
27+
await fs.chmod(executable, 0o755)
28+
} catch (e) {
29+
log('failed to create loader for sandbox fix: ' + e.message, chalk.red)
30+
throw new Error('Failed to create loader for sandbox fix')
31+
}
32+
33+
log('sandbox fix successfully applied', chalk.green)
34+
}
35+
36+
export default afterPackHook

scripts/wallets.mjs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ async function run(branch = 'master') {
3333

3434
await updateProductionConfig(config)
3535
await updateDevelopmentConfig(config)
36+
await updateTestnetConfig(config)
3637
await updateTorConfig(config)
3738

3839
console.log('Coins updated successfully')
@@ -152,6 +153,16 @@ function updateDevelopmentConfig(configs) {
152153
return updateConfig(configs, 'development')
153154
}
154155

156+
function updateTestnetConfig(configs) {
157+
const testnetConfigs = _.mapValues(configs, (config) => {
158+
if (config.testnet) config.nodes.list = config.testnet.nodes.list
159+
160+
return config
161+
});
162+
163+
return updateConfig(testnetConfigs, 'testnet')
164+
}
165+
155166
function updateTorConfig(configs) {
156167
const torConfigs = _.mapValues(configs, (config) => {
157168
const torConfig = _.mergeWith(config, config.tor, (value, srcValue) => {

src/components/LoginForm.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ export default defineComponent({
174174
175175
&:deep(.v-field__input) {
176176
width: 100%;
177-
padding-right: 0;
177+
padding-right: 32px;
178+
padding-left: 32px;
178179
}
179180
}
180181
}

src/components/LoginPasswordForm.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,8 @@ export default defineComponent({
160160
161161
&:deep(.v-field__input) {
162162
width: 100%;
163-
padding-right: 0;
163+
padding-right: 32px;
164+
padding-left: 32px;
164165
}
165166
166167
:deep(input) {

src/components/QrcodeCapture.vue

Lines changed: 112 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
2-
<div :class="className">
3-
<div :class="`${className}__activator`" @click="$refs.fileInput.click()">
2+
<div :class="classes.root">
3+
<div :class="classes.activator" @click="fileInput?.click()">
44
<slot />
55
</div>
66

@@ -9,88 +9,131 @@
99
ref="fileInput"
1010
type="file"
1111
accept="image/*"
12-
:class="`${className}__file-input`"
12+
:class="classes.input"
1313
@change="onFileSelect"
1414
/>
1515

16-
<img ref="imageElement" :src="imageBase64" :class="`${className}__image`" />
16+
<canvas ref="canvasElement" :class="classes.image" />
1717
</div>
1818
</template>
1919

20-
<script>
20+
<script setup lang="ts">
2121
import { vibrate } from '@/lib/vibrate'
22+
import { useTemplateRef } from 'vue'
23+
import type { BrowserQRCodeReader } from '@zxing/browser'
2224
23-
export default {
24-
emits: ['detect', 'error'],
25-
data: () => ({
26-
selectedImage: undefined,
27-
imageBase64: '',
28-
qrCodeText: '',
29-
codeReader: undefined
30-
}),
31-
computed: {
32-
className() {
33-
return 'qrcode-capture'
25+
const IMG_MAX_SIZE = 400
26+
27+
const emit = defineEmits<{
28+
(e: 'detect', text: string): void
29+
(e: 'error', err: unknown): void
30+
}>()
31+
32+
const className = 'qrcode-capture'
33+
34+
const classes = {
35+
root: className,
36+
activator: `${className}__activator`,
37+
input: `${className}__file-input`,
38+
image: `${className}__image`
39+
}
40+
41+
let codeReader: BrowserQRCodeReader
42+
43+
const canvas = useTemplateRef('canvasElement')
44+
const fileInput = useTemplateRef('fileInput')
45+
46+
const drawCanvas = (file: File) => {
47+
const img = new Image()
48+
const imgUrl = URL.createObjectURL(file)
49+
50+
const revokeObjectURL = () => {
51+
URL.revokeObjectURL(imgUrl)
52+
}
53+
54+
const promise = new Promise((resolve, reject) => {
55+
img.onload = () => {
56+
if (!canvas.value) {
57+
return reject()
58+
}
59+
60+
const ctx = canvas.value.getContext('2d')
61+
62+
if (!ctx) {
63+
return reject()
64+
}
65+
66+
const ratio = img.width / img.height
67+
let newWidth = IMG_MAX_SIZE
68+
let newHeight = IMG_MAX_SIZE / ratio
69+
70+
if (newHeight > IMG_MAX_SIZE) {
71+
newHeight = IMG_MAX_SIZE
72+
newWidth = IMG_MAX_SIZE * ratio
73+
}
74+
75+
canvas.value.width = newWidth
76+
canvas.value.height = newHeight
77+
78+
ctx.drawImage(img, 0, 0, canvas.value.width, canvas.value.height)
79+
80+
resolve(canvas)
3481
}
35-
},
36-
methods: {
37-
async onFileSelect(event) {
38-
this.selectedImage = event.target.files[0]
3982
40-
try {
41-
const { BrowserQRCodeReader } = await import('@zxing/browser')
42-
this.codeReader = new BrowserQRCodeReader()
43-
this.imageBase64 = await this.getImageBase64()
44-
this.qrCodeText = await this.tryToDecode()
83+
img.onerror = (e) => reject(e)
4584
46-
vibrate.veryShort()
85+
img.src = imgUrl
86+
})
4787
48-
this.$emit('detect', this.qrCodeText)
49-
} catch (err) {
50-
vibrate.tripleVeryShort()
88+
promise.finally(revokeObjectURL)
89+
90+
return promise
91+
}
5192
52-
this.$emit('error', err)
93+
const getQrcode = () => {
94+
return codeReader?.decodeFromCanvas(canvas.value!).getText()
95+
}
96+
97+
const tryToDecode = () => {
98+
return new Promise<string>((resolve, reject) => {
99+
// Vue should rerender <canvas> element,
100+
// so add a callback to the macrotasks queue
101+
setTimeout(() => {
102+
try {
103+
resolve(getQrcode())
104+
} catch (e) {
105+
reject(e)
53106
}
54-
// Reset input to trigger change event later if user selects same image (Chrome)
55-
this.$refs.fileInput.value = ''
56-
},
57-
58-
/**
59-
* Converts image into Base64.
60-
* @returns {Promise<string>}
61-
*/
62-
getImageBase64() {
63-
return new Promise((resolve, reject) => {
64-
const reader = new FileReader()
65-
66-
reader.onload = (e) => resolve(e.target.result)
67-
reader.onerror = (err) => reject(err)
68-
69-
reader.readAsDataURL(this.selectedImage)
70-
})
71-
},
72-
73-
/**
74-
* Decode QRCode from Base64 image.
75-
* @returns {Promise<string>}
76-
*/
77-
async getQrcode() {
78-
const result = await this.codeReader.decodeFromImageElement(this.$refs.imageElement)
79-
80-
return result.text
81-
},
82-
83-
tryToDecode() {
84-
return new Promise((resolve, reject) => {
85-
// Vue should rerender <img> element,
86-
// so add a callback to the macrotasks queue
87-
setTimeout(() => {
88-
this.getQrcode()
89-
.then((qrCodeText) => resolve(qrCodeText))
90-
.catch((err) => reject(err))
91-
}, 0)
92-
})
107+
}, 0)
108+
})
109+
}
110+
111+
const onFileSelect = async (event: Event) => {
112+
try {
113+
if (!codeReader) {
114+
const { BrowserQRCodeReader } = await import('@zxing/browser')
115+
codeReader = new BrowserQRCodeReader()
93116
}
117+
118+
const input = event.target as HTMLInputElement
119+
120+
const file = input.files![0]!
121+
122+
await drawCanvas(file)
123+
const qrCodeText = await tryToDecode()
124+
125+
vibrate.veryShort()
126+
127+
emit('detect', qrCodeText)
128+
} catch (err) {
129+
vibrate.tripleVeryShort()
130+
131+
emit('error', err)
132+
}
133+
134+
if (fileInput.value) {
135+
// Reset input to trigger change event later if user selects same image (Chrome)
136+
fileInput.value.value = ''
94137
}
95138
}
96139
</script>

src/components/SendFundsForm.vue

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,11 @@
189189
<script>
190190
import { adm } from '@/lib/nodes'
191191
import klyIndexer from '@/lib/nodes/kly-indexer'
192-
import { AllNodesDisabledError, AllNodesOfflineError, NoInternetConnectionError } from '@/lib/nodes/utils/errors'
192+
import {
193+
AllNodesDisabledError,
194+
AllNodesOfflineError,
195+
NoInternetConnectionError
196+
} from '@/lib/nodes/utils/errors'
193197
import { PendingTransactionError } from '@/lib/pending-transactions'
194198
import axios from 'axios'
195199
import { computed, nextTick } from 'vue'
@@ -235,7 +239,6 @@ import { MAX_UINT64 } from '@klayr/validator'
235239
import { mdiDotsVertical, mdiMenuDown } from '@mdi/js'
236240
import { useStore } from 'vuex'
237241
238-
239242
/**
240243
* @returns {string | boolean}
241244
*/
@@ -290,7 +293,7 @@ export default {
290293
const isOnline = computed(() => store.getters['isOnline'])
291294
292295
const checkIsOnline = () => {
293-
return navigator.onLine || isOnline.value;
296+
return navigator.onLine || isOnline.value
294297
}
295298
296299
return {

0 commit comments

Comments
 (0)