diff --git a/pkg/arvo/lib/hood/kiln.hoon b/pkg/arvo/lib/hood/kiln.hoon index ab932fb27..7c01f660d 100644 --- a/pkg/arvo/lib/hood/kiln.hoon +++ b/pkg/arvo/lib/hood/kiln.hoon @@ -680,11 +680,11 @@ |= [kel=weft except=(set desk) force=?] ^+ kiln =/ ded (find-blocked kel except) - ?: force - =. kiln (suspend-many ded) - (bump-many kel (all-desks-but (~(uni in except) ded))) - ?: =(~ ded) - (bump-many kel (all-desks-but except)) + =? kiln force (suspend-many ded) + ?: |(force =(~ ded)) + ?: !=(zuse+zuse kel) + (bump-one kel %base) + (bump-many (all-desks-but (~(uni in except) ded))) =- (^emit (pyre:pass leaf/- ~)) "kiln: desks blocked upgrade to {}: {}" :: @@ -704,7 +704,7 @@ $(ded t.ded, kiln abet:(suspend i.ded)) :: ++ bump-many - |= [kel=weft live=(set desk)] + |= live=(set desk) ^+ kiln :: ensure %base is always reloaded first :: @@ -718,7 +718,7 @@ :: |- ^+ kiln ?~ liv kiln - $(liv t.liv, kiln (bump-one kel i.liv)) + $(liv t.liv, kiln (bump-one zuse+zuse i.liv)) :: ++ bump-one |= [kel=weft =desk] @@ -733,7 +733,7 @@ ?: =(kel u.kul) ~> %slog.(fmt "{here} already at {<[lal num]:kel>}") update-running-dudes - =^ tem rail.rak (crank-next %| kel) + =^ tem rail.rak (crank-next kel) ?^ tem (emit merge-main:pass) =- (emit (pyre:pass leaf/- ~)) @@ -861,7 +861,8 @@ ++ kelvin-same ^+ vats ~> %slog.(fmt "merging into {here}") - =. rail.rak +:(crank-next %& (dec aeon:ral)) + ?> ?=(^ rail.rak) + =. next.u.rail.rak ~ (emil ~[merge-main sync-ud]:pass) :: ++ do-base @@ -878,7 +879,8 @@ =/ =diff [%block loc rak new-weft blockers] (emil sync-ud:pass (diff:give diff) ~) ~> %slog.(fmt "applying OTA to {here}, kelvin: {}") - =. rail.rak +:(crank-next %& (dec aeon:ral)) + ?> ?=(^ rail.rak) + =. next.u.rail.rak ~ =. wef ?: =(old-weft new-weft) ~ `new-weft @@ -912,11 +914,7 @@ update-running-dudes ?. =(%base loc) kiln - =/ kel=[@tas @ud] - ?~ rail.rak zuse/zuse - ?~ next.u.rail.rak zuse/zuse - weft.i.next.u.rail.rak - (bump-many kel (all-desks-but (get-unblockers ark))) + (bump-many (all-desks-but (get-unblockers ark))) :: ++ take-merge-main |= syn=sign-arvo @@ -991,7 +989,7 @@ :: +crank-next: pop stale items from .next until one matches :: ++ crank-next - |= new=(each aeon weft) + |= new=weft ^+ [match=*(unit rung) rail.rak] ?~ rail.rak ~| [%no-rail-for desk=loc] @@ -1000,10 +998,7 @@ =- [match `u.rail.rak(next next)] |- ^- [match=(unit rung) next=(list rung)] ?~ rog [~ next.u.rail.rak] - ?: ?- -.new - %& =(p.new aeon.i.rog) - %| =(p.new weft.i.rog) - == + ?: =(new weft.i.rog) [`i.rog t.rog] $(rog t.rog) :: diff --git a/pkg/arvo/mar/kiln/bump.hoon b/pkg/arvo/mar/kiln/bump.hoon index 35896403b..766454277 100644 --- a/pkg/arvo/mar/kiln/bump.hoon +++ b/pkg/arvo/mar/kiln/bump.hoon @@ -1,5 +1,5 @@ |% -+$ bump [%kiln-bump except=(set desk) force=_|] ++$ bump [except=(set desk) force=_|] -- |_ b=bump ++ grad %noun @@ -9,7 +9,6 @@ ++ json ^- $-(^json bump) =, dejs:format - %+ pe %kiln-bump %- ot :~ except+(as so) force+bo diff --git a/pkg/garden/desk.docket-0 b/pkg/garden/desk.docket-0 index 9b443f75f..8c07fb65c 100644 --- a/pkg/garden/desk.docket-0 +++ b/pkg/garden/desk.docket-0 @@ -1,10 +1,10 @@ :~ title+'System' info+'An app launcher for Urbit.' color+0xee.5432 - glob-http+['https://bootstrap.urbit.org/glob-0v5.fdf99.nph65.qecq3.ncpjn.q13mb.glob' 0v5.fdf99.nph65.qecq3.ncpjn.q13mb] + glob-http+['https://bootstrap.urbit.org/glob-0v4.64ana.19ug9.ik7l6.og080.68ce4.glob' 0v4.64ana.19ug9.ik7l6.og080.68ce4] ::glob-ames+~zod^0v0 base+'grid' - version+[1 0 1] + version+[1 0 2] website+'https://tlon.io' license+'MIT' == diff --git a/pkg/grid/src/app.tsx b/pkg/grid/src/app.tsx index 65371fd88..c18188296 100644 --- a/pkg/grid/src/app.tsx +++ b/pkg/grid/src/app.tsx @@ -49,8 +49,6 @@ const AppRoutes = () => { } }, [isDarkMode, theme]); - useEffect(() => {}, []); - useEffect( handleError(() => { window.name = 'grid'; diff --git a/pkg/grid/src/nav/Leap.tsx b/pkg/grid/src/nav/Leap.tsx index 526cbd3a0..6475e09e2 100644 --- a/pkg/grid/src/nav/Leap.tsx +++ b/pkg/grid/src/nav/Leap.tsx @@ -227,6 +227,7 @@ export const Leap = React.forwardRef( [selection, rawInput, match, matches, selectedMatch] ); + return (
- {selection || 'Search'} + {menu === 'upgrading' + ? 'Your Urbit is being updated, this page will update when ready' + : selection || 'Search'} - + {menu !== 'upgrading' ? ( + + ) : null}
{menu === 'search' && ( = ({ menu }) => { const select = useLeapStore((state) => state.select); const menuState = menu || 'closed'; - const isOpen = menuState !== 'closed'; + const isOpen = menuState !== 'upgrading' && menuState !== 'closed'; const eitherOpen = isOpen || systemMenuOpen; useEffect(() => { diff --git a/pkg/grid/src/nav/notifications/Inbox.tsx b/pkg/grid/src/nav/notifications/Inbox.tsx index 66299772c..4661f884e 100644 --- a/pkg/grid/src/nav/notifications/Inbox.tsx +++ b/pkg/grid/src/nav/notifications/Inbox.tsx @@ -12,7 +12,7 @@ function renderNotification(notification: Notification, key: string, lid: HarkLi if (notification.bin.place.path === '/lag') { return ; } - if (notification.bin.place.path === '/blocked') { + if (notification.bin.path === '/blocked' && notification.bin.place.path === '/desk/base') { return ; } if (notification.bin.place.path === '/onboard') { diff --git a/pkg/grid/src/nav/notifications/SystemNotification.tsx b/pkg/grid/src/nav/notifications/SystemNotification.tsx index accb6a95c..f9f650720 100644 --- a/pkg/grid/src/nav/notifications/SystemNotification.tsx +++ b/pkg/grid/src/nav/notifications/SystemNotification.tsx @@ -1,4 +1,4 @@ -import { pick } from 'lodash'; +import { pick, pickBy, partition } from 'lodash'; import React, { useCallback } from 'react'; import { kilnBump } from '@urbit/api/hood'; import { AppList } from '../../components/AppList'; @@ -7,9 +7,12 @@ import { Dialog, DialogClose, DialogContent, DialogTrigger } from '../../compone import { Elbow } from '../../components/icons/Elbow'; import api from '../../state/api'; import { useCharges } from '../../state/docket'; +import useKilnState, { useVat } from '../../state/kiln'; import { NotificationButton } from './NotificationButton'; import { disableDefault } from '../../state/util'; +import { Vat } from '@urbit/api'; +import {useHistory} from 'react-router-dom'; export const RuntimeLagNotification = () => (
(
); +function vatIsBlocked(newKelvin: number, vat: Vat) { + return !(vat.arak?.rail?.next || []).find(({ aeon, weft }) => weft.kelvin === newKelvin); +} + export const BaseBlockedNotification = () => { - const desks: string[] = []; + const base = useVat('base'); + const { push } = useHistory(); + // TODO: assert weft.name === 'zuse'?? + const newKelvin = base?.arak?.rail?.next?.[0]?.weft?.kelvin || 420; const charges = useCharges(); - const blockedCharges = Object.values(pick(charges, desks)); + const [blocked, unblocked] = useKilnState((s) => { + const [b, u] = partition(Object.entries(s.vats), ([desk, vat]) => vatIsBlocked(newKelvin, vat)); + return [b.map(([d]) => d), u.map(([d]) => d)] as const; + }); + + const blockedCharges = Object.values(pick(charges, blocked)); const count = blockedCharges.length; const handlePauseOTAs = useCallback(() => {}, []); const handleArchiveApps = useCallback(async () => { api.poke(kilnBump(true)); + push('/leap/upgrading'); }, []); return ( diff --git a/pkg/grid/src/pages/Grid.tsx b/pkg/grid/src/pages/Grid.tsx index 1ad02a9cc..9c3c6c756 100644 --- a/pkg/grid/src/pages/Grid.tsx +++ b/pkg/grid/src/pages/Grid.tsx @@ -1,27 +1,51 @@ import { map, omit } from 'lodash'; -import React, { FunctionComponent } from 'react'; +import React, { FunctionComponent, useEffect } from 'react'; import { ErrorBoundary } from 'react-error-boundary'; -import { Route, RouteComponentProps } from 'react-router-dom'; +import { Route, RouteComponentProps, useHistory, useParams } from 'react-router-dom'; import { ErrorAlert } from '../components/ErrorAlert'; import { MenuState, Nav } from '../nav/Nav'; import { useCharges } from '../state/docket'; +import useKilnState from '../state/kiln'; import { RemoveApp } from '../tiles/RemoveApp'; import { SuspendApp } from '../tiles/SuspendApp'; import { Tile } from '../tiles/Tile'; import { TileInfo } from '../tiles/TileInfo'; -type GridProps = RouteComponentProps<{ +interface RouteProps { menu?: MenuState; -}>; +} -export const Grid: FunctionComponent = ({ match, history }) => { +export const Grid: FunctionComponent<{}> = () => { const charges = useCharges(); + const { push } = useHistory(); + const { menu } = useParams(); const chargesLoaded = Object.keys(charges).length > 0; + useEffect(() => { + // TOOD: rework + // Heuristically detect reload completion and redirect + async function attempt(count = 0) { + if(count > 5) { + window.location.reload(); + } + const start = performance.now(); + await useKilnState.getState().fetchVats(); + await useKilnState.getState().fetchVats(); + if((performance.now() - start) > 5000) { + attempt(count+1); + } else { + push('/'); + } + } + if(menu === 'upgrading') { + attempt(); + } + }, [menu]) + return (
-
@@ -30,11 +54,11 @@ export const Grid: FunctionComponent = ({ match, history }) => {
{charges && map(omit(charges, window.desk), (charge, desk) => ( - + ))}
)} - history.push('/')}> + push('/')}> diff --git a/pkg/grid/src/state/mock-data.ts b/pkg/grid/src/state/mock-data.ts index 44240b3f3..f21d638d8 100644 --- a/pkg/grid/src/state/mock-data.ts +++ b/pkg/grid/src/state/mock-data.ts @@ -241,7 +241,17 @@ function createMockSysNotification(path: string, body: HarkBody[] = []) { } const lag = createMockSysNotification('/lag'); -const blocked = createMockSysNotification('/blocked'); +const blocked = { + bin: { + place: { + desk: window.desk, + path: '/desk/base' + }, + path: '/blocked' + }, + time: Date.now() - 3_600, + body: [] +}; const onboard = createMockSysNotification('/onboard'); const updateNotification = createMockSysNotification('/desk/bitcoin', [ diff --git a/pkg/grid/src/tiles/Tile.tsx b/pkg/grid/src/tiles/Tile.tsx index 45280d70f..ce172926f 100644 --- a/pkg/grid/src/tiles/Tile.tsx +++ b/pkg/grid/src/tiles/Tile.tsx @@ -13,19 +13,20 @@ import { Bullet } from '../components/icons/Bullet'; type TileProps = { charge: ChargeWithDesk; desk: string; + disabled?: boolean; }; -export const Tile: FunctionComponent = ({ charge, desk }) => { +export const Tile: FunctionComponent = ({ charge, desk, disabled = false }) => { const addRecentApp = useRecentsStore((state) => state.addRecentApp); const { title, image, color, chad, href } = charge; const vat = useVat(desk); const { lightText, tileColor, menuColor, suspendColor, suspendMenuColor } = useTileColor(color); - const loading = 'install' in chad; - const suspended = 'suspend' in chad; + const loading = !disabled && 'install' in chad; + const suspended = disabled || 'suspend' in chad; const hung = 'hung' in chad; - const active = chadIsRunning(chad); + const active = !disabled && chadIsRunning(chad); const link = getAppHref(href); - const backgroundColor = active ? tileColor || 'purple' : suspendColor; + const backgroundColor = suspended ? suspendColor : active ? tileColor || 'purple' : suspendColor; return ( = ({ charge, desk }) => { <> {loading && } - {suspended && 'Suspended'} - {loading && 'Installing'} - {hung && 'Errored'} + {suspended ? 'Suspended' : loading ? 'Installing' : hung ? 'Errored' : null } )}
- {vat?.arak.rail?.paused && ( + {vat?.arak.rail?.paused && !disabled && ( )}