From 0aba0eed23f11f3b76dab0d14f5564e1c6c2b1f9 Mon Sep 17 00:00:00 2001 From: Hunter Miller Date: Mon, 20 Sep 2021 14:54:50 -0500 Subject: [PATCH 1/2] local-storage: versioning --- pkg/grid/src/nav/search/Home.tsx | 3 ++- pkg/grid/src/state/base.ts | 4 ++-- pkg/grid/vite.config.ts | 4 ++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pkg/grid/src/nav/search/Home.tsx b/pkg/grid/src/nav/search/Home.tsx index 47df164ea..d25117026 100644 --- a/pkg/grid/src/nav/search/Home.tsx +++ b/pkg/grid/src/nav/search/Home.tsx @@ -53,7 +53,8 @@ export const useRecentsStore = create( }), { whitelist: ['recentApps', 'recentDevs'], - name: 'recents-store' + name: 'recents-store', + version: import.meta.env.VITE_SHORTHASH as any } ) ); diff --git a/pkg/grid/src/state/base.ts b/pkg/grid/src/state/base.ts index ddba61138..ea47c14cd 100644 --- a/pkg/grid/src/state/base.ts +++ b/pkg/grid/src/state/base.ts @@ -149,8 +149,8 @@ export const createState = >( }), { blacklist, - name: stateStorageKey(name) - // version: process.env.LANDSCAPE_SHORTHASH as any + name: stateStorageKey(name), + version: import.meta.env.VITE_SHORTHASH as any } ) ); diff --git a/pkg/grid/vite.config.ts b/pkg/grid/vite.config.ts index e159bf6ac..520cd3860 100644 --- a/pkg/grid/vite.config.ts +++ b/pkg/grid/vite.config.ts @@ -3,11 +3,15 @@ import analyze from 'rollup-plugin-analyzer'; import { visualizer } from 'rollup-plugin-visualizer'; import reactRefresh from '@vitejs/plugin-react-refresh'; import htmlPlugin from 'vite-plugin-html-config'; +import { execSync } from 'child_process'; const htmlPluginOpt = { headScripts: [{ src: '/apps/grid/desk.js' }, { src: '/session.js' }] }; +const GIT_DESC = execSync('git describe --always', { encoding: 'utf8' }).trim(); +process.env.VITE_SHORTHASH = GIT_DESC; + // https://vitejs.dev/config/ export default ({ mode }) => { Object.assign(process.env, loadEnv(mode, process.cwd())); From 9047053e130d3a013abb3fc0f1e89a0ecfb99333 Mon Sep 17 00:00:00 2001 From: Hunter Miller Date: Mon, 20 Sep 2021 16:30:22 -0500 Subject: [PATCH 2/2] grid: lots of fixes --- pkg/grid/src/components/AppInfo.tsx | 22 +++-- pkg/grid/src/nav/Leap.tsx | 1 + pkg/grid/src/nav/Notifications.tsx | 4 - pkg/grid/src/nav/Search.tsx | 5 +- pkg/grid/src/nav/SystemMenu.tsx | 22 +++-- .../nav/notifications/BasicNotification.tsx | 13 +-- .../notifications/OnboardingNotification.tsx | 98 +++++++++++-------- .../nav/notifications/SystemNotification.tsx | 6 +- pkg/grid/src/nav/search/TreatyInfo.tsx | 5 +- pkg/grid/src/state/kiln.ts | 6 +- pkg/grid/src/state/util.ts | 6 ++ pkg/grid/src/styles/base.css | 23 +++++ pkg/grid/src/styles/components.css | 4 +- pkg/grid/src/tiles/RemoveApp.tsx | 2 +- pkg/grid/src/tiles/SuspendApp.tsx | 2 +- pkg/grid/src/tiles/useTileColor.tsx | 6 +- 16 files changed, 142 insertions(+), 83 deletions(-) diff --git a/pkg/grid/src/components/AppInfo.tsx b/pkg/grid/src/components/AppInfo.tsx index cf10f6dc9..3b334951d 100644 --- a/pkg/grid/src/components/AppInfo.tsx +++ b/pkg/grid/src/components/AppInfo.tsx @@ -1,6 +1,6 @@ import { chadIsRunning, Treaty } from '@urbit/api'; import clipboardCopy from 'clipboard-copy'; -import React, { FC } from 'react'; +import React, { FC, useCallback, useState } from 'react'; import cn from 'classnames'; import { Vat } from '@urbit/api/hood'; import { Button, PillButton } from './Button'; @@ -50,6 +50,7 @@ function getRemoteDesk(docket: App, vat?: Vat) { export const AppInfo: FC = ({ docket, vat, className }) => { const installStatus = getInstallStatus(docket); const [ship, desk] = getRemoteDesk(docket, vat); + const [copied, setCopied] = useState(false); const installApp = async () => { if (installStatus === 'installed') { @@ -57,15 +58,21 @@ export const AppInfo: FC = ({ docket, vat, className }) => { } await useDocketState.getState().installDocket(ship, desk); }; - const copyApp = () => { - clipboardCopy(`web+urbitgraph://app/${ship}/${desk}`); - }; + + const copyApp = useCallback(() => { + setCopied(true); + clipboardCopy(`web+urbitgraph://${ship}/${desk}`); + + setTimeout(() => { + setCopied(false); + }, 1250); + }, []); if (!docket) { // TODO: maybe replace spinner with skeletons return ( -
- Loading... +
+
); } @@ -115,7 +122,8 @@ export const AppInfo: FC = ({ docket, vat, className }) => { )} - Copy App Link + {!copied && 'Copy App Link'} + {copied && 'copied!'}
diff --git a/pkg/grid/src/nav/Leap.tsx b/pkg/grid/src/nav/Leap.tsx index 1bccbaa65..50ad675cb 100644 --- a/pkg/grid/src/nav/Leap.tsx +++ b/pkg/grid/src/nav/Leap.tsx @@ -242,6 +242,7 @@ export const Leap = React.forwardRef( onFocus={onFocus} onChange={onChange} onKeyDown={onKeyDown} + autoComplete="off" aria-autocomplete="both" aria-controls={dropdown} aria-activedescendant={selectedMatch?.display || selectedMatch?.value} diff --git a/pkg/grid/src/nav/Notifications.tsx b/pkg/grid/src/nav/Notifications.tsx index c24562090..dda03cfc2 100644 --- a/pkg/grid/src/nav/Notifications.tsx +++ b/pkg/grid/src/nav/Notifications.tsx @@ -1,20 +1,16 @@ import React, { useEffect } from 'react'; import { Link, NavLink, Route, Switch } from 'react-router-dom'; -import { useLeapStore } from './Nav'; import { Button } from '../components/Button'; import { useHarkStore } from '../state/hark'; import { Inbox } from './notifications/Inbox'; export const Notifications = () => { - const select = useLeapStore((s) => s.select); const markAllAsRead = () => { const { archiveAll } = useHarkStore.getState(); archiveAll(); }; useEffect(() => { - select('Notifications'); - function visibilitychange() { if (document.visibilityState === 'hidden') { useHarkStore.getState().opened(); diff --git a/pkg/grid/src/nav/Search.tsx b/pkg/grid/src/nav/Search.tsx index 455333b28..c926f69d6 100644 --- a/pkg/grid/src/nav/Search.tsx +++ b/pkg/grid/src/nav/Search.tsx @@ -12,7 +12,10 @@ type SearchProps = RouteComponentProps<{ export const Search = ({ match }: SearchProps) => { return ( - + diff --git a/pkg/grid/src/nav/SystemMenu.tsx b/pkg/grid/src/nav/SystemMenu.tsx index 990ed915a..86266ac09 100644 --- a/pkg/grid/src/nav/SystemMenu.tsx +++ b/pkg/grid/src/nav/SystemMenu.tsx @@ -28,16 +28,22 @@ export const SystemMenu = ({ className, open, subMenuOpen, shouldDim }: SystemMe const hash = garden ? getHash(garden) : null; const isMobile = useMedia('(max-width: 639px)'); - const copyHash = useCallback((event: Event) => { - event.preventDefault(); + const copyHash = useCallback( + (event: Event) => { + event.preventDefault(); + if (!hash) { + return; + } - setCopied(true); - clipboardCopy('fjuhl'); + setCopied(true); + clipboardCopy(hash); - setTimeout(() => { - setCopied(false); - }, 1250); - }, []); + setTimeout(() => { + setCopied(false); + }, 1250); + }, + [hash] + ); const preventFlash = useCallback((e) => { const target = e.target as HTMLElement; diff --git a/pkg/grid/src/nav/notifications/BasicNotification.tsx b/pkg/grid/src/nav/notifications/BasicNotification.tsx index d8b8cb8b6..83e190c7a 100644 --- a/pkg/grid/src/nav/notifications/BasicNotification.tsx +++ b/pkg/grid/src/nav/notifications/BasicNotification.tsx @@ -5,10 +5,9 @@ import { map, take } from 'lodash'; import { useCharge } from '../../state/docket'; import { Elbow } from '../../components/icons/Elbow'; import { ShipName } from '../../components/ShipName'; -import { getAppHref } from '../../state/util'; -import { Link } from 'react-router-dom'; import { DeskLink } from '../../components/DeskLink'; -import {useHarkStore} from '../../state/hark'; +import { useHarkStore } from '../../state/hark'; +import { DocketImage } from '../../components/DocketImage'; interface BasicNotificationProps { notification: Notification; @@ -43,7 +42,6 @@ export const BasicNotification = ({ notification, lid }: BasicNotificationProps) const contents = map(notification.body, 'content').filter((c) => c.length > 0); const large = contents.length === 0; const archive = () => { - const { bin } = notification; useHarkStore.getState().archiveNote(notification.bin, lid); }; @@ -53,17 +51,14 @@ export const BasicNotification = ({ notification, lid }: BasicNotificationProps) to={`?grid-note=${encodeURIComponent(first.link)}`} desk={desk} className={cn( - 'text-black rounded', + 'text-black rounded-xl', 'unseen' in lid ? 'bg-blue-100' : 'bg-gray-100', large ? 'note-grid-no-content' : 'note-grid-content' )} aria-labelledby={id} >
-
+
{charge?.title || desk}
{!large ? : null}

diff --git a/pkg/grid/src/nav/notifications/OnboardingNotification.tsx b/pkg/grid/src/nav/notifications/OnboardingNotification.tsx index 743e9adcd..1919c9eeb 100644 --- a/pkg/grid/src/nav/notifications/OnboardingNotification.tsx +++ b/pkg/grid/src/nav/notifications/OnboardingNotification.tsx @@ -1,47 +1,57 @@ import React from 'react'; import cn from 'classnames'; +import { Link } from 'react-router-dom'; import { Button } from '../../components/Button'; +import { useCurrentTheme } from '../../state/local'; +import { getDarkColor } from '../../state/util'; const cards: OnboardingCardProps[] = [ { title: 'Terminal', body: "Install a web terminal to access your Urbit's command line", button: 'Install', - color: '#9CA4B1' + color: '#9CA4B1', + href: '/leap/search/direct/apps/~zod/webterm' }, { title: 'Groups', body: 'Install Groups, a suite of social software to communicate with other urbit users', button: 'Install', - color: '#D1DDD3' + color: '#D1DDD3', + href: '/leap/search/direct/apps/~zod/landscape' }, { title: 'Bitcoin', body: 'Install a bitcoin wallet. You can send bitcoin to any btc address, or even another ship', button: 'Install', - color: '#F6EBDB' - }, - { - title: 'Debug', - body: "Install a debugger. You can inspect your ship's internals using this interface", - button: 'Install' - }, - { - title: 'Build an app', - body: 'You can instantly get started building new things on Urbit. Just right click your Landscape and select “New App”', - button: 'Learn more', - color: '#82A6CA' + color: '#F6EBDB', + href: '/leap/search/direct/apps/~zod/bitcoin' } + // Commenting out until we have something real + // { + // title: 'Debug', + // body: "Install a debugger. You can inspect your ship's internals using this interface", + // button: 'Install', + // color: '#E5E5E5', + // href: '/leap/search/direct/apps/~zod/debug' + // } + // { + // title: 'Build an app', + // body: 'You can instantly get started building new things on Urbit. Just right click your Landscape and select “New App”', + // button: 'Learn more', + // color: '#82A6CA' + // } ]; interface OnboardingCardProps { title: string; button: string; + href: string; body: string; - color?: string; + color: string; } -const OnboardingCard = ({ title, button, body, color }: OnboardingCardProps) => ( +const OnboardingCard = ({ title, button, href, body, color }: OnboardingCardProps) => (

{title}

{body}

-

@@ -60,27 +70,35 @@ interface OnboardingNotificationProps { unread: boolean; } -export const OnboardingNotification = ({ unread }: OnboardingNotificationProps) => ( -
-
-
- - Grid +export const OnboardingNotification = ({ unread }: OnboardingNotificationProps) => { + const theme = useCurrentTheme(); + + return ( +
+
+
+ + Grid +
+
+

Hello there, welcome to Grid!

+
+
+
+ { + /* eslint-disable-next-line react/no-array-index-key */ + cards.map((card, i) => ( + + )) + }
-
-

Hello there, welcome to Grid!

-
-
-
- { - /* eslint-disable-next-line react/no-array-index-key */ - cards.map((card, i) => ( - - )) - } -
-
-); + + ); +}; diff --git a/pkg/grid/src/nav/notifications/SystemNotification.tsx b/pkg/grid/src/nav/notifications/SystemNotification.tsx index e50aa0feb..835414559 100644 --- a/pkg/grid/src/nav/notifications/SystemNotification.tsx +++ b/pkg/grid/src/nav/notifications/SystemNotification.tsx @@ -78,7 +78,8 @@ export const BaseBlockedNotification = () => { Dismiss

Skip System Update

@@ -108,7 +109,8 @@ export const BaseBlockedNotification = () => {

Archive ({count}) Apps and Apply System Update

diff --git a/pkg/grid/src/nav/search/TreatyInfo.tsx b/pkg/grid/src/nav/search/TreatyInfo.tsx index 57de404ff..8d556d091 100644 --- a/pkg/grid/src/nav/search/TreatyInfo.tsx +++ b/pkg/grid/src/nav/search/TreatyInfo.tsx @@ -1,6 +1,7 @@ import React, { useEffect } from 'react'; import { useParams } from 'react-router-dom'; import { AppInfo } from '../../components/AppInfo'; +import { Spinner } from '../../components/Spinner'; import useDocketState, { useCharge, useTreaty } from '../../state/docket'; import { useVat } from '../../state/kiln'; import { useLeapStore } from '../Nav'; @@ -25,8 +26,8 @@ export const TreatyInfo = () => { if (!treaty) { // TODO: maybe replace spinner with skeletons return ( -

- Loading... +
+
); } diff --git a/pkg/grid/src/state/kiln.ts b/pkg/grid/src/state/kiln.ts index 0de5ad68e..b1731307b 100644 --- a/pkg/grid/src/state/kiln.ts +++ b/pkg/grid/src/state/kiln.ts @@ -17,7 +17,7 @@ interface KilnState { toggleOTAs: (desk: string, on: boolean) => Promise; set: (s: KilnState) => void; } -const useKilnState = create((set) => ({ +const useKilnState = create((set, get) => ({ vats: useMockData ? mockVats : {}, lag: !!useMockData, loaded: false, @@ -66,6 +66,10 @@ const useKilnState = create((set) => ({ } await api.poke(on ? kilnResume(desk) : kilnPause(desk)); + + if (!on) { + get().fetchVats(); // refresh vat state + } }, set: produce(set) })); diff --git a/pkg/grid/src/state/util.ts b/pkg/grid/src/state/util.ts index 76fb253ee..8f738275c 100644 --- a/pkg/grid/src/state/util.ts +++ b/pkg/grid/src/state/util.ts @@ -1,4 +1,5 @@ import { DocketHref } from '@urbit/api/docket'; +import { hsla, parseToHsla } from 'color2k'; export const useMockData = import.meta.env.MODE === 'mock'; @@ -33,3 +34,8 @@ export function deSig(ship: string): string { } return ship.replace('~', ''); } + +export function getDarkColor(color: string): string { + const hslaColor = parseToHsla(color); + return hsla(hslaColor[0], hslaColor[1], 1 - hslaColor[2], 1); +} diff --git a/pkg/grid/src/styles/base.css b/pkg/grid/src/styles/base.css index f473781fb..b48a6d8d3 100644 --- a/pkg/grid/src/styles/base.css +++ b/pkg/grid/src/styles/base.css @@ -1,3 +1,26 @@ +body { + scrollbar-width: thin; + scrollbar-color: #e5e5e5 transparent; +} + +body::-webkit-scrollbar-thumb { + background-color: #e5e5e5; +} + +body::-webkit-scrollbar-track { + background: transparent; +} + +@media (prefers-color-scheme: dark) { + body { + scrollbar-color: #333333 transparent; + } + + body::-webkit-scrollbar-thumb { + background-color: #333333; + } +} + .h1 { @apply text-2xl sm:text-3xl font-bold leading-relaxed tracking-tighter; } diff --git a/pkg/grid/src/styles/components.css b/pkg/grid/src/styles/components.css index ff8690e1e..b0cebc598 100644 --- a/pkg/grid/src/styles/components.css +++ b/pkg/grid/src/styles/components.css @@ -7,11 +7,11 @@ } .dialog-container { - @apply fixed z-40 top-1/2 left-1/2 min-w-80 transform -translate-x-1/2 -translate-y-1/2; + @apply fixed z-40 top-1/2 left-1/2 p-4 transform -translate-x-1/2 -translate-y-1/2; } .dialog { - @apply relative p-5 sm:p-8 bg-white rounded-3xl; + @apply relative max-h-[calc(100vh-2rem)] max-w-[calc(100vw-2rem)] p-5 sm:p-8 bg-white rounded-3xl overflow-auto; } .dialog-inner-container { diff --git a/pkg/grid/src/tiles/RemoveApp.tsx b/pkg/grid/src/tiles/RemoveApp.tsx index 3325ce7cb..0efbcf24d 100644 --- a/pkg/grid/src/tiles/RemoveApp.tsx +++ b/pkg/grid/src/tiles/RemoveApp.tsx @@ -18,7 +18,7 @@ export const RemoveApp = () => { return ( !open && history.push('/')}> - +

Remove “{docket?.title || ''}”?

This will remove the software's tile from your home screen. diff --git a/pkg/grid/src/tiles/SuspendApp.tsx b/pkg/grid/src/tiles/SuspendApp.tsx index 7c295ae0e..a9da9f6b5 100644 --- a/pkg/grid/src/tiles/SuspendApp.tsx +++ b/pkg/grid/src/tiles/SuspendApp.tsx @@ -21,7 +21,7 @@ export const SuspendApp = () => { return (

!open && history.push('/')}> - +

Suspend “{charge?.title || ''}”

Suspending an app will freeze its current state and render it unable diff --git a/pkg/grid/src/tiles/useTileColor.tsx b/pkg/grid/src/tiles/useTileColor.tsx index 2d326c04c..2351903da 100644 --- a/pkg/grid/src/tiles/useTileColor.tsx +++ b/pkg/grid/src/tiles/useTileColor.tsx @@ -1,10 +1,6 @@ import { darken, hsla, lighten, parseToHsla, readableColorIsBlack } from 'color2k'; import { useCurrentTheme } from '../state/local'; - -function getDarkColor(color: string): string { - const hslaColor = parseToHsla(color); - return hsla(hslaColor[0], hslaColor[1], 1 - hslaColor[2], 1); -} +import { getDarkColor } from '../state/util'; function bgAdjustedColor(color: string, darkBg: boolean): string { return darkBg ? lighten(color, 0.1) : darken(color, 0.1);