mirror of
https://github.com/obsidian-desci/Obsidian-Desci.git
synced 2026-07-22 08:50:32 +00:00
run cowsay from obsidian
This commit is contained in:
parent
1dd6e863f7
commit
f08f674596
11 changed files with 818 additions and 85 deletions
236
artifacts/ExampleClient.json
Normal file
236
artifacts/ExampleClient.json
Normal file
File diff suppressed because one or more lines are too long
0
components/hooks/useExampleClient.tsx
Normal file
0
components/hooks/useExampleClient.tsx
Normal file
|
|
@ -1,8 +1,10 @@
|
|||
import { useApp } from 'components/hooks/useApp';
|
||||
|
||||
|
||||
export const ReactView = () => {
|
||||
const { vault } = useApp();
|
||||
|
||||
console.log('hello react')
|
||||
return (<h4>vault name: {vault.getName()}</h4>);
|
||||
return (<h4>vault name: {vault.getName()}</h4>);
|
||||
|
||||
};
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import esbuild from "esbuild";
|
||||
import process from "process";
|
||||
import builtins from "builtin-modules";
|
||||
import { polyfillNode } from "esbuild-plugin-polyfill-node";
|
||||
|
||||
const banner =
|
||||
`/*
|
||||
|
|
@ -38,6 +39,9 @@ const context = await esbuild.context({
|
|||
sourcemap: prod ? false : "inline",
|
||||
treeShaking: true,
|
||||
outfile: "main.js",
|
||||
plugins: [
|
||||
polyfillNode({})
|
||||
]
|
||||
});
|
||||
|
||||
if (prod) {
|
||||
|
|
|
|||
258
main.tsx
258
main.tsx
|
|
@ -1,27 +1,56 @@
|
|||
import { App, Editor, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting, ItemView, WorkspaceLeaf } from 'obsidian';
|
||||
import { App, TFile, Editor, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting, ItemView, WorkspaceLeaf } from 'obsidian';
|
||||
import { AllCanvasNodeData } from 'obsidian/canvas'
|
||||
import { CanvasView, addEdge } from './utils/canvas-util'
|
||||
|
||||
import { Canvas, CanvasNode, CreateNodeOptions } from './utils/canvas-internal'
|
||||
import { ReactView } from './components/views/ReactView'
|
||||
import { createContext, StrictMode, useContext } from "react";
|
||||
import { createRoot, Root } from 'react-dom/client'
|
||||
import { AppContext } from 'components/context/context';
|
||||
const VIEW_TYPE_EXAMPLE = "example-view";
|
||||
|
||||
|
||||
import { ethers, Signer, Provider, JsonRpcProvider, Wallet } from 'ethers';
|
||||
import ExampleClient from './artifacts/ExampleClient.json'
|
||||
interface ChainConfig {
|
||||
name: string;
|
||||
rpcUrl: string;
|
||||
chainId: number;
|
||||
}
|
||||
|
||||
// Remember to rename these classes and interfaces!
|
||||
|
||||
interface ObsidianLilypadSettings {
|
||||
mySetting: string;
|
||||
privateKey: string;
|
||||
chain: ChainConfig
|
||||
}
|
||||
|
||||
const DEFAULT_SETTINGS: ObsidianLilypadSettings = {
|
||||
mySetting: 'default'
|
||||
privateKey: '',
|
||||
chain: {
|
||||
name: 'lilypad',
|
||||
rpcUrl: 'http://testnet.lilypadnetwork.org:8545',
|
||||
chainId: 1337
|
||||
}
|
||||
}
|
||||
|
||||
export default class ObsidianLilypad extends Plugin {
|
||||
settings: ObsidianLilypadSettings;
|
||||
unloaded = false
|
||||
provider: Provider
|
||||
wallet: Wallet
|
||||
signer: Signer
|
||||
exampleClient: ethers.Contract
|
||||
logDebug: (...args: unknown[]) => void = () => { }
|
||||
|
||||
async onload() {
|
||||
await this.loadSettings();
|
||||
this.provider = new JsonRpcProvider(this.settings.chain.rpcUrl)
|
||||
if (this.settings.privateKey) {
|
||||
this.wallet = new Wallet(this.settings.privateKey, this.provider)
|
||||
this.signer = this.wallet.connect(this.provider)
|
||||
this.exampleClient = new ethers.Contract(ExampleClient.address, ExampleClient.abi, this.signer)
|
||||
} else {
|
||||
console.log('no private key detected, web3 not enabled')
|
||||
}
|
||||
|
||||
// This creates an icon in the left ribbon.
|
||||
const ribbonIconEl = this.addRibbonIcon('dice', 'Obsidian Lilypad', (evt: MouseEvent) => {
|
||||
|
|
@ -37,21 +66,13 @@ export default class ObsidianLilypad extends Plugin {
|
|||
|
||||
// This adds a simple command that can be triggered anywhere
|
||||
this.addCommand({
|
||||
id: 'open-sample-modal-simple',
|
||||
name: 'Open sample modal (simple)',
|
||||
id: 'runCowsay',
|
||||
name: 'execute the cowsay program through a smart contract',
|
||||
callback: () => {
|
||||
new SampleModal(this.app).open();
|
||||
}
|
||||
});
|
||||
// This adds an editor command that can perform some operation on the current editor instance
|
||||
this.addCommand({
|
||||
id: 'sample-editor-command',
|
||||
name: 'Sample editor command',
|
||||
editorCallback: (editor: Editor, view: MarkdownView) => {
|
||||
console.log(editor.getSelection());
|
||||
editor.replaceSelection('Sample Editor Command');
|
||||
this.runCowsay()
|
||||
}
|
||||
});
|
||||
|
||||
// This adds a complex command that can check whether the current state of the app allows execution of the command
|
||||
this.addCommand({
|
||||
id: 'open-sample-modal-complex',
|
||||
|
|
@ -88,6 +109,74 @@ export default class ObsidianLilypad extends Plugin {
|
|||
onunload() {
|
||||
|
||||
}
|
||||
async runCowsay() {
|
||||
if (this.unloaded) return
|
||||
|
||||
this.logDebug("Running Cowsay")
|
||||
|
||||
const canvas = this.getActiveCanvas()
|
||||
if (!canvas) {
|
||||
this.logDebug('No active canvas')
|
||||
return
|
||||
}
|
||||
const selection = canvas.selection
|
||||
if (selection?.size !== 1) return
|
||||
const values = Array.from(selection.values())
|
||||
const node = values[0]
|
||||
if (node) {
|
||||
await canvas.requestSave()
|
||||
await sleep(200)
|
||||
|
||||
const settings = this.settings
|
||||
|
||||
const nodeData = node.getData()
|
||||
let nodeText = await getNodeText(node) || ''
|
||||
if (nodeText.length == 0) {
|
||||
this.logDebug('no node Text found')
|
||||
return
|
||||
}
|
||||
|
||||
const created = createNode(canvas, node,
|
||||
{
|
||||
text: `Calling Lilpad Cowsay with ${nodeText}`,
|
||||
size: { height: placeholderNoteHeight }
|
||||
},
|
||||
{
|
||||
color: assistantColor,
|
||||
chat_role: 'assistant'
|
||||
}
|
||||
)
|
||||
|
||||
try {
|
||||
|
||||
const tx = await this.exampleClient.runCowsay(
|
||||
nodeText, {
|
||||
value: ethers.parseUnits('2', 'ether')
|
||||
}
|
||||
)
|
||||
|
||||
console.log('tx', tx)
|
||||
created.setText(`success! tx hash: ${tx.hash}, fetching ipfs.io cid`)
|
||||
|
||||
const res = await this.exampleClient.fetchAllResults()
|
||||
console.log(res)
|
||||
created.setText(`${res}`)
|
||||
|
||||
|
||||
} catch (e) {
|
||||
created.setText(`error :( ${e}`)
|
||||
this.logDebug(`e: ${e}`)
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
getActiveCanvas() {
|
||||
const maybeCanvasView = this.app.workspace.getActiveViewOfType(ItemView) as CanvasView | null
|
||||
return maybeCanvasView ? maybeCanvasView['canvas'] : null
|
||||
}
|
||||
|
||||
|
||||
async loadSettings() {
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
||||
|
|
@ -98,6 +187,28 @@ export default class ObsidianLilypad extends Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
async function getNodeText(node: CanvasNode) {
|
||||
const nodeData = node.getData()
|
||||
switch (nodeData.type) {
|
||||
case 'text':
|
||||
return nodeData.text
|
||||
case 'file':
|
||||
return readFile(nodeData.file)
|
||||
}
|
||||
}
|
||||
|
||||
async function readFile(path: string) {
|
||||
const file = this.app.vault.getAbstractFileByPath(path)
|
||||
if (file instanceof TFile) {
|
||||
const body = await app.vault.read(file)
|
||||
return `## ${file.basename}\n${body}`
|
||||
}
|
||||
}
|
||||
const calcHeight = (options: { parentHeight: number, text: string }) => {
|
||||
const calcTextHeight = Math.round(textPaddingHeight + pxPerLine * options.text.length / (minWidth / pxPerChar))
|
||||
return Math.max(options.parentHeight, calcTextHeight)
|
||||
}
|
||||
|
||||
class SampleModal extends Modal {
|
||||
constructor(app: App) {
|
||||
super(app);
|
||||
|
|
@ -132,9 +243,9 @@ class ObsidianLilypadSettingTab extends PluginSettingTab {
|
|||
.setDesc('It\'s a secret')
|
||||
.addText(text => text
|
||||
.setPlaceholder('Enter your Ethereum Private Key')
|
||||
.setValue(this.plugin.settings.mySetting)
|
||||
.setValue(this.plugin.settings.privateKey)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.mySetting = value;
|
||||
this.plugin.settings.privateKey = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
}
|
||||
|
|
@ -170,4 +281,113 @@ class ExampleView extends ItemView {
|
|||
async onClose() {
|
||||
this.root?.unmount();
|
||||
}
|
||||
}
|
||||
const minWidth = 360
|
||||
|
||||
/**
|
||||
* Assumed pixel width per character
|
||||
*/
|
||||
const pxPerChar = 5
|
||||
|
||||
/**
|
||||
* Assumed pixel height per line
|
||||
*/
|
||||
const pxPerLine = 28
|
||||
|
||||
/**
|
||||
* Assumed height of top + bottom text area padding
|
||||
*/
|
||||
const textPaddingHeight = 12
|
||||
|
||||
/**
|
||||
* Color for assistant notes: 6 == purple
|
||||
*/
|
||||
const assistantColor = "6"
|
||||
|
||||
/**
|
||||
* Margin between new notes
|
||||
*/
|
||||
const newNoteMargin = 60
|
||||
|
||||
/**
|
||||
* Min height of new notes
|
||||
*/
|
||||
const minHeight = 60
|
||||
|
||||
/**
|
||||
* Height to use for new empty note
|
||||
*/
|
||||
const emptyNoteHeight = 100
|
||||
|
||||
/**
|
||||
* Height to use for placeholder note
|
||||
*/
|
||||
const placeholderNoteHeight = 60
|
||||
|
||||
const randomHexString = (len: number) => {
|
||||
const t = []
|
||||
for (let n = 0; n < len; n++) {
|
||||
t.push((16 * Math.random() | 0).toString(16))
|
||||
}
|
||||
return t.join("")
|
||||
}
|
||||
const createNode = (
|
||||
canvas: Canvas,
|
||||
parentNode: CanvasNode,
|
||||
nodeOptions: CreateNodeOptions,
|
||||
nodeData?: Partial<AllCanvasNodeData>
|
||||
) => {
|
||||
if (!canvas) {
|
||||
throw new Error('Invalid arguments')
|
||||
}
|
||||
|
||||
const { text } = nodeOptions
|
||||
const width = nodeOptions?.size?.width || Math.max(minWidth, parentNode?.width)
|
||||
const height = nodeOptions?.size?.height
|
||||
|| Math.max(minHeight, (parentNode && calcHeight({ text, parentHeight: parentNode.height })))
|
||||
|
||||
const siblings = parent && canvas.getEdgesForNode(parentNode)
|
||||
.filter(n => n.from.node.id == parentNode.id)
|
||||
.map(e => e.to.node)
|
||||
const siblingsRight = siblings && siblings.reduce((right, sib) => Math.max(right, sib.x + sib.width), 0)
|
||||
const priorSibling = siblings[siblings.length - 1]
|
||||
|
||||
// Position left at right of prior sibling, otherwise aligned with parent
|
||||
const x = siblingsRight ? siblingsRight + newNoteMargin : parentNode.x
|
||||
|
||||
// Position top at prior sibling top, otherwise offset below parent
|
||||
const y = (priorSibling
|
||||
? priorSibling.y
|
||||
: (parentNode.y + parentNode.height + newNoteMargin))
|
||||
// Using position=left, y value is treated as vertical center
|
||||
+ height * 0.5
|
||||
|
||||
const newNode = canvas.createTextNode(
|
||||
{
|
||||
pos: { x, y },
|
||||
position: 'left',
|
||||
size: { height, width },
|
||||
text,
|
||||
focus: false
|
||||
}
|
||||
)
|
||||
|
||||
if (nodeData) {
|
||||
newNode.setData(nodeData)
|
||||
}
|
||||
|
||||
canvas.deselectAll()
|
||||
canvas.addNode(newNode)
|
||||
|
||||
addEdge(canvas, randomHexString(16), {
|
||||
fromOrTo: "from",
|
||||
side: "bottom",
|
||||
node: parentNode,
|
||||
}, {
|
||||
fromOrTo: "to",
|
||||
side: "top",
|
||||
node: newNode,
|
||||
})
|
||||
|
||||
return newNode
|
||||
}
|
||||
260
package-lock.json
generated
260
package-lock.json
generated
|
|
@ -9,6 +9,9 @@
|
|||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"esbuild-plugin-polyfill-node": "^0.3.0",
|
||||
"ethers": "^6.7.1",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
|
|
@ -36,6 +39,11 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@adraffy/ens-normalize": {
|
||||
"version": "1.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.9.2.tgz",
|
||||
"integrity": "sha512-0h+FrQDqe2Wn+IIGFkTCd4aAwTJ+7834Ek1COohCyV26AXhwQ7WQaz+4F/nLOeVl/3BtWHOHLPsq46V8YB46Eg=="
|
||||
},
|
||||
"node_modules/@chainsafe/as-sha256": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz",
|
||||
|
|
@ -88,7 +96,6 @@
|
|||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
|
|
@ -104,7 +111,6 @@
|
|||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
|
|
@ -120,7 +126,6 @@
|
|||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
|
|
@ -136,7 +141,6 @@
|
|||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
|
|
@ -152,7 +156,6 @@
|
|||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
|
|
@ -168,7 +171,6 @@
|
|||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
|
|
@ -184,7 +186,6 @@
|
|||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
|
|
@ -200,7 +201,6 @@
|
|||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
|
|
@ -216,7 +216,6 @@
|
|||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
|
|
@ -232,7 +231,6 @@
|
|||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
|
|
@ -248,7 +246,6 @@
|
|||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
|
|
@ -264,7 +261,6 @@
|
|||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
|
|
@ -280,7 +276,6 @@
|
|||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
|
|
@ -296,7 +291,6 @@
|
|||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
|
|
@ -312,7 +306,6 @@
|
|||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
|
|
@ -328,7 +321,6 @@
|
|||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
|
|
@ -344,7 +336,6 @@
|
|||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
|
|
@ -360,7 +351,6 @@
|
|||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
|
|
@ -376,7 +366,6 @@
|
|||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
|
|
@ -392,7 +381,6 @@
|
|||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
|
|
@ -408,7 +396,6 @@
|
|||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
|
|
@ -424,7 +411,6 @@
|
|||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
|
|
@ -805,6 +791,12 @@
|
|||
"scrypt-js": "3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@ethersproject/json-wallets/node_modules/aes-js": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz",
|
||||
"integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ethersproject/keccak256": {
|
||||
"version": "5.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz",
|
||||
|
|
@ -1251,6 +1243,11 @@
|
|||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@jspm/core": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@jspm/core/-/core-2.0.1.tgz",
|
||||
"integrity": "sha512-Lg3PnLp0QXpxwLIAuuJboLeRaIhrgJjeuh797QADg3xz8wGLugQOS5DpsE8A6i6Adgzf+bacllkKZG3J0tGfDw=="
|
||||
},
|
||||
"node_modules/@metamask/eth-sig-util": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz",
|
||||
|
|
@ -1283,7 +1280,6 @@
|
|||
"version": "1.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz",
|
||||
"integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
|
|
@ -1367,6 +1363,54 @@
|
|||
"setimmediate": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@nomicfoundation/ethereumjs-block/node_modules/ethers": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz",
|
||||
"integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
|
||||
},
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://www.buymeacoffee.com/ricmoo"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@ethersproject/abi": "5.7.0",
|
||||
"@ethersproject/abstract-provider": "5.7.0",
|
||||
"@ethersproject/abstract-signer": "5.7.0",
|
||||
"@ethersproject/address": "5.7.0",
|
||||
"@ethersproject/base64": "5.7.0",
|
||||
"@ethersproject/basex": "5.7.0",
|
||||
"@ethersproject/bignumber": "5.7.0",
|
||||
"@ethersproject/bytes": "5.7.0",
|
||||
"@ethersproject/constants": "5.7.0",
|
||||
"@ethersproject/contracts": "5.7.0",
|
||||
"@ethersproject/hash": "5.7.0",
|
||||
"@ethersproject/hdnode": "5.7.0",
|
||||
"@ethersproject/json-wallets": "5.7.0",
|
||||
"@ethersproject/keccak256": "5.7.0",
|
||||
"@ethersproject/logger": "5.7.0",
|
||||
"@ethersproject/networks": "5.7.1",
|
||||
"@ethersproject/pbkdf2": "5.7.0",
|
||||
"@ethersproject/properties": "5.7.0",
|
||||
"@ethersproject/providers": "5.7.2",
|
||||
"@ethersproject/random": "5.7.0",
|
||||
"@ethersproject/rlp": "5.7.0",
|
||||
"@ethersproject/sha2": "5.7.0",
|
||||
"@ethersproject/signing-key": "5.7.0",
|
||||
"@ethersproject/solidity": "5.7.0",
|
||||
"@ethersproject/strings": "5.7.0",
|
||||
"@ethersproject/transactions": "5.7.0",
|
||||
"@ethersproject/units": "5.7.0",
|
||||
"@ethersproject/wallet": "5.7.0",
|
||||
"@ethersproject/web": "5.7.1",
|
||||
"@ethersproject/wordlists": "5.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nomicfoundation/ethereumjs-blockchain": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.2.tgz",
|
||||
|
|
@ -1570,6 +1614,54 @@
|
|||
"setimmediate": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@nomicfoundation/ethereumjs-statemanager/node_modules/ethers": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz",
|
||||
"integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
|
||||
},
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://www.buymeacoffee.com/ricmoo"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@ethersproject/abi": "5.7.0",
|
||||
"@ethersproject/abstract-provider": "5.7.0",
|
||||
"@ethersproject/abstract-signer": "5.7.0",
|
||||
"@ethersproject/address": "5.7.0",
|
||||
"@ethersproject/base64": "5.7.0",
|
||||
"@ethersproject/basex": "5.7.0",
|
||||
"@ethersproject/bignumber": "5.7.0",
|
||||
"@ethersproject/bytes": "5.7.0",
|
||||
"@ethersproject/constants": "5.7.0",
|
||||
"@ethersproject/contracts": "5.7.0",
|
||||
"@ethersproject/hash": "5.7.0",
|
||||
"@ethersproject/hdnode": "5.7.0",
|
||||
"@ethersproject/json-wallets": "5.7.0",
|
||||
"@ethersproject/keccak256": "5.7.0",
|
||||
"@ethersproject/logger": "5.7.0",
|
||||
"@ethersproject/networks": "5.7.1",
|
||||
"@ethersproject/pbkdf2": "5.7.0",
|
||||
"@ethersproject/properties": "5.7.0",
|
||||
"@ethersproject/providers": "5.7.2",
|
||||
"@ethersproject/random": "5.7.0",
|
||||
"@ethersproject/rlp": "5.7.0",
|
||||
"@ethersproject/sha2": "5.7.0",
|
||||
"@ethersproject/signing-key": "5.7.0",
|
||||
"@ethersproject/solidity": "5.7.0",
|
||||
"@ethersproject/strings": "5.7.0",
|
||||
"@ethersproject/transactions": "5.7.0",
|
||||
"@ethersproject/units": "5.7.0",
|
||||
"@ethersproject/wallet": "5.7.0",
|
||||
"@ethersproject/web": "5.7.1",
|
||||
"@ethersproject/wordlists": "5.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nomicfoundation/ethereumjs-trie": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.2.tgz",
|
||||
|
|
@ -2459,10 +2551,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/aes-js": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz",
|
||||
"integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==",
|
||||
"dev": true
|
||||
"version": "4.0.0-beta.5",
|
||||
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz",
|
||||
"integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q=="
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
|
|
@ -3199,7 +3290,6 @@
|
|||
"version": "0.17.3",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.3.tgz",
|
||||
"integrity": "sha512-9n3AsBRe6sIyOc6kmoXg2ypCLgf3eZSraWFRpnkto+svt8cZNuKTkb1bhQcitBcvIqjNiK7K0J3KPmwGSfkA8g==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
|
|
@ -3232,6 +3322,18 @@
|
|||
"@esbuild/win32-x64": "0.17.3"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-plugin-polyfill-node": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-plugin-polyfill-node/-/esbuild-plugin-polyfill-node-0.3.0.tgz",
|
||||
"integrity": "sha512-SHG6CKUfWfYyYXGpW143NEZtcVVn8S/WHcEOxk62LuDXnY4Zpmc+WmxJKN6GMTgTClXJXhEM5KQlxKY6YjbucQ==",
|
||||
"dependencies": {
|
||||
"@jspm/core": "^2.0.1",
|
||||
"import-meta-resolve": "^3.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"esbuild": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
||||
|
|
@ -3550,14 +3652,13 @@
|
|||
}
|
||||
},
|
||||
"node_modules/ethers": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz",
|
||||
"integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==",
|
||||
"dev": true,
|
||||
"version": "6.7.1",
|
||||
"resolved": "https://registry.npmjs.org/ethers/-/ethers-6.7.1.tgz",
|
||||
"integrity": "sha512-qX5kxIFMfg1i+epfgb0xF4WM7IqapIIu50pOJ17aebkxxa4BacW5jFrQRmCJpDEg2ZK2oNtR5QjrQ1WDBF29dA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
|
||||
"url": "https://github.com/sponsors/ethers-io/"
|
||||
},
|
||||
{
|
||||
"type": "individual",
|
||||
|
|
@ -3565,36 +3666,52 @@
|
|||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@ethersproject/abi": "5.7.0",
|
||||
"@ethersproject/abstract-provider": "5.7.0",
|
||||
"@ethersproject/abstract-signer": "5.7.0",
|
||||
"@ethersproject/address": "5.7.0",
|
||||
"@ethersproject/base64": "5.7.0",
|
||||
"@ethersproject/basex": "5.7.0",
|
||||
"@ethersproject/bignumber": "5.7.0",
|
||||
"@ethersproject/bytes": "5.7.0",
|
||||
"@ethersproject/constants": "5.7.0",
|
||||
"@ethersproject/contracts": "5.7.0",
|
||||
"@ethersproject/hash": "5.7.0",
|
||||
"@ethersproject/hdnode": "5.7.0",
|
||||
"@ethersproject/json-wallets": "5.7.0",
|
||||
"@ethersproject/keccak256": "5.7.0",
|
||||
"@ethersproject/logger": "5.7.0",
|
||||
"@ethersproject/networks": "5.7.1",
|
||||
"@ethersproject/pbkdf2": "5.7.0",
|
||||
"@ethersproject/properties": "5.7.0",
|
||||
"@ethersproject/providers": "5.7.2",
|
||||
"@ethersproject/random": "5.7.0",
|
||||
"@ethersproject/rlp": "5.7.0",
|
||||
"@ethersproject/sha2": "5.7.0",
|
||||
"@ethersproject/signing-key": "5.7.0",
|
||||
"@ethersproject/solidity": "5.7.0",
|
||||
"@ethersproject/strings": "5.7.0",
|
||||
"@ethersproject/transactions": "5.7.0",
|
||||
"@ethersproject/units": "5.7.0",
|
||||
"@ethersproject/wallet": "5.7.0",
|
||||
"@ethersproject/web": "5.7.1",
|
||||
"@ethersproject/wordlists": "5.7.0"
|
||||
"@adraffy/ens-normalize": "1.9.2",
|
||||
"@noble/hashes": "1.1.2",
|
||||
"@noble/secp256k1": "1.7.1",
|
||||
"@types/node": "18.15.13",
|
||||
"aes-js": "4.0.0-beta.5",
|
||||
"tslib": "2.4.0",
|
||||
"ws": "8.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ethers/node_modules/@noble/hashes": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.2.tgz",
|
||||
"integrity": "sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/ethers/node_modules/@types/node": {
|
||||
"version": "18.15.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz",
|
||||
"integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q=="
|
||||
},
|
||||
"node_modules/ethers/node_modules/ws": {
|
||||
"version": "8.5.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
|
||||
"integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/ethjs-util": {
|
||||
|
|
@ -3611,6 +3728,11 @@
|
|||
"npm": ">=3"
|
||||
}
|
||||
},
|
||||
"node_modules/eventemitter3": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
|
||||
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="
|
||||
},
|
||||
"node_modules/evp_bytestokey": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
|
||||
|
|
@ -4303,6 +4425,15 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/import-meta-resolve": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-3.0.0.tgz",
|
||||
"integrity": "sha512-4IwhLhNNA8yy445rPjD/lWh++7hMDOml2eHtd58eG7h+qK3EryMuuRbsHGPikCoAgIkkDnckKfWSk2iDla/ejg==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/imurmurhash": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||
|
|
@ -5835,8 +5966,7 @@
|
|||
"node_modules/tslib": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
|
||||
},
|
||||
"node_modules/tsort": {
|
||||
"version": "0.0.1",
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@
|
|||
"typescript": "4.7.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"esbuild-plugin-polyfill-node": "^0.3.0",
|
||||
"ethers": "^6.7.1",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"baseUrl": ".",
|
||||
"inlineSourceMap": true,
|
||||
"inlineSources": true,
|
||||
|
|
|
|||
76
utils/canvas-internal.ts
Normal file
76
utils/canvas-internal.ts
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
import { App } from 'obsidian'
|
||||
import { AllCanvasNodeData, CanvasData } from 'obsidian/canvas'
|
||||
|
||||
export interface CanvasNode {
|
||||
id: string
|
||||
app: App
|
||||
canvas: Canvas
|
||||
child: Partial<CanvasNode>
|
||||
color: string
|
||||
containerEl: HTMLElement
|
||||
containerBlockerEl: HTMLElement
|
||||
contentEl: HTMLElement
|
||||
destroyted: boolean
|
||||
height: number
|
||||
initialized: boolean
|
||||
isContentMounted: boolean
|
||||
isEditing: boolean
|
||||
nodeEl: HTMLElement
|
||||
placeholderEl: HTMLElement
|
||||
renderedZIndex: number
|
||||
resizeDirty: boolean
|
||||
text: string
|
||||
unknownData: Record<string, string>
|
||||
width: number
|
||||
x: number
|
||||
y: number
|
||||
zIndex: number
|
||||
convertToFile(): Promise<void>
|
||||
focus(): void
|
||||
getData(): AllCanvasNodeData
|
||||
initialize(): void
|
||||
moveAndResize(options: MoveAndResizeOptions): void
|
||||
render(): void
|
||||
setData(data: Partial<AllCanvasNodeData>): void
|
||||
setText(text: string): Promise<void>
|
||||
showMenu(): void
|
||||
startEditing(): void
|
||||
}
|
||||
|
||||
export interface MoveAndResizeOptions {
|
||||
x?: number, y?: number, width?: number, height?: number
|
||||
}
|
||||
|
||||
export interface CanvasEdge {
|
||||
from: {
|
||||
node: CanvasNode
|
||||
}
|
||||
to: {
|
||||
node: CanvasNode
|
||||
}
|
||||
}
|
||||
|
||||
export interface Canvas {
|
||||
edges: CanvasEdge[]
|
||||
selection: Set<CanvasNode>
|
||||
nodes: CanvasNode[]
|
||||
wrapperEl: HTMLElement | null
|
||||
addNode(node: CanvasNode): void
|
||||
createTextNode(options: CreateNodeOptions): CanvasNode
|
||||
deselectAll(): void
|
||||
getData(): CanvasData
|
||||
getEdgesForNode(node: CanvasNode): CanvasEdge[]
|
||||
importData(data: { nodes: object[], edges: object[] }): void
|
||||
removeNode(node: CanvasNode): void
|
||||
requestFrame(): Promise<void>
|
||||
requestSave(): Promise<void>
|
||||
selectOnly(node: CanvasNode, startEditing: boolean): void
|
||||
}
|
||||
|
||||
export interface CreateNodeOptions {
|
||||
text: string,
|
||||
pos?: { x: number, y: number }
|
||||
position?: 'left' | 'right' | 'top' | 'bottom',
|
||||
size?: { height?: number, width?: number },
|
||||
focus?: boolean
|
||||
}
|
||||
50
utils/canvas-util.ts
Normal file
50
utils/canvas-util.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
import { ItemView } from 'obsidian'
|
||||
import { Canvas } from './canvas-internal'
|
||||
|
||||
interface CanvasEdge {
|
||||
fromOrTo: string
|
||||
side: string,
|
||||
node: CanvasElement,
|
||||
}
|
||||
|
||||
interface CanvasElement {
|
||||
id: string
|
||||
}
|
||||
|
||||
export type CanvasView = ItemView & {
|
||||
canvas: Canvas
|
||||
}
|
||||
|
||||
/**
|
||||
* Add edge entry to canvas.
|
||||
*/
|
||||
export const addEdge = (canvas: Canvas, edgeID: string, fromEdge: CanvasEdge, toEdge: CanvasEdge) => {
|
||||
if (!canvas) return
|
||||
|
||||
const data = canvas.getData()
|
||||
|
||||
if (!data) return
|
||||
|
||||
canvas.importData({
|
||||
"edges": [
|
||||
...data.edges,
|
||||
{ "id": edgeID, "fromNode": fromEdge.node.id, "fromSide": fromEdge.side, "toNode": toEdge.node.id, "toSide": toEdge.side }
|
||||
],
|
||||
"nodes": data.nodes,
|
||||
})
|
||||
|
||||
canvas.requestFrame()
|
||||
}
|
||||
|
||||
/**
|
||||
* Trap exception and write to console.error.
|
||||
*/
|
||||
export function trapError<T>(fn: (...params: unknown[]) => T) {
|
||||
return (...params: unknown[]) => {
|
||||
try {
|
||||
return fn(...params)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
10
utils/utils.ts
Normal file
10
utils/utils.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* Generate a string of random hexadecimal chars
|
||||
*/
|
||||
export const randomHexString = (len: number) => {
|
||||
const t = []
|
||||
for (let n = 0; n < len; n++) {
|
||||
t.push((16 * Math.random() | 0).toString(16))
|
||||
}
|
||||
return t.join("")
|
||||
}
|
||||
Loading…
Reference in a new issue