Skip to content
This repository has been archived by the owner on Jun 7, 2023. It is now read-only.

Add payment browser notifications #52

Merged
merged 8 commits into from
Dec 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .nowignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.tests
.*
assets
ios
node_modules
Expand Down
13 changes: 11 additions & 2 deletions src-ui/components/inputs/Toggle.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script>
export let on
export let disabled

$: active = $on === true
</script>
Expand All @@ -14,7 +15,13 @@
background: var(--box-bg);
cursor: pointer;
}
knob {

toggle.disabled {
pointer-events: none;
}

knob,
toggle.disabled knob.active {
position: absolute;
top: 2px;
left: 2px;
Expand All @@ -25,6 +32,7 @@
opacity: 0.2;
transition: all 0.1s cubic-bezier(0.4, 0, 0.2, 1);
}

knob.active {
left: 20px;
opacity: 1;
Expand All @@ -34,6 +42,7 @@
<toggle
on:click={() => {
on.update((on) => !on)
}}>
}}
class:disabled>
<knob class:active />
</toggle>
81 changes: 65 additions & 16 deletions src-ui/lib/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { derived, get, writable, Writable } from 'svelte/store'
import { Account } from '@iota/account'
import { CDAParams, CDA } from '@iota/cda'

import { cda, persistent, getRandomNode, isDevnet } from '~/lib/helpers'
import { cda, formatValue, persistent, getRandomNode, isDevnet } from '~/lib/helpers'
import API from '~/lib/api'

/**
Expand Down Expand Up @@ -54,45 +54,94 @@ export const updateHistory = async (

const $history = get(history) as Transaction[]
const $address = get(address) as cda

const bundle = !(payload instanceof Array) ? payload.bundle : payload

const tx =
const incomingTx =
incoming && !(payload instanceof Array)
? bundle.find((item) => item.value > 0 && item.address === payload.address)
: bundle.find((item) => item.currentIndex === 0)

if (!tx) {
if (!incomingTx) {
return
}

const historyEntry = $history.find((item) => item.address === tx.address)
// Check if CDA address exists in history
const addressExists = $history.find((item) => item.address === incomingTx.address)

if (!historyEntry) {
if (!addressExists) {
return
}

const historyIndex = $history.findIndex(
(item) => item.address === tx.address && item.incoming === incoming && (!item.bundle || item.bundle === tx.bundle)
// Check if history item already exists
const existingIndex = $history.findIndex(
(item) =>
item.address === incomingTx.address &&
item.incoming === incoming &&
(!item.bundle || item.bundle === incomingTx.bundle)
)

if ($address && $address.address.substr(0, 81) === historyEntry.address && incoming) {
const existingTx = $history[existingIndex]

// Unset current request adddress if it is receiving tokens
if ($address && $address.address.substr(0, 81) === incomingTx.address && incoming) {
address.set(null)
}

if (historyIndex > -1) {
if (!$history[historyIndex].bundle && !incoming) {
// If history item already exists - update it, otherwise add to history
if (existingIndex > -1) {
if (!existingTx.bundle && !incoming) {
sendState.set('done')
}

$history[historyIndex] = {
...$history[historyIndex],
...tx,
persistence: $history[historyIndex].persistence || tx.persistence
// Show notification if incoming payment
if (incoming) {
const value = formatValue(incomingTx.value)

if (!existingTx.bundle) {
new Notification(`New pending payment`, {
icon: '/icons/512x512.png',
body: `You are receiving ${value.rounded}${value.unit}`
})
}

if (!existingTx.persistence && incomingTx.persistence) {
new Notification(`Payment confirmed`, {
icon: '/icons/512x512.png',
body: `Incoming payment of ${value.rounded}${value.unit} has confirmed`
})
}
}

// Show notification if outgoing payment
if (!incoming) {
const value = formatValue(incomingTx.value)

if (!existingTx.bundle) {
sendState.set('done')

new Notification(`Payment sent`, {
icon: '/icons/512x512.png',
body: `Payment of ${value.rounded}${value.unit} was just sent`
})
}

if (!existingTx.persistence && incomingTx.persistence) {
new Notification(`Payment confirmed`, {
icon: '/icons/512x512.png',
body: `Outgoing payment of ${value.rounded}${value.unit} has confirmed`
})
}
}

$history[existingIndex] = {
...existingTx,
...incomingTx,
persistence: existingTx.persistence || incomingTx.persistence
}
history.set($history)
} else {
history.update((item) => item.concat([{ ...historyEntry, ...tx }]))
history.update((item) => item.concat([{ ...addressExists, ...incomingTx }]))
}
}

Expand Down
5 changes: 5 additions & 0 deletions src-ui/lib/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ export const fiatCurrency = persistent<string>('fiatCurrency', 'USD')
*/
export const backupReminder = persistent<boolean>('backupReminder', true)

/**
* Application notifications enabled state
*/
export const showNotifications = persistent<boolean>('showNotifications', true)

/**
* Unset notification timeout
*/
Expand Down
2 changes: 1 addition & 1 deletion src-ui/lib/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export const getRandomNode = async (): Promise<string> => {
*/
export const formatValue = (
iotas: number,
marketPrice: MarketPrice,
marketPrice?: MarketPrice,
units?: string
): { value: number; rounded: string; unit: string; fiat: string } => {
let value = getIotas(iotas, units, marketPrice)
Expand Down
9 changes: 8 additions & 1 deletion src-ui/views/Dashboard.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script>
import { onMount } from 'svelte'
import API from '~/lib/api'
import { error, backupReminder } from '~/lib/app'
import { error, backupReminder, showNotifications } from '~/lib/app'
import { goto, formatValue, parseLink } from '~/lib/helpers'
import { account, balance, history, setAddress } from '~/lib/account'
import { marketPrice } from '~/lib/market'
Expand Down Expand Up @@ -47,6 +48,12 @@
goto('pay')
}
}

onMount(() => {
if ($showNotifications && typeof Notification === 'function' && Notification.permission === 'default') {
Notification.requestPermission()
}
})
</script>

<style>
Expand Down
16 changes: 15 additions & 1 deletion src-ui/views/Settings.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
import { Export, Button, Dropdown, Footer, Header, Icon, Tabs, Toggle, Warning } from '~/components'
import { account, seed } from '~/lib/account'
import { marketData } from '~/lib/market'
import { darkMode, fiatCurrency } from '~/lib/app'
import { darkMode, fiatCurrency, showNotifications } from '~/lib/app'

let showWarning = false
let showExport = false

$: currencies = getCurrencies($marketData.rates)

let disabledNotifications = typeof Notification !== 'function' || Notification.permission === 'denied'

const getCurrencies = ($rates) => {
if (!$rates) {
return []
Expand Down Expand Up @@ -172,6 +174,18 @@
</label>
<p>Visual theme optimised for night time use</p>
<hr />
<label class="inline">
<span>Notifications</span>
<span>
<Toggle disabled={disabledNotifications} on={showNotifications} />
</span>
</label>
{#if disabledNotifications}
<p>Notifications are blocked by your browser. Enable them in the browser settings and restart Spark.</p>
{:else}
<p>Show new and confirmed payment notifications</p>
{/if}
<hr />
</section>
{/if}
{#if tab === 'Advanced'}
Expand Down