Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change style of bouquet to me more consistent with Lunaria and NFT Sender #51

Merged
merged 37 commits into from
Aug 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
f2b28e4
Footer and Navbar new style
0xjimmy Jul 16, 2023
f1eefee
Buttons and Settings modal style
0xjimmy Jul 17, 2023
b9cac3e
Error handling clean, inputs for import better, new style
0xjimmy Jul 17, 2023
eda98eb
Styling
0xjimmy Jul 18, 2023
c2b647a
Can check, but need to avoid checking gass diff and funding
0xjimmy Jul 18, 2023
d117973
Calculate correct funding amounts
0xjimmy Jul 23, 2023
df3c434
Transaction list shows diff warning and correct funding amount
0xjimmy Jul 24, 2023
c52450f
Get address utils
0xjimmy Jul 24, 2023
6008a8d
Apply suggestions from code review
0xjimmy Jul 25, 2023
a622099
Merge pull request #56 from DarkFlorist/transactions-and-import-diff
0xjimmy Jul 25, 2023
3984fa6
Merge pull request #52 from DarkFlorist/import-fixes
0xjimmy Jul 25, 2023
ec0fc09
Add Import btn to warning card
0xjimmy Aug 1, 2023
954c299
Split components into 2
0xjimmy Aug 1, 2023
1769c4d
Fix #50, new styling
0xjimmy Aug 1, 2023
c110425
Burner section css
0xjimmy Aug 1, 2023
2fb4256
Update app/ts/components/Warns.tsx
0xjimmy Aug 3, 2023
48c7c3e
Merge pull request #59 from DarkFlorist/feat/click-to-sync
0xjimmy Aug 3, 2023
ffba358
Can withdraw funds
0xjimmy Aug 8, 2023
a7d852f
Make some responsive changes
0xjimmy Aug 8, 2023
214d770
Update app/ts/components/ConfigureFunding.tsx
0xjimmy Aug 8, 2023
0ff95ec
Fix quote formatting
0xjimmy Aug 8, 2023
1315b1c
Merge branch 'style' into configure
0xjimmy Aug 8, 2023
6cdf094
Merge pull request #60 from DarkFlorist/configure
0xjimmy Aug 8, 2023
ce64307
Move to validate, then parse on save. Fix disabled button style
0xjimmy Aug 9, 2023
2a3a681
Block callback pass number
0xjimmy Aug 9, 2023
96ce1e4
Display simulation outcomes
0xjimmy Aug 9, 2023
acc65cb
Bundle inclusion detection
0xjimmy Aug 9, 2023
e8f04d7
Complete desgin of successful bundle
0xjimmy Aug 9, 2023
4bc5997
Fix bug where it wouldn't show or hide success when it should
0xjimmy Aug 9, 2023
ed35b0d
Apply suggestions from code review
0xjimmy Aug 13, 2023
ab3c230
Merge pull request #61 from DarkFlorist/fix-settings-signals
0xjimmy Aug 13, 2023
e7915de
Update app/ts/library/provider.ts
0xjimmy Aug 13, 2023
11f0516
Merge pull request #62 from DarkFlorist/simulate-submit-clearer-respo…
0xjimmy Aug 15, 2023
d12c037
Wrong unit label
0xjimmy Aug 15, 2023
b214ae6
Fix #63
0xjimmy Aug 15, 2023
5f0f298
Update app/ts/components/Settings.tsx
0xjimmy Aug 15, 2023
974d611
Merge branch 'main' into style
0xjimmy Aug 20, 2023
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
310 changes: 226 additions & 84 deletions app/css/index.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<link rel="stylesheet" href="./css/index.css" />
</head>

<body>
<body class="w-full bg-black flex justify-center">
<script type="importmap">
{
"imports": {
Expand Down
14 changes: 8 additions & 6 deletions app/ts/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { Import } from './Import.js'
import { Configure } from './Configure.js'
import { Submit } from './Submit.js'
import { Button } from './Button.js'
import { Transactions } from './Transactions.js'
import { connectBrowserProvider } from '../library/provider.js'
import { Navbar } from './Navbar.js'
import { createGlobalState } from '../stores.js'
import { Footer } from './Footer.js'
import { ConfigureKeys } from './ConfigureKeys.js'
import { ConfigureFunding } from './ConfigureFunding.js'

export function App() {
const state = createGlobalState()

return (
<main class='bg-background text-primary w-full min-h-screen sm:px-6 font-serif flex flex-col items-center'>
<article className='p-4 max-w-screen-lg w-full'>
<main class='bg-black text-primary w-screen max-w-screen overflow-hidden min-h-screen sm:p-4 p-6 gap-4 font-serif flex flex-col items-center max-w-screen-xl'>
<Navbar {...state} />
<div className='p-4 mt-4 flex flex-col gap-8'>
<div className='p-4 mt-4 flex flex-col gap-8 w-full'>
{!state.provider.value && state.bundle.value ? (
<article className='items-center flex flex-col gap-4 py-8'>
<h2 class='text-2xl font-bold'>Welcome Back</h2>
Expand All @@ -28,12 +29,13 @@ export function App() {
<>
<Import {...state} />
{state.bundle.value ? <Transactions {...state} /> : null}
<Configure {...state} />
<h2 className='font-bold text-2xl'><span class='text-gray-500'>2.</span> Configure</h2>
{state.bundle.value ? (<><ConfigureKeys {...state} /><ConfigureFunding {...state} /></>) : <p>No transactions imported yet.</p>}
<Submit {...state} />
</>
)}
</div>
</article>
<Footer />
</main>
)
}
197 changes: 197 additions & 0 deletions app/ts/components/Blockie.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import { JSX } from 'preact/jsx-runtime'
import { ReadonlySignal, Signal, useSignalEffect } from '@preact/signals'
import { useAsyncState } from '../library/asyncState.js'
import { DataURLCache } from '../library/DataURLCache.js'

const dataURLCache = new DataURLCache()

class Future<T> implements PromiseLike<T> {
private promise: Promise<T>
private resolveFunction: (value: T | PromiseLike<T>) => void
private rejectFunction: (reason: Error) => void

constructor() {
let resolveFunction: (value: T | PromiseLike<T>) => void
let rejectFunction: (reason: Error) => void
this.promise = new Promise((resolve: (value: T | PromiseLike<T>) => void, reject: (reason: Error) => void) => {
resolveFunction = resolve
rejectFunction = reject
})
// the function passed to the Promise constructor is called before the constructor returns, so we can be sure the resolve and reject functions have been set by here even if the compiler can't verify
this.resolveFunction = resolveFunction!
this.rejectFunction = rejectFunction!
}

public get asPromise() { return this.promise }

public readonly then = <TResult1 = T, TResult2 = never>(
onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,
onrejected?: ((reason: Error) => TResult2 | PromiseLike<TResult2>) | undefined | null
): PromiseLike<TResult1 | TResult2> => {
return this.promise.then(onfulfilled, onrejected)
}

public readonly resolve = (value: T | PromiseLike<T>) => {
this.resolveFunction!(value)
}

public readonly reject = (reason: Error) => {
this.rejectFunction!(reason)
}
}

function addressString(address: bigint) {
return `0x${address.toString(16).padStart(40, '0')}`
}

interface BlockieProps {
address: Signal<bigint> | ReadonlySignal<bigint>,
scale?: Signal<number>,
style?: JSX.CSSProperties
}

function generateIdenticon(address: bigint, scale: number, canvasRef: HTMLCanvasElement) {
// NOTE -- Majority of this code is referenced from: https://github.com/alexvandesande/blockies
// Mostly to ensure congruence to Ethereum Mist's Identicons

// The random number is a js implementation of the Xorshift PRNG
const randseed = new Array(4) // Xorshift: [x, y, z, w] 32 bit values

function seedrand(seed: string) {
for (let i = 0; i < randseed.length; i++) {
randseed[i] = 0
}
for (let i = 0; i < seed.length; i++) {
randseed[i % 4] = ((randseed[i % 4] << 5) - randseed[i % 4]) + seed.charCodeAt(i)
}
}

function rand() {
// based on Java's String.hashCode(), expanded to 4 32bit values
const t = randseed[0] ^ (randseed[0] << 11)

randseed[0] = randseed[1]
randseed[1] = randseed[2]
randseed[2] = randseed[3]
randseed[3] = (randseed[3] ^ (randseed[3] >> 19) ^ t ^ (t >> 8))

return (randseed[3] >>> 0) / ((1 << 31) >>> 0)
}

function createColor() {
// saturation is the whole color spectrum
const h = Math.floor(rand() * 360)
// saturation goes from 40 to 100, it avoids greyish colors
const s = ((rand() * 60) + 40) + '%'
// lightness can be anything from 0 to 100, but probabilities are a bell curve around 50%
const l = ((rand() + rand() + rand() + rand()) * 25) + '%'

const color = 'hsl(' + h + ',' + s + ',' + l + ')'
return color
}

function createImageData(size: number) {
const width = size // Only support square icons for now
const height = size

const dataWidth = Math.ceil(width / 2)
const mirrorWidth = width - dataWidth

const data = []
for (let y = 0; y < height; y++) {
let row = []
for (let x = 0; x < dataWidth; x++) {
// this makes foreground and background color to have a 43% (1/2.3) probability
// spot color has 13% chance
row[x] = Math.floor(rand() * 2.3)
}
const r = row.slice(0, mirrorWidth)
r.reverse()
row = row.concat(r)

for (let i = 0; i < row.length; i++) {
data.push(row[i])
}
}

return data
}

function setCanvas(identicon: HTMLCanvasElement, imageData: number[], color: string, scale: number, bgcolor: string, spotcolor: string) {
const width = Math.sqrt(imageData.length)
const size = width * scale

identicon.width = size
identicon.style.width = `${size}px`

identicon.height = size
identicon.style.height = `${size}px`

const cc = identicon.getContext('2d')
cc!.fillStyle = bgcolor
cc!.fillRect(0, 0, identicon.width, identicon.height)
cc!.fillStyle = color

for (let i = 0; i < imageData.length; i++) {
// if data is 2, choose spot color, if 1 choose foreground
cc!.fillStyle = (imageData[i] === 1) ? color : spotcolor

// if data is 0, leave the background
if (imageData[i]) {
const row = Math.floor(i / width)
const col = i % width

cc!.fillRect(col * scale, row * scale, scale, scale)
}
}
}

const seed = addressString(address)

seedrand(seed)

const color = createColor()
const bgcolor = createColor()
const spotcolor = createColor()
const imageData = createImageData(8)
const canvas = setCanvas(canvasRef, imageData, color, scale, bgcolor, spotcolor)

return canvas
}

async function renderBlockieToUrl(address: Signal<bigint>, scale: Signal<number> | undefined) {
const key = `${address.value}!${scale?.value || 4}`
const cacheResult = dataURLCache.get(key)
if (cacheResult !== undefined) return cacheResult
const future = new Future<string>()
const element = document.createElement('canvas')
generateIdenticon(address.value, scale?.value || 4, element)
element.toBlob((blob) => {
if (!blob) return
const dataUrl = URL.createObjectURL(blob)
dataURLCache.set(dataUrl, key)
future.resolve(dataUrl)
})
return await future
}

export function Blockie(props: BlockieProps) {
const dimension = 8 * (props.scale?.value || 4)
const { value: dataURL, waitFor } = useAsyncState<string>()
useSignalEffect(() => {
props.address.value
waitFor(async () => renderBlockieToUrl(props.address, props.scale))
})
return <img
src={dataURL.value.state !== 'resolved' ? 'data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=' : dataURL.value.value}
style={
{
...props.style,
width: `${dimension}px`,
height: `${dimension}px`,
minWidth: `${dimension}px`,
minHeight: `${dimension}px`,
}
}
/>
}
13 changes: 7 additions & 6 deletions app/ts/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { JSX } from "preact/jsx-runtime"
import { ComponentChildren } from 'preact'

const classNames = {
primary: 'flex items-center justify-center gap-1 font-semibold rounded-xl px-6 py-2 w-max bg-accent text-background hover:bg-accent/80 disabled:bg-slate-600 disabled:cursor-not-allowed',
secondary: 'flex items-center justify-center gap-1 font-semibold rounded-xl px-6 py-2 w-max bg-white text-background hover:bg-white/80 disabled:bg-slate-600 disabled:cursor-not-allowed',
primary: 'h-12 px-4 border border-white/50 bg-gray-500/50 outline-none focus:border-white/90 focus:bg-gray-500/20 flex items-center gap-2 justify-center disabled:opacity-50',
secondary: 'h-12 px-4 border border-white/50 bg-black outline-none focus:border-white/90 focus:bg-gray-500/20 text-white flex items-center gap-2 justify-center disabled:opacity-50',
full: 'px-4 h-16 border border-white/50 text-lg bg-white/10 flex items-center gap-2 justify-center outline-none focus:border-white/90 focus:bg-gray-500 disabled:opacity-50'
}

export const Button = ({
Expand All @@ -11,13 +12,13 @@ export const Button = ({
variant,
onClick,
}: {
children: string | JSX.Element
children: ComponentChildren,
disabled?: boolean
variant?: 'primary' | 'secondary'
variant?: 'primary' | 'secondary' | 'full'
onClick: () => unknown
}) => {
return (
<button onClick={onClick} disabled={disabled ?? false} className={classNames[variant ?? 'primary']}>
<button onClick={onClick} disabled={disabled ?? false} className={classNames[variant ?? 'primary']} >
{children}
</button>
)
Expand Down
Loading