Skip to content

Commit

Permalink
V2 (#1485)
Browse files Browse the repository at this point in the history
* Update pages structure (#1476)

* update pages structure

* use routes helper

* replace route string

* fix paths

* Update import paths (#1487)

* update tsconfig

* use absolute paths

* Add base layout (#1488)

* add base layout and sidebar

* move wallet widget up

* update tests

* rename component

* Add settings page (#1489)

* add page

* fix

* Connect settings page (#1498)

* expose settings fns to view

* use in settings page

* remove from tray

* fix

* move to settings.js

* update checkbox update

* Update renderer/src/pages/settings/Settings.tsx

Co-authored-by: Julian Gruber <[email protected]>

---------

Co-authored-by: Julian Gruber <[email protected]>

* Update tests (#1510)

* update deps

* fix mocks

* add test for settings

* add tests

* remove uneeded

* Add wallet modal (#1514)

* add radix dialog

* create dialog provider comp

* add dialog to layout, remove curtain

* add wallet modal content, and utils

* close dialog on route change

* fix util

* update tests

* Add wallet page content (#1515)

* add basic wallet page

* tx history

* add basic transfer form

* fix form

* fix condition

* Setup dashboard chart (#1534)

* add mock rewards data

* add hook, move rewards out of activity hook

* add basic chart, add deps

* update tests

* Style sidebar (#1518)

* add new icons

* initial styling

* style links

* add expandable

* fix

* font size fix

* replace icon

* Add chart controls (#1544)

* generate mock data

* adjust scheduled reward viz

* fixes

* add filtered

* fix scheduled rewards gen

* Add modules page (#1524)

* add page

* create hook with mock data

* Add draggable bar (#1545)

* create draggable component

* fix layout

* fix drag style

* add bg pattern

* Add modules api (#1550)

* add modules api

* add spark logo

* add voyager logo

* Update design system (#1551)

* update tailwind config and styles

* update changed

* add text and button generics

* update layout

* add switch

* add safelist to config

* font type fix

* Style settings page (#1560)

* use settings group comp

* add icons

* fixes

* layout fix

* add bordered box

* fix test

* use html ents

* Add openExternalURL (#1571)

* add openExternalURL

* normalize urls

* add tests

* replace other url handlers

* add pattern allowlist

* Style wallet page info (#1568)

* add new icons

* add tooltip component

* add address component

* add page shell

* use appshell in settings

* style half of wallet page

* improve address tooltips

* add tx empty state

* fixes

* fix indent

* lint fix

* Address fixes

* remove pageshell

* `eslint --fix .`

* fix don't update balance while transaction processing

* `eslint --fix .`

* Style modules page (#1577)

* setup mod card component

* add tags

* add icons

* style card

* handle text overflow

* indent fix

* Update rewards mock data (#1576)

* update mock data gen

* chart controls for mod id

* move fns out of utils

* Update renderer/src/lib/utils.ts

Co-authored-by: Julian Gruber <[email protected]>

---------

Co-authored-by: Julian Gruber <[email protected]>

* Style transfer flow (#1572)

* add Input component

* create transfer wrapper comp

* add error state to Input component

* add variant to input

* create transfer flow components

* add adress validation hook

* add Button disabled state and 3rd variant

* add tooltip to address save

* add transfer states

* add icon

* fix validation initial valid

* Update renderer/src/components/Tooltip.tsx

Co-authored-by: Julian Gruber <[email protected]>

* Update renderer/src/components/Tooltip.tsx

Co-authored-by: Julian Gruber <[email protected]>

* Update renderer/src/components/Tooltip.tsx

Co-authored-by: Julian Gruber <[email protected]>

* rename isShowingConfirm

* remove lint ignore

* rename useCallback

* feedback changes

* use ref to track status

* use tx status

* lint indent fixes

---------

Co-authored-by: Julian Gruber <[email protected]>

* Style wallet widget (#1586)

* update wallet widget

* add modal content, styles

* show sent or received

* add status indicator comp

* add spinner loading

* hide on wallet page

* fix tooltip maxwidth

* improvements

* fix tests

* Style dashboard info (#1587)

* style info

* create select component

* add tab btn

* style values info

* use togglegroup component

* fix maxwidth

* lint fix

* fix ui test

* add default val to select

* Configure chart styles (#1593)

* update chart config

* create custom tooltip

* add cross lines on hover

* fix tooltip movement

* add payout event indicator

* update layout

* add payout version tooltip

* fixes

* fix, add comment

* fix e2e test

* Add transfer flow transitions (#1594)

* add Transition comp

* animate form, step 1

* animate next steps

* improvements for Transition

* update tx indicator in blance cotnrol

* style tweaks, fixes

* reinstall deps

* Fix wallet hook and sync (#1598)

* backend fix

* fix hook

* remove uneeded hook

* Add grid (#1599)

* add grid canvas

* add grid class, with warp

* ro count fix

* fix warp point calc

* rerender on resize

* force as prop

* add tween render

* warp on balance

* grid improvements, add midline reveal

* add transfer glow

* remove mocked state

* rebase fix

* get config for balance

* style tweaks

* persist grid

* remove comment

* Update renderer/src/lib/grid-utils.ts

Co-authored-by: Julian Gruber <[email protected]>

* Update renderer/src/lib/grid.ts

Co-authored-by: Julian Gruber <[email protected]>

* Update renderer/src/lib/grid.ts

Co-authored-by: Julian Gruber <[email protected]>

* move utils to grid

* update import path

---------

Co-authored-by: Julian Gruber <[email protected]>

* Highlight latest tx (#1601)

* highlight latest tx

* fix

* add transition

* rename

* style fix

* General fixes (#1602)

* fix button font size

* fix walletwidget drag

* fix sidebar

* improve forms

* copy fix

* render grid when no dest addresss

* fix openAtLogin initial state

* add fadeins

* fix overflow sizes

* fix grid when on resize render

* fix wallet page tabindex order

* Remove old files (#1617)

* remove components

* remove icons

* remove empty css

* remove 1d (#1616)

* Add read scheduled rewards from API (#1618)

* add read scheduled rewards from API

* dynamic from/to

* finish query

* update scheduled rewards url

* fix scheduled rewards parsing

* style

* add historic reward transfers

* Add update historic rewards (#1624)

* add update historic rewards every hour

* skip update when window hidden

* update when window becomes visible

* update every 20 minutes (round length)

* add safe (#1628)

* Frontend file structure proposal (#1477)

* first draft

* Update docs/architecture-decision-records/2024-04-frontend-file-structure.md

Co-authored-by: Julian Gruber <[email protected]>

* Update docs/architecture-decision-records/2024-04-frontend-file-structure.md

Co-authored-by: Julian Gruber <[email protected]>

* Update docs/architecture-decision-records/2024-04-frontend-file-structure.md

Co-authored-by: Julian Gruber <[email protected]>

* Update docs/architecture-decision-records/2024-04-frontend-file-structure.md

Co-authored-by: Julian Gruber <[email protected]>

---------

Co-authored-by: Julian Gruber <[email protected]>

* add dynamic SPARK rewards

* Fixes  (#1629)

* fix tooltip zindex

* chart y min

* disable input spellcheck

* coming soon

* deprecated -> ended

* add laoding

* fix resize (#1631)

* Add tests (#1634)

* update dashboard test 1st half

* update dashboard populated

* add wallet page tests

* remove file

* fix

* remove log

* 2.0.0-0

* Open the wallet docs in external browser (#1640)

* tray: fix updater referencing removed items (#1658)

* StationRewards: fix rewards not accumulating

* Chart: fix summing logic for scheduled rewards

* 2.0.0-1

* explain June 13th situation

* 2.0.0-2

* 2.0.0-3

* prevent deselect time range (#1673)

---------

Co-authored-by: David Lange <[email protected]>
  • Loading branch information
juliangruber and davelange authored Jul 8, 2024
1 parent d841f97 commit b25bcaa
Show file tree
Hide file tree
Showing 131 changed files with 16,918 additions and 28,899 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Frontend file structure

- Status: PROPOSED


## Context

As the app UI is becoming more complex, more groupings are necessary in order to keep the amount of components per file / folder sensibly small.


## Decision

We are adopting the following structure:
```
src/
pages/
dashboard/
Dashboard.tsx <- entrypoint
Graph.tsx <- component specific to page
...
components/ <- common UI components
Button.tsx
Text.tsx
...
```

- Each route should have its own directory inside `pages`
- Each route directory should have an entrypoint component with the name of the route (ex: `/dashboard` -> `Dashboard.tsx`)
- Alongside the entrypoint component, place any component that is specific to that route
- In the `components` directory, place common UI components, such as `Text`, `Button`, `Modal`, etc.
13 changes: 10 additions & 3 deletions main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ const { ipcMain } = require('electron/main')
const os = require('os')
const core = require('./core')
const wallet = require('./wallet')
const settings = require('./settings')
const serve = require('electron-serve')
const { setupAppMenu } = require('./app-menu')
const setupTray = require('./tray')
const setupUI = require('./ui')
const setupUpdater = require('./updater')
const Sentry = require('@sentry/node')
const telemetry = require('./telemetry')
const { validateExternalURL } = require('./utils')

const inTest = (process.env.NODE_ENV === 'test')
const isDev = !app.isPackaged && !inTest
Expand Down Expand Up @@ -123,6 +125,9 @@ const ctx = {

manualCheckForUpdates: () => { throw new Error('never get here') },
saveModuleLogsAs: () => { throw new Error('never get here') },
toggleOpenAtLogin: () => { throw new Error('never get here') },
isOpenAtLogin: () => { throw new Error('never get here') },
exportSeedPhrase: () => { throw new Error('never get here') },
showUI: () => { throw new Error('never get here') },
isShowingUI: false,
loadWebUIFromDist: serve({
Expand All @@ -131,9 +136,10 @@ const ctx = {
restartToUpdate: () => { throw new Error('never get here') },
openReleaseNotes: () => { throw new Error('never get here') },
getUpdaterStatus: () => { throw new Error('never get here') },
browseTransactionTracker: (/** @type {string} */ transactionHash) => { shell.openExternal(`https://beryx.zondax.ch/v1/search/fil/mainnet/address/${transactionHash}`) },
showTermsOfService: () => { shell.openExternal('https://pl-strflt.notion.site/Station-Terms-Conditions-e97da76bb89f49e280c2897aebe4c41f?pvs=4') },
openBeryx: () => { shell.openExternal('https://beryx.io/') },
openExternalURL: (/** @type {string} */ url) => {
validateExternalURL(url)
shell.openExternal(url)
},
transactionUpdate: (transactions) => {
ipcMain.emit(ipcMainEvents.TRANSACTION_UPDATE, transactions)
},
Expand Down Expand Up @@ -174,6 +180,7 @@ async function run () {
await wallet.setup(ctx)
await telemetry.setup()
await core.setup(ctx)
await settings.setup(ctx)

await core.run(ctx)
} catch (e) {
Expand Down
25 changes: 20 additions & 5 deletions main/ipc.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,28 @@ function setupIpcMain (/** @type {Context} */ ctx) {
(_events, _args) => ctx.getUpdaterStatus()
)
ipcMain.handle(
'station:browseTransactionTracker',
(_events, transactionHash) => ctx.browseTransactionTracker(transactionHash)
'station:openExternalURL',
(_events, url) => ctx.openExternalURL(url)
)
ipcMain.handle('station:openBeryx', () => ctx.openBeryx())
ipcMain.handle(
'station:showTermsOfService',
(_events) => ctx.showTermsOfService()
'station:toggleOpenAtLogin',
(_events) => ctx.toggleOpenAtLogin()
)
ipcMain.handle(
'station:isOpenAtLogin',
(_events) => ctx.isOpenAtLogin()
)
ipcMain.handle(
'station:exportSeedPhrase',
(_events) => ctx.exportSeedPhrase()
)
ipcMain.handle(
'station:saveModuleLogsAs',
(_events) => ctx.saveModuleLogsAs()
)
ipcMain.handle(
'station:checkForUpdates',
(_events) => ctx.manualCheckForUpdates()
)
}

Expand Down
13 changes: 8 additions & 5 deletions main/preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ contextBridge.exposeInMainWorld('electron', {
getUpdaterStatus: () => ipcRenderer.invoke('station:getUpdaterStatus'),
restartToUpdate: () => ipcRenderer.invoke('station:restartToUpdate'),
openReleaseNotes: () => ipcRenderer.invoke('station:openReleaseNotes'),
openBeryx: () => ipcRenderer.invoke('station:openBeryx'),

getScheduledRewards: () =>
ipcRenderer.invoke('station:getScheduledRewards'),
Expand All @@ -40,12 +39,16 @@ contextBridge.exposeInMainWorld('electron', {
ipcRenderer.invoke('station:getStationWalletTransactionsHistory'),
transferAllFundsToDestinationWallet: () =>
ipcRenderer.invoke('station:transferAllFundsToDestinationWallet'),
browseTransactionTracker: (/** @type {string } */ transactionHash) =>
ipcRenderer.invoke('station:browseTransactionTracker', transactionHash),
openExternalURL: (/** @type {string } */ url) =>
ipcRenderer.invoke('station:openExternalURL', url),
getScheduledRewards: () =>
ipcRenderer.invoke('station:getScheduledRewards'),
showTermsOfService: () =>
ipcRenderer.invoke('station:showTermsOfService')
toggleOpenAtLogin: () =>
ipcRenderer.invoke('station:toggleOpenAtLogin'),
isOpenAtLogin: () => ipcRenderer.invoke('station:isOpenAtLogin'),
exportSeedPhrase: () => ipcRenderer.invoke('station:exportSeedPhrase'),
saveModuleLogsAs: () => ipcRenderer.invoke('station:saveModuleLogsAs'),
checkForUpdates: () => ipcRenderer.invoke('station:checkForUpdates')
},
stationEvents: {
onActivityLogged: (/** @type {(value: Activity) => void} */ callback) => {
Expand Down
38 changes: 38 additions & 0 deletions main/settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
'use strict'

const { app, clipboard } = require('electron')
const wallet = require('./wallet')
const { showDialogSync } = require('./dialog')

/** @typedef {import('./typings').Context} Context */

/**
* @param {Context} ctx
*/
async function setup (ctx) {
ctx.toggleOpenAtLogin = () => {
const openAtLogin = !app.getLoginItemSettings().openAtLogin
app.setLoginItemSettings({ openAtLogin })
}

ctx.isOpenAtLogin = () => {
return app.getLoginItemSettings().openAtLogin
}

ctx.exportSeedPhrase = async () => {
const button = showDialogSync({
title: 'Export Seed Phrase',
// eslint-disable-next-line max-len
message: 'The seed phrase is used in order to back up your wallet, or move it to a different machine. Please be cautious, as anyone with access to it has full control over your wallet and funds.',
type: 'info',
buttons: ['Cancel', 'Copy to Clipboard']
})
if (button === 1) {
clipboard.writeText(await wallet.getSeedPhrase())
}
}
}

module.exports = {
setup
}
34 changes: 33 additions & 1 deletion main/test/utils.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'

const { formatTokenValue } = require('../utils')
const { formatTokenValue, validateExternalURL } = require('../utils')
const assert = require('assert').strict

describe('formatTokenValue', function () {
Expand Down Expand Up @@ -64,3 +64,35 @@ describe('formatTokenValue', function () {
assert.equal(result, expectedOutput)
})
})

describe('validateExternalURL', function () {
it('should throw on empty string', function () {
assert.throws(() => {
validateExternalURL('')
})
})

it('should throw on URL not in allowlist', function () {
assert.throws(() => {
validateExternalURL('https://google.com')
})
})

it('should not throw for allowed URL', function () {
assert.doesNotThrow(() => {
validateExternalURL('https://filspark.com/')
})
})

it('should not throw when url matches allowed pattern', function () {
assert.doesNotThrow(() => {
validateExternalURL('https://beryx.zondax.ch/v1/search/fil/mainnet/address/123')
})
})

it('should throw when url doesnt match allowed pattern', function () {
assert.throws(() => {
validateExternalURL('https://bery.zonda.ch/v1/search/fil/mainnet/address/123')
})
})
})
74 changes: 3 additions & 71 deletions main/tray.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
'use strict'

const { IS_MAC, STATION_VERSION } = require('./consts')
const { Menu, Tray, app, ipcMain, nativeImage, clipboard } = require('electron')
const { Menu, Tray, app, ipcMain, nativeImage } = require('electron')
const { ipcMainEvents } = require('./ipc')
const path = require('path')
const assert = require('node:assert')
const core = require('./core')
const { formatTokenValue } = require('./utils')
const { getSeedPhrase } = require('./wallet')
const { showDialogSync } = require('./dialog')

/** @typedef {import('./typings').Context} Context */

Expand Down Expand Up @@ -78,50 +76,6 @@ const createContextMenu = (/** @type {Context} */ ctx) => {
enabled: false
},
{ type: 'separator' },
{
id: 'checkForUpdates',
label: 'Check for Updates...',
click: () => { ctx.manualCheckForUpdates() }
},
{
id: 'checkingForUpdates',
label: 'Checking for Updates',
enabled: false,
visible: false
},
{
label: 'Save Module Logs As…',
click: function () {
ctx.saveModuleLogsAs()
}
},
{
label: 'Export Seed Phrase…',
click: async () => {
const button = showDialogSync({
title: 'Export Seed Phrase',
// eslint-disable-next-line max-len
message: 'The seed phrase is used in order to back up your wallet, or move it to a different machine. Please be cautious, as anyone with access to it has full control over your wallet and funds.',
type: 'info',
buttons: ['Cancel', 'Copy to Clipboard']
})
if (button === 1) {
clipboard.writeText(await getSeedPhrase())
}
}
},
{ type: 'separator' },
{
label: 'Start at login',
type: 'checkbox',
click: function (item) {
const openAtLogin = !app.getLoginItemSettings().openAtLogin
app.setLoginItemSettings({ openAtLogin })
item.checked = openAtLogin
},
checked: app.getLoginItemSettings().openAtLogin
},
{ type: 'separator' },
{
label: 'Quit Station',
click: () => app.quit(),
Expand All @@ -138,41 +92,19 @@ module.exports = async function (/** @type {Context} */ ctx) {
tray.setToolTip('Filecoin Station')
tray.setContextMenu(contextMenu)

setupIpcEventListeners(contextMenu, ctx)
setupIpcEventListeners(ctx)
}

/**
* @param {Electron.Menu} contextMenu
* @param {Context} ctx
*/
function setupIpcEventListeners (contextMenu, ctx) {
ipcMain.on(ipcMainEvents.UPDATE_CHECK_STARTED, () => {
getItemById('checkForUpdates').visible = false
getItemById('checkingForUpdates').visible = true
})

ipcMain.on(ipcMainEvents.UPDATE_CHECK_FINISHED, () => {
getItemById('checkForUpdates').visible = true
getItemById('checkingForUpdates').visible = false
})

function setupIpcEventListeners (ctx) {
ipcMain.on(ipcMainEvents.ACTIVITY_LOGGED, updateTray)
ipcMain.on(ipcMainEvents.READY_TO_UPDATE, updateTray)
ipcMain.on(ipcMainEvents.JOB_STATS_UPDATED, updateTray)
ipcMain.on(ipcMainEvents.BALANCE_UPDATE, updateTray)
ipcMain.on(ipcMainEvents.SCHEDULED_REWARDS_UPDATE, updateTray)

/**
* Get an item from the Tray menu or fail with a useful error message.
* @param {string} id
* @returns {Electron.MenuItem}
*/
function getItemById (id) {
const item = contextMenu.getMenuItemById(id)
if (!item) throw new Error(`Unknown tray menu item id: ${id}`)
return item
}

function updateTray () {
assert(tray)
tray.setImage(
Expand Down
8 changes: 5 additions & 3 deletions main/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,14 @@ export interface Context {
openReleaseNotes: () => void;
restartToUpdate: () => void;
getUpdaterStatus: () => {readyToUpdate: boolean};
browseTransactionTracker: (transactionHash: string) => void;
showTermsOfService: () => void;
openBeryx: () => void;
openExternalURL: (url: string) => void;

transactionUpdate: (transactions: (FILTransaction|FILTransactionProcessing)[]) => void;
balanceUpdate: (balance:string) => void;

toggleOpenAtLogin: () => void;
isOpenAtLogin: () => boolean;
exportSeedPhrase: () => void;
}

export interface WalletSeed {
Expand Down
29 changes: 28 additions & 1 deletion main/utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict'

const assert = require('node:assert')

/**
* @param {string | number | undefined} input
* @returns {number}
Expand All @@ -13,6 +15,31 @@ function formatTokenValue (input) {
return Number(number.toFixed(6))
}

const allowedURLs = [
'https://filspark.com/',
'https://github.com/filecoin-station/voyager',
'https://filstation.app/',
'https://github.com/filecoin-station/spark',
'https://beryx.io',
'https://pl-strflt.notion.site/Station-Terms-Conditions-e97da76bb89f49e280c2897aebe4c41f?pvs=4'
].map(str => new URL(str))

const allowedURLsRegEx = [
/https:\/\/docs.filstation.app\/.*$/,
/https:\/\/beryx.zondax.ch\/v1\/search\/fil\/mainnet\/address\/.*$/
].map(str => new RegExp(str))

/**
* @param {string} url
*/
function validateExternalURL (url) {
const normalizedURL = new URL(url).href
assert(
allowedURLs.find(item => normalizedURL === item.href) ||
allowedURLsRegEx.find(pattern => pattern.test(normalizedURL)))
}

module.exports = {
formatTokenValue
formatTokenValue,
validateExternalURL
}
Loading

0 comments on commit b25bcaa

Please sign in to comment.