mirror of
https://github.com/zhigang1992/wallet.git
synced 2026-04-29 13:15:32 +08:00
feat: add warning messages
This commit is contained in:
5
.changeset/brown-pandas-clap.md
Normal file
5
.changeset/brown-pandas-clap.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@stacks/wallet-web': minor
|
||||
---
|
||||
|
||||
Adds messages sourced from the main branch of the repository
|
||||
17
.github/workflows/code-checks.yml
vendored
17
.github/workflows/code-checks.yml
vendored
@@ -159,6 +159,23 @@ jobs:
|
||||
- name: Test
|
||||
run: yarn test:unit
|
||||
|
||||
check-message-schema:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 14.x
|
||||
|
||||
- name: Install ajv-cli
|
||||
runs: yarn global add ajv-cli
|
||||
|
||||
- name: Validate message schema
|
||||
runs: ajv-cli validate -s scripts/wallet-comms.schema.json -d wallet-comms.json
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
||||
1
config/wallet-comms.json
Normal file
1
config/wallet-comms.json
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
26
config/wallet-comms.md
Normal file
26
config/wallet-comms.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Hiro Wallet messages
|
||||
|
||||
All Hiro Wallet instances make HTTP requests to the file located in `config/wallet-comms.json`. If there are messages, either global or pinned to a matching version, they will be displayed on the wallet's home screen.
|
||||
|
||||
If there are no messages, the object should be empty: `{}`
|
||||
|
||||
The schema of the `wallet-comms.json` file is validated by Github Actions.
|
||||
|
||||
### Example
|
||||
|
||||
A message targeting all versions is referred to with the key `global`. The JSON may look something like:
|
||||
|
||||
```json
|
||||
{
|
||||
"global": [
|
||||
{
|
||||
"purpose": "info",
|
||||
"title": "API experiencing slowness",
|
||||
"text": "Balances and transactions may take longer to update",
|
||||
"learnMoreUrl": "https://stacks.co",
|
||||
"publishedAt": "2021-09-27T07:57:37.397Z",
|
||||
"dismissible": false
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
43
config/wallet-comms.schema.json
Normal file
43
config/wallet-comms.schema.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema",
|
||||
"type": "object",
|
||||
"description": "Dictionary describing the application versions for which the messages should be displayed. Use `global` for all versions.",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9]*$": {
|
||||
"type": "array",
|
||||
"description": "ONLY FIRST ITEM WILL SHOW IN WALLET.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": ["purpose", "title", "text", "publishedAt", "dismissible"],
|
||||
"properties": {
|
||||
"purpose": {
|
||||
"type": "string",
|
||||
"enum": ["info", "warning", "error"],
|
||||
"description": "Add additional semantics to the purpose of the message. May be used in UI to indicate style variants"
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "Short headline that introduces the issue at hand"
|
||||
},
|
||||
"text": {
|
||||
"type": "string",
|
||||
"description": "Additional context to explain what the issue concerns"
|
||||
},
|
||||
"publishedAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Estimate date time at which the message has been published"
|
||||
},
|
||||
"learnMoreUrl": {
|
||||
"type": "string",
|
||||
"description": "URL to additional resources such as blog or forum post"
|
||||
},
|
||||
"dismissible": {
|
||||
"type": "boolean",
|
||||
"description": "NOT IMPLEMENTED IN WALLET. Whether or not the message can be dismissed by the user"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,10 @@ export const POPUP_WIDTH = 442;
|
||||
export const POPUP_HEIGHT = 646;
|
||||
export const MICROBLOCKS_ENABLED = !IS_TEST_ENV && true;
|
||||
|
||||
export const GITHUB_ORG = 'blockstack';
|
||||
export const GITHUB_REPO = 'stacks-wallet-web';
|
||||
export const GITHUB_PRIMARY_BRANCH = 'main';
|
||||
|
||||
export const SIP_010 = {
|
||||
mainnet: {
|
||||
address: 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE',
|
||||
|
||||
30
src/common/hooks/use-hiro-messages.ts
Normal file
30
src/common/hooks/use-hiro-messages.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { GITHUB_ORG, GITHUB_PRIMARY_BRANCH, GITHUB_REPO } from '@common/constants';
|
||||
import { useQuery } from 'react-query';
|
||||
|
||||
export interface HiroMessage {
|
||||
title: string;
|
||||
text: string;
|
||||
purpose: 'error' | 'info' | 'warning';
|
||||
publishedAt: string;
|
||||
dismissible: boolean;
|
||||
learnMoreUrl?: string;
|
||||
}
|
||||
|
||||
type HiroMessagesResponse = Record<string, HiroMessage[]>;
|
||||
|
||||
const githubCommsConfigRawUrl = `https://raw.githubusercontent.com/${GITHUB_ORG}/${GITHUB_REPO}/${GITHUB_PRIMARY_BRANCH}/config/wallet-comms.json`;
|
||||
|
||||
async function fetchHiroMessages(): Promise<HiroMessagesResponse> {
|
||||
return fetch(githubCommsConfigRawUrl).then(msg => msg.json());
|
||||
}
|
||||
|
||||
export function useHiroMessages() {
|
||||
const { data } = useQuery(['walletComms'], fetchHiroMessages, {
|
||||
// As we're fetching from Github, a third-party, we want
|
||||
// to avoid any unnecessary stress on their services, so
|
||||
// we use quite slow stale/retry times
|
||||
staleTime: 1000 * 60 * 10,
|
||||
retryDelay: 1000 * 60,
|
||||
});
|
||||
return data;
|
||||
}
|
||||
@@ -45,6 +45,7 @@ export const Header: React.FC<HeaderProps> = memo(props => {
|
||||
alignItems={hideActions ? 'center' : 'flex-start'}
|
||||
justifyContent="space-between"
|
||||
position="relative"
|
||||
scrollSnapAlign="start"
|
||||
{...rest}
|
||||
>
|
||||
{!title ? (
|
||||
|
||||
@@ -62,6 +62,7 @@ export const PopupContainer: React.FC<PopupHomeProps> = ({ children, header, req
|
||||
maxHeight="100vh"
|
||||
position="relative"
|
||||
overflow="auto"
|
||||
scrollSnapType="y proximity"
|
||||
>
|
||||
{header || null}
|
||||
<Flex
|
||||
|
||||
37
src/features/hiro-messages/components/hiro-message-item.tsx
Normal file
37
src/features/hiro-messages/components/hiro-message-item.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import React, { FC } from 'react';
|
||||
import { Box, color, Flex, Text } from '@stacks/ui';
|
||||
import { FiInfo } from 'react-icons/fi';
|
||||
import { HiroMessage } from '@common/hooks/use-hiro-messages';
|
||||
|
||||
export const HiroMessageItem: FC<HiroMessage> = props => {
|
||||
const { title, text, learnMoreUrl } = props;
|
||||
|
||||
return (
|
||||
<Flex>
|
||||
<Box mr="tight" mt="2px">
|
||||
<FiInfo size="16px" color={color('accent')} />
|
||||
</Box>
|
||||
<Box>
|
||||
<Text display="block" textStyle="body.small.medium" lineHeight="20px">
|
||||
{title}
|
||||
</Text>
|
||||
<Text display="inline" textStyle="caption" mt="extra-tight" mr="extra-tight">
|
||||
{text}
|
||||
</Text>
|
||||
{learnMoreUrl && (
|
||||
<Text
|
||||
as="a"
|
||||
display="inline-block"
|
||||
textStyle="caption"
|
||||
textDecoration="underline"
|
||||
href={learnMoreUrl}
|
||||
whiteSpace="nowrap"
|
||||
target="_blank"
|
||||
>
|
||||
Learn more
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
18
src/features/hiro-messages/hiro-messages.tsx
Normal file
18
src/features/hiro-messages/hiro-messages.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import React from 'react';
|
||||
import { Box, Flex, FlexProps } from '@stacks/ui';
|
||||
|
||||
import { useHiroMessages } from '@common/hooks/use-hiro-messages';
|
||||
import { HiroMessageItem } from './components/hiro-message-item';
|
||||
|
||||
export const HiroMessages = (props: FlexProps) => {
|
||||
const messages = useHiroMessages();
|
||||
if (!messages || !messages.global || !messages.global[0]) return null;
|
||||
|
||||
return (
|
||||
<Box pt="tight" scrollSnapAlign="start" scrollPadding="20%">
|
||||
<Flex background="#F7F8FD" borderRadius="8px" p="base" {...props}>
|
||||
<HiroMessageItem {...messages.global[0]} />
|
||||
</Flex>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -1,25 +1,28 @@
|
||||
import React from 'react';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
import { Stack } from '@stacks/ui';
|
||||
import { Box, Stack } from '@stacks/ui';
|
||||
import { PopupContainer } from '@components/popup/container';
|
||||
import { Header } from '@components/header';
|
||||
import { BalancesAndActivity } from '@components/popup/balances-and-activity';
|
||||
import { UserAccount } from '@pages/home/components/user-area';
|
||||
import { HomeActions } from '@pages/home/components/actions';
|
||||
|
||||
const PageTop = () => (
|
||||
<>
|
||||
<UserAccount />
|
||||
<HomeActions />
|
||||
</>
|
||||
);
|
||||
import { HiroMessages } from '@features/hiro-messages/hiro-messages';
|
||||
|
||||
export const PopupHome = () => {
|
||||
return (
|
||||
<>
|
||||
<PopupContainer header={<Header />} requestType="auth">
|
||||
<PopupContainer
|
||||
header={
|
||||
<>
|
||||
<HiroMessages mx="tight" />
|
||||
<Header pt="base-tight" />
|
||||
</>
|
||||
}
|
||||
requestType="auth"
|
||||
>
|
||||
<Stack data-testid="home-page" flexGrow={1} spacing="loose">
|
||||
<PageTop />
|
||||
<UserAccount />
|
||||
<HomeActions />
|
||||
<BalancesAndActivity />
|
||||
</Stack>
|
||||
</PopupContainer>
|
||||
|
||||
Reference in New Issue
Block a user