Add currency conversion support to Math blocks

This commit is contained in:
Jonatan Heyman 2023-03-20 11:09:56 +01:00
parent ab4506939a
commit a4e9ce6893
8 changed files with 114 additions and 2 deletions

View File

@ -27,6 +27,14 @@ const schema = {
}, },
theme: {type: "string", default: "system"}, theme: {type: "string", default: "system"},
currency: {
type: "object",
properties: {
data: {type: "object"},
timeFetched: {type: "number"},
},
},
} }
const defaults = { const defaults = {

33
electron/main/cors.ts Normal file
View File

@ -0,0 +1,33 @@
import { BrowserWindow } from 'electron'
export function fixElectronCors(win: BrowserWindow) {
win.webContents.session.webRequest.onBeforeSendHeaders(
(details, callback) => {
callback({ requestHeaders: { Origin: '*', ...details.requestHeaders } });
},
);
win.webContents.session.webRequest.onHeadersReceived((details, callback) => {
// check if Access-Control-Allow-Origin header is set to ["*"], and if not, set it to that
let newHeaders = details.responseHeaders
let headerAlreadySet = false
for (const [key, value] of Object.entries(details.responseHeaders)) {
if (key.toLowerCase() === "access-control-allow-origin") {
if (value[0] === "*") {
headerAlreadySet = true
}
break
}
}
if (!headerAlreadySet) {
newHeaders = {
"access-control-allow-origin": ["*"],
...details.responseHeaders,
}
}
callback({
responseHeaders: newHeaders,
});
});
}

View File

@ -10,6 +10,7 @@ import CONFIG from "../config"
import { onBeforeInputEvent } from "../keymap" import { onBeforeInputEvent } from "../keymap"
import { isMac } from '../detect-platform'; import { isMac } from '../detect-platform';
import { initializeAutoUpdate } from './auto-update'; import { initializeAutoUpdate } from './auto-update';
import { fixElectronCors } from './cors';
// The built directory structure // The built directory structure
@ -137,6 +138,8 @@ async function createWindow() {
} }
return { action: 'deny' } return { action: 'deny' }
}) })
fixElectronCors(win)
} }
app.whenReady().then(createWindow).then(async () => { app.whenReady().then(createWindow).then(async () => {

View File

@ -0,0 +1,37 @@
import CONFIG from "../config"
const STALE_TIME = 1000 * 3600 * 24
export default async function getCurrencyData() {
const currency = CONFIG.get("currency")
if (currency?.timeFetched && (new Date()).getTime() - currency.timeFetched < STALE_TIME) {
// we already have currency data and it's not stale
return currency.data
} else {
// we either don't have currency data, or it's stale
let response
try {
response = await fetch("https://currencies.heynote.com/rates.json", {cache: "no-cache"})
} catch(err) {
// if we got an error, but have stale currency data, we'll use that
if (currency?.data) {
return currency.data
}
}
if (response.ok) {
const data = JSON.parse(await response.text())
CONFIG.set("currency", {
data,
timeFetched: (new Date()).getTime(),
})
return data
} else {
// if we got an error, but have stale currency data, we'll use that
console.log("Error retrieving currency data:", response)
if (currency?.data) {
return currency.data
}
}
}
}

View File

@ -16,9 +16,10 @@ import {
UPDATE_CHECK_FOR_UPDATES, UPDATE_CHECK_FOR_UPDATES,
} from "../constants" } from "../constants"
import CONFIG from "../config" import CONFIG from "../config"
import getCurrencyData from "./currency"
//contextBridge.exposeInMainWorld("platform", ) //contextBridge.exposeInMainWorld("platform", )
contextBridge.exposeInMainWorld('darkMode', darkMode) contextBridge.exposeInMainWorld("darkMode", darkMode)
contextBridge.exposeInMainWorld("heynote", { contextBridge.exposeInMainWorld("heynote", {
platform: { platform: {
@ -60,6 +61,10 @@ contextBridge.exposeInMainWorld("heynote", {
ipcRenderer.invoke("settings:set", settings) ipcRenderer.invoke("settings:set", settings)
}, },
async getCurrencyData() {
return await getCurrencyData()
},
onSettingsChange(callback) { onSettingsChange(callback) {
ipcRenderer.on(SETTINGS_CHANGE_EVENT, (event, settings) => callback(settings)) ipcRenderer.on(SETTINGS_CHANGE_EVENT, (event, settings) => callback(settings))
}, },

17
src/currency.js Normal file
View File

@ -0,0 +1,17 @@
let currenciesLoaded = false
export async function loadCurrencies() {
const data = await window.heynote.getCurrencyData()
if (!currenciesLoaded)
math.createUnit(data.base, {override:currenciesLoaded, aliases:[]})
Object.keys(data.rates)
.filter(function (currency) {
return currency !== data.base
})
.forEach(function (currency) {
math.createUnit(currency, {
definition: math.unit(1 / data.rates[currency], data.base),
aliases: [],
}, {override: currenciesLoaded})
})
currenciesLoaded = true
}

View File

@ -49,7 +49,7 @@ function mathDeco(view) {
// get math.js parser and cache it for this block // get math.js parser and cache it for this block
let parser = mathParsers.get(block) let parser = mathParsers.get(block)
if (!parser) { if (!parser) {
parser = math.parser() parser = window.math.parser()
mathParsers.set(block, parser) mathParsers.set(block, parser)
} }

View File

@ -2,6 +2,7 @@ import './css/application.sass'
import { createApp } from 'vue' import { createApp } from 'vue'
import App from './components/App.vue' import App from './components/App.vue'
import { loadCurrencies } from './currency'
const app = createApp(App) const app = createApp(App)
@ -10,3 +11,11 @@ app.mount('#app').$nextTick(() => {
// hide loading screen // hide loading screen
postMessage({ payload: 'removeLoading' }, '*') postMessage({ payload: 'removeLoading' }, '*')
}) })
// load math.js currencies
loadCurrencies()
setInterval(loadCurrencies, 1000 * 3600 * 4)