Skip to content

Commit 1c67763

Browse files
authored
Merge pull request #63 from sapio-lang/ux-improvements
UX Bug Fixes
2 parents a0f267c + d59fa5c commit 1c67763

File tree

8 files changed

+153
-107
lines changed

8 files changed

+153
-107
lines changed

desktop/handlers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export default function (window: BrowserWindow) {
128128
}
129129
);
130130

131-
const name = JSON.parse(mod).which;
131+
const name = JSON.parse(mod).module;
132132

133133
return { ok: { data, name, args } };
134134
}

src/App.tsx

Lines changed: 98 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Collapse, Paper } from '@mui/material';
2-
import { createTheme, ThemeProvider } from '@mui/material/styles';
2+
import { createTheme, ThemeProvider, useTheme } from '@mui/material/styles';
33
import useMediaQuery from '@mui/material/useMediaQuery';
44
import {
55
BaseEntityEvent,
@@ -26,6 +26,7 @@ import { BitcoinStatusBar } from './Data/BitcoinStatusBar';
2626
import { ContractModel, Data } from './Data/ContractManager';
2727
import { ModelManager } from './Data/ModelManager';
2828
import { SimulationController } from './Data/Simulation';
29+
import { selectSimIsShowing, toggle_showing } from './Data/SimulationSlice';
2930
import { TransactionModel } from './Data/Transaction';
3031
import { UTXOModel } from './Data/UTXO';
3132
import './Glyphs.css';
@@ -150,13 +151,7 @@ function AppInner(props: {
150151
}) {
151152
const bitcoin_node_bar = useSelector(selectStatusBar);
152153
const { engine, model, load_new_contract } = props;
153-
const entity_id: EntityType = useSelector(selectEntityToView);
154-
155-
const show = useSelector(selectShouldViewEntity);
156-
const details = entity_id[0] !== 'NULL' && show;
157154

158-
const [timing_simulator_enabled, set_timing_simulator_enabled] =
159-
React.useState(false);
160155
// engine is the processor for graphs, we need to load all our custom factories here
161156

162157
const [contract_data, counter] = useSelector(selectContract);
@@ -173,26 +168,6 @@ function AppInner(props: {
173168

174169
const is_showing = useSelector(selectShowing);
175170

176-
React.useEffect(() => {
177-
if (entity_id[0] === 'TXN')
178-
jump_to_entity(
179-
model,
180-
engine,
181-
TXIDAndWTXIDMap.get_by_txid_s(
182-
current_contract.txid_map,
183-
entity_id[1]
184-
) ?? null
185-
);
186-
else if (entity_id[0] === 'UTXO')
187-
jump_to_entity(
188-
model,
189-
engine,
190-
TXIDAndWTXIDMap.get_by_txid_s(
191-
current_contract.txid_map,
192-
entity_id[1].hash
193-
)?.utxo_models[entity_id[1].nIn] ?? null
194-
);
195-
}, [entity_id]);
196171
const relayout = () => {
197172
dag.redistribute(props.model);
198173
engine.repaintCanvas();
@@ -237,58 +212,6 @@ function AppInner(props: {
237212
}),
238213
[prefersDarkMode]
239214
);
240-
let showing = null;
241-
switch (is_showing) {
242-
case 'Settings':
243-
showing = (
244-
<Paper className="settings-container" square={true}>
245-
<Settings></Settings>
246-
</Paper>
247-
);
248-
break;
249-
case 'Wallet':
250-
showing = (
251-
<Paper className="wallet-container" square={true}>
252-
<Wallet
253-
bitcoin_node_manager={bitcoin_node_manager}
254-
></Wallet>
255-
</Paper>
256-
);
257-
break;
258-
case 'ContractCreator':
259-
showing = <CreateContractModal />;
260-
break;
261-
case 'ContractViewer':
262-
showing = (
263-
<>
264-
<div className="main-container">
265-
<DemoCanvasWidget
266-
engine={engine}
267-
model={model}
268-
background={theme.palette.background.paper}
269-
color={theme.palette.divider}
270-
>
271-
<CanvasWidget engine={engine as any} key={'main'} />
272-
</DemoCanvasWidget>
273-
</div>
274-
<Collapse in={details}>
275-
<CurrentlyViewedEntity
276-
current_contract={current_contract}
277-
/>
278-
</Collapse>
279-
<div className="area-overlays">
280-
<Collapse in={timing_simulator_enabled}>
281-
<SimulationController
282-
contract={current_contract}
283-
engine={engine}
284-
hide={() => set_timing_simulator_enabled(false)}
285-
/>
286-
</Collapse>
287-
</div>
288-
</>
289-
);
290-
break;
291-
}
292215
return (
293216
<ThemeProvider theme={theme}>
294217
<div className="App">
@@ -298,14 +221,16 @@ function AppInner(props: {
298221
relayout={relayout}
299222
bitcoin_node_manager={bitcoin_node_manager}
300223
contract={current_contract}
301-
toggle_timing_simulator={() =>
302-
set_timing_simulator_enabled(
303-
!timing_simulator_enabled
304-
)
305-
}
306224
/>
307225
</div>
308-
<div className="area-inner">{showing}</div>
226+
<div className="area-inner">
227+
<Viewing
228+
bitcoin_node_manager={bitcoin_node_manager}
229+
model={model}
230+
engine={engine}
231+
current_contract={current_contract}
232+
/>
233+
</div>
309234
</div>
310235
<div hidden={!bitcoin_node_bar}>
311236
{bitcoin_node_bar && (
@@ -323,4 +248,92 @@ function AppInner(props: {
323248
);
324249
}
325250

251+
function Viewing(props: {
252+
model: DiagramModel;
253+
engine: DiagramEngine;
254+
current_contract: ContractModel;
255+
bitcoin_node_manager: BitcoinNodeManager;
256+
}) {
257+
const is_showing = useSelector(selectShowing);
258+
switch (is_showing) {
259+
case 'Settings':
260+
return (
261+
<Paper className="settings-container" square={true}>
262+
<Settings></Settings>
263+
</Paper>
264+
);
265+
case 'Wallet':
266+
return (
267+
<Paper className="wallet-container" square={true}>
268+
<Wallet
269+
bitcoin_node_manager={props.bitcoin_node_manager}
270+
></Wallet>
271+
</Paper>
272+
);
273+
case 'ContractCreator':
274+
return <CreateContractModal />;
275+
case 'ContractViewer':
276+
return <ContractViewer {...props} />;
277+
}
278+
}
279+
function ContractViewer(props: {
280+
model: DiagramModel;
281+
engine: DiagramEngine;
282+
current_contract: ContractModel;
283+
}) {
284+
const dispatch = useDispatch();
285+
const entity_id: EntityType = useSelector(selectEntityToView);
286+
const show = useSelector(selectShouldViewEntity);
287+
const theme = useTheme();
288+
const timing_simulator_enabled = useSelector(selectSimIsShowing);
289+
const details = entity_id[0] !== 'NULL' && show;
290+
const { model, engine, current_contract } = props;
291+
React.useEffect(() => {
292+
if (entity_id[0] === 'TXN')
293+
jump_to_entity(
294+
model,
295+
engine,
296+
TXIDAndWTXIDMap.get_by_txid_s(
297+
current_contract.txid_map,
298+
entity_id[1]
299+
) ?? null
300+
);
301+
else if (entity_id[0] === 'UTXO')
302+
jump_to_entity(
303+
model,
304+
engine,
305+
TXIDAndWTXIDMap.get_by_txid_s(
306+
current_contract.txid_map,
307+
entity_id[1].hash
308+
)?.utxo_models[entity_id[1].nIn] ?? null
309+
);
310+
}, [entity_id]);
311+
312+
return (
313+
<>
314+
<div className="main-container">
315+
<DemoCanvasWidget
316+
engine={engine}
317+
model={model}
318+
background={theme.palette.background.paper}
319+
color={theme.palette.divider}
320+
>
321+
<CanvasWidget engine={engine as any} key={'main'} />
322+
</DemoCanvasWidget>
323+
</div>
324+
<Collapse in={details}>
325+
<CurrentlyViewedEntity current_contract={current_contract} />
326+
</Collapse>
327+
<div className="area-overlays">
328+
<Collapse in={timing_simulator_enabled}>
329+
<SimulationController
330+
contract={current_contract}
331+
engine={engine}
332+
hide={() => dispatch(toggle_showing())}
333+
/>
334+
</Collapse>
335+
</div>
336+
</>
337+
);
338+
}
326339
export default App;

src/Data/ContractManager.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
} from '../util';
1414
import { PhantomTransactionModel, TransactionModel } from './Transaction';
1515
import { UTXOModel } from './UTXO';
16+
import Color from 'color';
1617
export type NodeColorT = ['NodeColor', string];
1718
export const NodeColor = {
1819
new(c: string): NodeColorT {
@@ -237,7 +238,11 @@ function process_txn_models(
237238
// TODO: a hack to make the flow technically correct and detectable
238239
mock_txn.addOutput(Buffer.from(''), 21e6 * 100e6);
239240
}
240-
const color = NodeColor.new('magenta');
241+
const c = Color(
242+
[Math.random() * 255, Math.random() * 255, Math.random() * 255],
243+
'rgb'
244+
).toString();
245+
const color = NodeColor.new(c);
241246
const utxo_metadata: Array<UTXOFormatData | null> = new Array(
242247
n_outputs
243248
);
@@ -263,6 +268,8 @@ function process_utxo_models(
263268
const to_add: Array<UTXOModel> = [];
264269
for (const m_txn of txn_models) {
265270
assert.equal(m_txn.utxo_models.length, m_txn.tx.outs.length);
271+
if (!(m_txn instanceof PhantomTransactionModel))
272+
to_add.push(...m_txn.utxo_models);
266273
_.zip(m_txn.utxo_models, m_txn.tx.outs).forEach(
267274
([opt_utxo_model, opt_out], output_index) => {
268275
// safe because of assert
@@ -274,10 +281,12 @@ function process_utxo_models(
274281
m_txn.get_txid(),
275282
output_index
276283
) ?? [];
284+
assert.equal(m_txn, utxo_model.txn);
277285
if (
278-
utxo_model?.txn instanceof PhantomTransactionModel &&
286+
m_txn instanceof PhantomTransactionModel &&
279287
spenders.length > 0
280288
) {
289+
to_add.push(utxo_model);
281290
if (spenders[0]?.witness_set.witnesses.length) {
282291
const witstack =
283292
spenders[0]?.witness_set.witnesses[0]?.[
@@ -337,7 +346,6 @@ function process_utxo_models(
337346
});
338347
}
339348
);
340-
to_add.push(...m_txn.utxo_models);
341349
}
342350
return to_add;
343351
}

src/Data/SimulationSlice.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import { RootState } from '../Store/store';
33
import { hasOwn, TXID } from '../util';
44
type SimulationState = {
55
unreachable_models: Record<TXID, null>;
6+
show: boolean;
67
};
78
function default_state(): SimulationState {
89
return {
910
unreachable_models: {},
11+
show: false,
1012
};
1113
}
1214

@@ -17,13 +19,19 @@ export const simulationSlice = createSlice({
1719
set_unreachable: (state, action: PayloadAction<Record<TXID, null>>) => {
1820
state.unreachable_models = action.payload;
1921
},
22+
toggle_showing: (state) => {
23+
state.show = !state.show;
24+
},
2025
},
2126
});
2227

23-
export const { set_unreachable } = simulationSlice.actions;
28+
export const { set_unreachable, toggle_showing } = simulationSlice.actions;
2429

2530
export const selectIsReachable: (state: RootState) => (t: TXID) => boolean =
2631
(state: RootState) => (t: TXID) =>
2732
!hasOwn(state.simulationReducer.unreachable_models, t);
33+
export const selectSimIsShowing: (state: RootState) => boolean = (
34+
state: RootState
35+
) => state.simulationReducer.show;
2836

2937
export const simulationReducer = simulationSlice.reducer;

src/UX/AppNavbar.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ import {
1919
} from '../AppSlice';
2020
import { BitcoinNodeManager } from '../Data/BitcoinNode';
2121
import { ContractModel } from '../Data/ContractManager';
22+
import { toggle_showing } from '../Data/SimulationSlice';
2223
import './AppNavbar.css';
2324
import { set_apis } from './ContractCreator/ContractCreatorSlice';
2425
import { open_modal } from './ModalSlice';
2526
export function AppNavbar(props: {
2627
relayout: () => void;
27-
toggle_timing_simulator: () => void;
2828
contract: ContractModel;
2929
bitcoin_node_manager: BitcoinNodeManager;
3030
}): JSX.Element {
@@ -39,9 +39,7 @@ export function AppNavbar(props: {
3939
<List>
4040
<ContractMenu relayout={props.relayout} />
4141
<NodeMenu bitcoin_node_manager={props.bitcoin_node_manager} />
42-
<Simulator
43-
toggle_timing_simulator={props.toggle_timing_simulator}
44-
/>
42+
<Simulator />
4543
</List>
4644
<Divider />
4745
<List>
@@ -68,7 +66,8 @@ function SettingsMenuItem() {
6866
</ListItem>
6967
);
7068
}
71-
function Simulator(props: { toggle_timing_simulator: () => void }) {
69+
function Simulator() {
70+
const dispatch = useDispatch();
7271
const simulateRef = React.useRef<HTMLLIElement>(null);
7372
const [sim_open, setSimOpen] = React.useState(false);
7473
return (
@@ -96,7 +95,7 @@ function Simulator(props: { toggle_timing_simulator: () => void }) {
9695
<MenuItem
9796
onClick={() => {
9897
setSimOpen(false);
99-
props.toggle_timing_simulator();
98+
dispatch(toggle_showing());
10099
}}
101100
>
102101
Timing

0 commit comments

Comments
 (0)