mirror of
https://github.com/joinmarket-webui/jam.git
synced 2026-08-20 13:28:21 +02:00
chore: pass versions to footer
This commit is contained in:
parent
4f1ad18e9f
commit
428cd8d6cd
8 changed files with 66 additions and 30 deletions
|
|
@ -88,7 +88,9 @@ const withTheme = (Story: React.ComponentType, context: GlobalContext) => {
|
|||
)
|
||||
}
|
||||
|
||||
const withQueryClient = (Story: React.ComponentType) => {
|
||||
// Use only when necessary! Try to pass data from queries to
|
||||
// components so they can be tested independently from an API.
|
||||
export const withQueryClient = (Story: React.ComponentType) => {
|
||||
const queryClient = new QueryClient()
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
|
|
@ -98,6 +100,6 @@ const withQueryClient = (Story: React.ComponentType) => {
|
|||
}
|
||||
|
||||
// export decorators for storybook to wrap your stories in
|
||||
export const decorators = [withTheme, withI18next, withQueryClient]
|
||||
export const decorators = [withTheme, withI18next]
|
||||
|
||||
export default preview
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useState } from 'react'
|
||||
import { useState, type ComponentProps } from 'react'
|
||||
import { AlertTriangleIcon, BlocksIcon, BookOpenIcon, FileQuestionMarkIcon } from 'lucide-react'
|
||||
import { useTranslation, Trans } from 'react-i18next'
|
||||
import { useStore } from 'zustand'
|
||||
|
|
@ -9,23 +9,27 @@ import { Dialog, DialogContent, DialogFooter } from '@/components/ui/dialog'
|
|||
import { Cheatsheet } from '@/components/ui/jam/Cheatsheet'
|
||||
import { JmWebsocketInfo } from '@/components/ui/jam/JmWebsocketInfo'
|
||||
import { useCheatsheet } from '@/hooks/useCheatsheet'
|
||||
import { useJmInfo } from '@/hooks/useJmInfo'
|
||||
import type { JmWebsocket } from '@/hooks/useJmWebsocket'
|
||||
import { toSemVer } from '@/lib/utils'
|
||||
import type { SemVer } from '@/lib/utils'
|
||||
import { jmSessionStore } from '@/store/jmSessionStore'
|
||||
import packageInfo from '../../../package.json'
|
||||
|
||||
const APP_DISPLAY_VERSION = (() => {
|
||||
const version = toSemVer(packageInfo.version)
|
||||
return version.raw
|
||||
})()
|
||||
type WithRequiredProperty<Type, Key extends keyof Type> = Type & {
|
||||
[Property in Key]-?: Type[Property]
|
||||
}
|
||||
|
||||
const BetaWarningModal = ({ open, onOpenChange }: { open: boolean; onOpenChange: (open: boolean) => void }) => {
|
||||
type BetaWarningModalProps = WithRequiredProperty<
|
||||
Omit<ComponentProps<typeof Dialog>, 'children'>,
|
||||
'open' | 'onOpenChange'
|
||||
> & {
|
||||
jamVersion: SemVer
|
||||
joinmarketVersion?: SemVer
|
||||
}
|
||||
|
||||
const BetaWarningModal = ({ jamVersion, joinmarketVersion, ...dialogProps }: BetaWarningModalProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { version } = useJmInfo()
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<Dialog {...dialogProps}>
|
||||
<DialogContent className="pt-12" showCloseButton={true}>
|
||||
<Alert variant="default">
|
||||
<AlertTriangleIcon />
|
||||
|
|
@ -34,12 +38,12 @@ const BetaWarningModal = ({ open, onOpenChange }: { open: boolean; onOpenChange:
|
|||
</Alert>
|
||||
|
||||
<p className="text-muted-foreground text-sm">
|
||||
JoinMarket: v{version?.raw || '_unknown'}
|
||||
JoinMarket: v{joinmarketVersion?.raw || '_unknown'}
|
||||
<br />
|
||||
Jam: v{APP_DISPLAY_VERSION}
|
||||
Jam: v{jamVersion.raw || '_unknown'}
|
||||
</p>
|
||||
<DialogFooter>
|
||||
<Button onClick={() => onOpenChange(false)}>{t('footer.warning_alert_button_ok')}</Button>
|
||||
<Button onClick={() => dialogProps.onOpenChange(false)}>{t('footer.warning_alert_button_ok')}</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
|
@ -47,11 +51,12 @@ const BetaWarningModal = ({ open, onOpenChange }: { open: boolean; onOpenChange:
|
|||
}
|
||||
|
||||
type JmWebsocketInfo = Pick<JmWebsocket, 'isOpen' | 'isAuthenticated'>
|
||||
interface AppFooterProps {
|
||||
|
||||
type AppFooterProps = Pick<BetaWarningModalProps, 'jamVersion' | 'joinmarketVersion'> & {
|
||||
websocketInfo?: JmWebsocketInfo
|
||||
}
|
||||
|
||||
export function AppFooter({ websocketInfo }: AppFooterProps) {
|
||||
export function AppFooter({ websocketInfo, jamVersion, joinmarketVersion }: AppFooterProps) {
|
||||
const { t } = useTranslation()
|
||||
const cheatsheet = useCheatsheet()
|
||||
|
||||
|
|
@ -63,7 +68,12 @@ export function AppFooter({ websocketInfo }: AppFooterProps) {
|
|||
<>
|
||||
<footer className="flex items-center justify-between gap-2 p-4">
|
||||
<div className="hidden flex-1 text-xs sm:block">
|
||||
<BetaWarningModal open={isShowBetaWarning} onOpenChange={setShowBetaWarning} />
|
||||
<BetaWarningModal
|
||||
open={isShowBetaWarning}
|
||||
onOpenChange={setShowBetaWarning}
|
||||
joinmarketVersion={joinmarketVersion}
|
||||
jamVersion={jamVersion}
|
||||
/>
|
||||
<Trans i18nKey="footer.warning">
|
||||
This is pre-alpha software.
|
||||
<Button variant="link" size="sm" className="h-auto p-0 text-xs" onClick={() => setShowBetaWarning(true)}>
|
||||
|
|
@ -105,7 +115,7 @@ export function AppFooter({ websocketInfo }: AppFooterProps) {
|
|||
rel="noopener noreferrer"
|
||||
className="text-right underline opacity-80"
|
||||
>
|
||||
v{APP_DISPLAY_VERSION}
|
||||
v{jamVersion?.raw}
|
||||
</a>
|
||||
{blockHeight && (
|
||||
<span className="flex items-center gap-1">
|
||||
|
|
|
|||
|
|
@ -7,8 +7,10 @@ import { AppFooter } from '@/components/layout/AppFooter'
|
|||
import { AppNavbar } from '@/components/layout/AppNavbar'
|
||||
import { Sidebar, SidebarProvider, SidebarTrigger } from '@/components/ui/sidebar'
|
||||
import { useSidebar } from '@/components/ui/use-sidebar'
|
||||
import { APP_DISPLAY_VERSION } from '@/constants/jam'
|
||||
import { useJamDisplayContext } from '@/context/JamDisplayContext'
|
||||
import { useJamWalletInfoContext } from '@/context/JamWalletInfoContext'
|
||||
import { useJmInfo } from '@/hooks/useJmInfo'
|
||||
import { useJmWebsocket } from '@/hooks/useJmWebsocket'
|
||||
import { jmSessionStore } from '@/store/jmSessionStore'
|
||||
import { AppSidebar } from './AppSidebar'
|
||||
|
|
@ -26,6 +28,8 @@ export function LayoutInner({ onLogout, onLockWallet, children }: LayoutInnerPro
|
|||
const navigate = useNavigate()
|
||||
const jmSessionState = useStore(jmSessionStore, (state) => state.state)
|
||||
|
||||
const { version: joinmarketVersion } = useJmInfo()
|
||||
|
||||
const { resolvedTheme, setTheme } = useTheme()
|
||||
const toggleTheme = () => setTheme(resolvedTheme === 'dark' ? 'light' : 'dark')
|
||||
|
||||
|
|
@ -53,7 +57,7 @@ export function LayoutInner({ onLogout, onLockWallet, children }: LayoutInnerPro
|
|||
sidebarInfo={sidebarContext}
|
||||
/>
|
||||
<main className="flex-1">{children}</main>
|
||||
<AppFooter websocketInfo={websocket} />
|
||||
<AppFooter websocketInfo={websocket} jamVersion={APP_DISPLAY_VERSION} joinmarketVersion={joinmarketVersion} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
import { percentageToFactor } from '@/lib/utils'
|
||||
import { percentageToFactor, toSemVer } from '@/lib/utils'
|
||||
import type { AmountSats, Milliseconds } from '@/types/global'
|
||||
import { version as packageInfoVersion } from '../../package.json'
|
||||
import { JM_API_AUTH_TOKEN_EXPIRY, JM_DUST_THRESHOLD } from './jm'
|
||||
|
||||
export const APP_DISPLAY_VERSION = (() => {
|
||||
return toSemVer(packageInfoVersion)
|
||||
})()
|
||||
|
||||
export const TX_FEES_FACTOR_MIN = 0 // 0%
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,19 +1,25 @@
|
|||
import { versionOptions } from '@joinmarket-webui/joinmarket-api-ts/@tanstack/react-query'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import type { ErrorMessage, VersionResponse } from '@joinmarket-webui/joinmarket-api-ts/jm'
|
||||
import { useQuery, type UseQueryResult } from '@tanstack/react-query'
|
||||
import { useApiClient } from '@/hooks/useApiClient'
|
||||
import { toSemVer } from '@/lib/utils'
|
||||
import { toSemVer, type SemVer } from '@/lib/utils'
|
||||
|
||||
export const useJmInfo = () => {
|
||||
type UseJmInfoResult = {
|
||||
version: SemVer | undefined
|
||||
queryResult: UseQueryResult<VersionResponse, ErrorMessage>
|
||||
}
|
||||
|
||||
export function useJmInfo(): UseJmInfoResult {
|
||||
const client = useApiClient()
|
||||
|
||||
const { data, isPending } = useQuery({
|
||||
const queryResult = useQuery({
|
||||
...versionOptions({ client }),
|
||||
staleTime: Infinity,
|
||||
gcTime: Infinity,
|
||||
})
|
||||
|
||||
return {
|
||||
version: data ? toSemVer(data.version) : undefined,
|
||||
isLoading: isPending,
|
||||
version: queryResult.data ? toSemVer(queryResult.data.version) : undefined,
|
||||
queryResult,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ type UseUtxosResult = {
|
|||
utxos: Utxo[]
|
||||
queryResult: UseQueryResult<ListUtxosResponse, ErrorMessage>
|
||||
}
|
||||
|
||||
interface UseUtxosProps {
|
||||
walletFileName: WalletFileName
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ export const factorToPercentage = (val: number, precision = 6) => {
|
|||
return Number((val * 100).toFixed(precision))
|
||||
}
|
||||
|
||||
type SemVer = { major: number; minor: number; patch: number; raw?: string }
|
||||
export type SemVer = { major: number; minor: number; patch: number; raw?: string }
|
||||
|
||||
export const UNKNOWN_VERSION: SemVer = { major: 0, minor: 0, patch: 0, raw: 'unknown' }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import type { Meta, StoryObj } from '@storybook/react-vite'
|
||||
import { MemoryRouter } from 'react-router-dom'
|
||||
import { AppFooter } from '@/components/layout/AppFooter'
|
||||
import { APP_DISPLAY_VERSION } from '@/constants/jam'
|
||||
import { toSemVer } from '@/lib/utils'
|
||||
|
||||
const meta: Meta<typeof AppFooter> = {
|
||||
title: 'Layout/AppFooter',
|
||||
|
|
@ -19,5 +21,11 @@ export default meta
|
|||
type Story = StoryObj<typeof AppFooter>
|
||||
|
||||
export const Default: Story = {
|
||||
render: () => <AppFooter websocketInfo={{ isOpen: true, isAuthenticated: true }} />,
|
||||
render: () => (
|
||||
<AppFooter
|
||||
websocketInfo={{ isOpen: true, isAuthenticated: true }}
|
||||
jamVersion={APP_DISPLAY_VERSION}
|
||||
joinmarketVersion={toSemVer('0.9.12')}
|
||||
/>
|
||||
),
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue