Setup GitHub Actions (#287)
* add new GitHub Action for CI * add yarn flag * use actions v3 * add ci badge (lol) * cache lint and format scripts * add more steps * remove unused component * fix lint errors * remove unsued eslint plugins
This commit is contained in:
parent
afd5b1c6c3
commit
6fc6410b32
|
@ -32,14 +32,14 @@
|
|||
"plugin:jsx-a11y/recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
// "plugin:node/recommended",
|
||||
// "plugin:jest/recommended",
|
||||
"prettier"
|
||||
],
|
||||
"rules": {
|
||||
"react/prop-types": 0,
|
||||
// "@typescript-eslint/consistent-type-definitions": ["error", "interface"],
|
||||
"@typescript-eslint/consistent-type-imports": "error",
|
||||
// TODO: turn on this rul
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
// "@typescript-eslint/consistent-type-exports": "error",
|
||||
"simple-import-sort/imports": [
|
||||
"error",
|
||||
|
|
|
@ -1,20 +1,44 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
branches: ["main"]
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
build:
|
||||
name: Build and Test
|
||||
timeout-minutes: 15
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup node 16
|
||||
uses: actions/setup-node@v1
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn build
|
||||
- run: DEBUG=communities:test* yarn test
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Setup Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn --frozen-lockfile
|
||||
|
||||
- name: Build
|
||||
run: yarn build
|
||||
|
||||
- name: Typecheck
|
||||
run: yarn typecheck
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint && yarn format:check
|
||||
|
||||
- name: Test
|
||||
run: yarn test
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
# Status Communities for the Web
|
||||
|
||||
[![CI](https://github.com/status-im/status-web/actions/workflows/ci.yml/badge.svg)](https://github.com/status-im/status-web/actions/workflows/ci.yml)
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
"test": "turbo run test --filter=@status-im/* -- --run",
|
||||
"dev": "turbo run dev --parallel --filter=@status-im/*",
|
||||
"build": "turbo run build --filter=@status-im/*",
|
||||
"lint": "turbo run lint --filter=@status-im/*",
|
||||
"check": "turbo run check --filter=@status-im/*",
|
||||
"format": "prettier --write .",
|
||||
"typecheck": "turbo run typecheck --filter=@status-im/*",
|
||||
"lint": "eslint --cache --cache-location ./node_modules/.cache/eslint/.eslint-cache .",
|
||||
"format": "prettier --cache --write .",
|
||||
"format:check": "prettier --check .",
|
||||
"clean": "turbo run clean && rm -rf node_modules .parcel-cache"
|
||||
},
|
||||
|
@ -27,9 +27,7 @@
|
|||
"eslint-import-resolver-typescript": "^2.4.0",
|
||||
"eslint-plugin-eslint-comments": "^3.2.0",
|
||||
"eslint-plugin-import": "^2.25.2",
|
||||
"eslint-plugin-jest": "^26.1.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.5.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-react": "^7.27.0",
|
||||
"eslint-plugin-react-hooks": "^4.3.0",
|
||||
"eslint-plugin-simple-import-sort": "^7.0.0",
|
||||
|
|
|
@ -20,11 +20,12 @@
|
|||
},
|
||||
"scripts": {
|
||||
"dev": "vite build --watch --mode development",
|
||||
"build": "vite build && yarn typegen",
|
||||
"build": "vite build",
|
||||
"postbuild": "yarn typegen",
|
||||
"test": "vitest",
|
||||
"lint": "eslint src",
|
||||
"typecheck": "tsc",
|
||||
"typegen": "tsc --noEmit false --emitDeclarationOnly --paths null || true",
|
||||
"lint": "eslint src",
|
||||
"format": "prettier --write src",
|
||||
"protos": "protons protos/*.proto",
|
||||
"clean": "rm -rf dist node_modules .turbo"
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
},
|
||||
"scripts": {
|
||||
"dev": "vite build --watch --mode development",
|
||||
"build": "vite build && yarn typegen",
|
||||
"build": "vite build",
|
||||
"postbuild": "yarn typegen",
|
||||
"#test": "vitest",
|
||||
"typecheck": "tsc",
|
||||
"typegen": "tsc --noEmit false --emitDeclarationOnly --paths null || true",
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
// @ts-nocheck
|
||||
import React, { useMemo, useRef, useState } from 'react'
|
||||
|
||||
import styled from 'styled-components'
|
||||
|
||||
import { useIdentity } from '../../contexts/identityProvider'
|
||||
import { useActivities } from '../../hooks/useActivities'
|
||||
import { useClickOutside } from '../../hooks/useClickOutside'
|
||||
import { TopBtn } from '../Chat-legacy/ChatTopbar'
|
||||
import { ActivityIcon } from '../Icons/ActivityIcon'
|
||||
import { ActivityCenter } from './ActivityCenter'
|
||||
|
||||
interface ActivityButtonProps {
|
||||
className?: string
|
||||
}
|
||||
|
||||
export function ActivityButton({ className }: ActivityButtonProps) {
|
||||
const { activities, activityDispatch } = useActivities()
|
||||
const identity = useIdentity()
|
||||
const disabled = useMemo(() => !identity, [identity])
|
||||
const ref = useRef(null)
|
||||
useClickOutside(ref, () => setShowActivityCenter(false))
|
||||
|
||||
const [showActivityCenter, setShowActivityCenter] = useState(false)
|
||||
const badgeAmount = useMemo(
|
||||
() => activities.filter(activity => !activity.isRead).length,
|
||||
[activities]
|
||||
)
|
||||
|
||||
return (
|
||||
<ActivityWrapper ref={ref} className={className}>
|
||||
<TopBtn
|
||||
onClick={() => setShowActivityCenter(!showActivityCenter)}
|
||||
disabled={disabled}
|
||||
>
|
||||
<ActivityIcon />
|
||||
{badgeAmount > 0 && (
|
||||
<NotificationBagde
|
||||
className={
|
||||
badgeAmount > 99
|
||||
? 'countless'
|
||||
: badgeAmount > 9
|
||||
? 'wide'
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{badgeAmount < 100 ? badgeAmount : '∞'}
|
||||
</NotificationBagde>
|
||||
)}
|
||||
</TopBtn>
|
||||
{showActivityCenter && (
|
||||
<ActivityCenter
|
||||
activities={activities}
|
||||
setShowActivityCenter={setShowActivityCenter}
|
||||
activityDispatch={activityDispatch}
|
||||
/>
|
||||
)}
|
||||
</ActivityWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
export const ActivityWrapper = styled.div`
|
||||
padding-left: 10px;
|
||||
margin-left: 10px;
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
width: 2px;
|
||||
height: 24px;
|
||||
transform: translateY(-50%);
|
||||
border-radius: 1px;
|
||||
background: ${({ theme }) => theme.primary};
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
&.creation {
|
||||
padding-left: 0px;
|
||||
margin-left: 16px;
|
||||
|
||||
&:before {
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const NotificationBagde = styled.div`
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
right: -2px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
border-radius: 50%;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
font-weight: 500;
|
||||
background-color: ${({ theme }) => theme.notificationColor};
|
||||
color: ${({ theme }) => theme.bodyBackgroundColor};
|
||||
border-radius: 9px;
|
||||
|
||||
&.wide {
|
||||
width: 26px;
|
||||
right: -7px;
|
||||
}
|
||||
|
||||
&.countless {
|
||||
width: 22px;
|
||||
}
|
||||
`
|
|
@ -1,191 +0,0 @@
|
|||
// @ts-nocheck
|
||||
import React, { useMemo, useState } from 'react'
|
||||
|
||||
import styled from 'styled-components'
|
||||
|
||||
import { useMessengerContext } from '../../contexts/messengerProvider'
|
||||
import { buttonTransparentStyles } from '../Buttons/buttonStyle'
|
||||
import { Tooltip } from '../Form/Tooltip'
|
||||
import { HideIcon } from '../Icons/HideIcon'
|
||||
import { ReadIcon } from '../Icons/ReadIcon'
|
||||
import { ShowIcon } from '../Icons/ShowIcon'
|
||||
import { ActivityMessage } from './ActivityMessage'
|
||||
|
||||
import type { ActivityAction } from '../../hooks/useActivities'
|
||||
import type { Activity } from '../../models/Activity'
|
||||
|
||||
interface ActivityCenterProps {
|
||||
activities: Activity[]
|
||||
setShowActivityCenter: (val: boolean) => void
|
||||
activityDispatch: React.Dispatch<ActivityAction>
|
||||
}
|
||||
|
||||
export function ActivityCenter({
|
||||
activities,
|
||||
setShowActivityCenter,
|
||||
activityDispatch,
|
||||
}: ActivityCenterProps) {
|
||||
const { contacts } = useMessengerContext()
|
||||
|
||||
const shownActivities = useMemo(
|
||||
() =>
|
||||
activities.filter(
|
||||
activity => !contacts?.[activity.user]?.blocked ?? true
|
||||
),
|
||||
[contacts, activities]
|
||||
)
|
||||
|
||||
const [hideRead, setHideRead] = useState(false)
|
||||
|
||||
const [filter, setFilter] = useState('')
|
||||
|
||||
const filteredActivities = shownActivities.filter(activity =>
|
||||
filter
|
||||
? activity.type === filter
|
||||
: hideRead
|
||||
? activity.isRead !== true
|
||||
: activity
|
||||
)
|
||||
|
||||
return (
|
||||
<ActivityBlock>
|
||||
<ActivityFilter>
|
||||
<FlexDiv>
|
||||
<FilterBtn onClick={() => setFilter('')}>All</FilterBtn>
|
||||
<FilterBtn onClick={() => setFilter('mention')}>Mentions</FilterBtn>
|
||||
<FilterBtn onClick={() => setFilter('reply')}>Replies</FilterBtn>
|
||||
<FilterBtn onClick={() => setFilter('request')}>
|
||||
Contact requests
|
||||
</FilterBtn>
|
||||
</FlexDiv>
|
||||
<Btns>
|
||||
<BtnWrapper>
|
||||
<ActivityBtn
|
||||
onClick={() => activityDispatch({ type: 'setAllAsRead' })}
|
||||
>
|
||||
<ReadIcon />
|
||||
</ActivityBtn>
|
||||
<Tooltip tip="Mark all as Read" />
|
||||
</BtnWrapper>
|
||||
<BtnWrapper>
|
||||
<ActivityBtn onClick={() => setHideRead(!hideRead)}>
|
||||
{hideRead ? <ShowIcon /> : <HideIcon />}
|
||||
</ActivityBtn>
|
||||
<Tooltip tip={hideRead ? 'Show read' : 'Hide read'} />
|
||||
</BtnWrapper>
|
||||
</Btns>
|
||||
</ActivityFilter>
|
||||
{filteredActivities.length > 0 ? (
|
||||
<Activities>
|
||||
{filteredActivities.map(activity => (
|
||||
<ActivityMessage
|
||||
key={activity.id}
|
||||
activity={activity}
|
||||
setShowActivityCenter={setShowActivityCenter}
|
||||
activityDispatch={activityDispatch}
|
||||
/>
|
||||
))}
|
||||
</Activities>
|
||||
) : (
|
||||
<EmptyActivities>Notifications will appear here</EmptyActivities>
|
||||
)}
|
||||
</ActivityBlock>
|
||||
)
|
||||
}
|
||||
|
||||
const ActivityBlock = styled.div`
|
||||
width: 600px;
|
||||
height: 770px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: ${({ theme }) => theme.bodyBackgroundColor};
|
||||
box-shadow: 0px 12px 24px rgba(0, 34, 51, 0.1);
|
||||
border-radius: 8px;
|
||||
position: absolute;
|
||||
top: calc(100% + 4px);
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
`
|
||||
|
||||
const ActivityFilter = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 13px 16px;
|
||||
`
|
||||
|
||||
export const FlexDiv = styled.div`
|
||||
display: flex;
|
||||
`
|
||||
|
||||
const FilterBtn = styled.button`
|
||||
${buttonTransparentStyles}
|
||||
|
||||
& + & {
|
||||
margin-left: 8px;
|
||||
}
|
||||
`
|
||||
|
||||
const BtnWrapper = styled.div`
|
||||
position: relative;
|
||||
|
||||
&:hover > div {
|
||||
visibility: visible;
|
||||
}
|
||||
`
|
||||
|
||||
export const ActivityBtn = styled.button`
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 8px;
|
||||
align-self: center;
|
||||
|
||||
&:hover {
|
||||
background: ${({ theme }) => theme.buttonBgHover};
|
||||
}
|
||||
|
||||
&.read {
|
||||
&:hover {
|
||||
background: ${({ theme }) => theme.bodyBackgroundColor};
|
||||
}
|
||||
}
|
||||
|
||||
&.accept {
|
||||
&:hover {
|
||||
background: rgba(78, 188, 96, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
&.decline {
|
||||
&:hover {
|
||||
background: rgba(255, 45, 85, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
& + & {
|
||||
margin-left: 8px;
|
||||
}
|
||||
`
|
||||
|
||||
const Activities = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
`
|
||||
|
||||
const EmptyActivities = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
color: ${({ theme }) => theme.secondary};
|
||||
`
|
||||
|
||||
const Btns = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`
|
|
@ -1,389 +0,0 @@
|
|||
// @ts-nocheck
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react'
|
||||
|
||||
import styled from 'styled-components'
|
||||
|
||||
import { useMessengerContext } from '../../contexts/messengerProvider'
|
||||
import { useModal } from '../../contexts/modalProvider'
|
||||
import { useScrollToMessage } from '../../contexts/scrollProvider'
|
||||
import { useClickOutside } from '../../hooks/useClickOutside'
|
||||
import { equalDate } from '../../utils/equalDate'
|
||||
import { DownloadButton } from '../Buttons/DownloadButton'
|
||||
import { Mention } from '../Chat-legacy/ChatMessageContent'
|
||||
import { Logo } from '../CommunityIdentity'
|
||||
import { ContactMenu } from '../Form/ContactMenu'
|
||||
import { Tooltip } from '../Form/Tooltip'
|
||||
import { CheckIcon } from '../Icons/CheckIcon'
|
||||
import { ClearSvg } from '../Icons/ClearIcon'
|
||||
import { CommunityIcon } from '../Icons/CommunityIcon'
|
||||
import { GroupIcon } from '../Icons/GroupIcon'
|
||||
import { MoreIcon } from '../Icons/MoreIcon'
|
||||
import { ReadMessageIcon } from '../Icons/ReadMessageIcon'
|
||||
import { ReplyIcon } from '../Icons/ReplyActivityIcon'
|
||||
import { UntrustworthIcon } from '../Icons/UntrustworthIcon'
|
||||
import { UserIcon } from '../Icons/UserIcon'
|
||||
import {
|
||||
ContentWrapper,
|
||||
DateSeparator,
|
||||
MessageHeaderWrapper,
|
||||
MessageOuterWrapper,
|
||||
MessageText,
|
||||
TimeWrapper,
|
||||
UserAddress,
|
||||
UserName,
|
||||
UserNameWrapper,
|
||||
} from '../Messages/Styles'
|
||||
import { ProfileModalName } from '../Modals/ProfileModal'
|
||||
import { textMediumStyles, textSmallStyles } from '../Text'
|
||||
import { ActivityBtn, FlexDiv } from './ActivityCenter'
|
||||
|
||||
import type { ActivityAction } from '../../hooks/useActivities'
|
||||
import type { Activity } from '../../models/Activity'
|
||||
|
||||
const today = new Date()
|
||||
|
||||
type ActivityMessageProps = {
|
||||
activity: Activity
|
||||
setShowActivityCenter: (val: boolean) => void
|
||||
activityDispatch: React.Dispatch<ActivityAction>
|
||||
}
|
||||
|
||||
export function ActivityMessage({
|
||||
activity,
|
||||
setShowActivityCenter,
|
||||
activityDispatch,
|
||||
}: ActivityMessageProps) {
|
||||
const { contacts, channelsDispatch } = useMessengerContext()
|
||||
const scroll = useScrollToMessage()
|
||||
const { setModal } = useModal(ProfileModalName)
|
||||
const showChannel = () => {
|
||||
'channel' in activity &&
|
||||
channelsDispatch({ type: 'ChangeActive', payload: activity.channel.id }),
|
||||
setShowActivityCenter(false)
|
||||
}
|
||||
|
||||
const [showMenu, setShowMenu] = useState(false)
|
||||
|
||||
const type = activity.type
|
||||
|
||||
const contact = useMemo(
|
||||
() => contacts[activity.user],
|
||||
[activity.user, contacts]
|
||||
)
|
||||
|
||||
const [elements, setElements] = useState<
|
||||
(string | React.ReactElement | undefined)[]
|
||||
>(['message' in activity ? activity.message?.content : undefined])
|
||||
|
||||
useEffect(() => {
|
||||
if ('message' in activity) {
|
||||
const split = activity.message?.content.split(' ')
|
||||
const newSplit = split.flatMap((element, idx) => {
|
||||
if (element.startsWith('@')) {
|
||||
return [
|
||||
<Mention
|
||||
key={idx}
|
||||
id={element}
|
||||
setMentioned={() => true}
|
||||
className="activity"
|
||||
/>,
|
||||
' ',
|
||||
]
|
||||
}
|
||||
return [element, ' ']
|
||||
})
|
||||
newSplit.pop()
|
||||
setElements(newSplit)
|
||||
}
|
||||
}, [activity])
|
||||
|
||||
const ref = useRef(null)
|
||||
useClickOutside(ref, () => setShowMenu(false))
|
||||
|
||||
return (
|
||||
<MessageOuterWrapper>
|
||||
<ActivityDate>
|
||||
{equalDate(activity.date, today)
|
||||
? 'Today'
|
||||
: activity.date.toLocaleDateString()}
|
||||
</ActivityDate>
|
||||
|
||||
<MessageWrapper className={`${!activity.isRead && 'unread'}`}>
|
||||
<>
|
||||
<UserIcon />
|
||||
<ActivityContent>
|
||||
<MessageHeaderWrapper>
|
||||
<UserNameWrapper>
|
||||
<ActivityUserName
|
||||
onClick={() => {
|
||||
setModal({
|
||||
id: activity.user,
|
||||
renamingState: false,
|
||||
requestState: false,
|
||||
})
|
||||
}}
|
||||
>
|
||||
{' '}
|
||||
{contact?.customName ?? activity.user.slice(0, 10)}
|
||||
</ActivityUserName>
|
||||
{contact?.customName && (
|
||||
<UserAddress>
|
||||
{activity.user.slice(0, 5)}...{activity.user.slice(-3)}
|
||||
</UserAddress>
|
||||
)}
|
||||
{contact.isUntrustworthy && <UntrustworthIcon />}
|
||||
</UserNameWrapper>
|
||||
<TimeWrapper>
|
||||
{activity.date.toLocaleString('en-US', {
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
hour12: true,
|
||||
})}
|
||||
</TimeWrapper>
|
||||
</MessageHeaderWrapper>
|
||||
{type === 'request' && (
|
||||
<ContextHeading>
|
||||
Contact request
|
||||
{activity.requestType === 'outcome'
|
||||
? ` to ${activity.user.slice(0, 10)}`
|
||||
: ': '}
|
||||
</ContextHeading>
|
||||
)}
|
||||
{type === 'invitation' && (
|
||||
<FlexDiv>
|
||||
<ContextHeading>{`Invited you to join a community `}</ContextHeading>
|
||||
<Tag>
|
||||
<CommunityIcon width={17} height={16} />
|
||||
<CommunityLogo
|
||||
style={{
|
||||
backgroundImage: activity.invitation?.icon
|
||||
? `url(${activity.invitation?.icon}`
|
||||
: '',
|
||||
}}
|
||||
>
|
||||
{activity.invitation?.icon === undefined &&
|
||||
activity.invitation?.name.slice(0, 1).toUpperCase()}
|
||||
</CommunityLogo>
|
||||
<span>{activity.invitation?.name}</span>
|
||||
</Tag>
|
||||
</FlexDiv>
|
||||
)}
|
||||
<ActivityText>
|
||||
{'message' in activity && activity.message?.content && (
|
||||
// TODO: Check if broken (was a div)
|
||||
<button
|
||||
onClick={() => {
|
||||
scroll(activity.message, activity.channel.id)
|
||||
setShowActivityCenter(false)
|
||||
}}
|
||||
>
|
||||
{elements.map(el => el)}
|
||||
</button>
|
||||
)}
|
||||
{activity.type === 'request' &&
|
||||
activity.requestType === 'income' &&
|
||||
activity.request}
|
||||
</ActivityText>
|
||||
{type === 'mention' &&
|
||||
activity.channel &&
|
||||
activity.channel.type !== 'dm' && (
|
||||
<Tag onClick={showChannel}>
|
||||
{activity.channel.type === 'group' ? <GroupIcon /> : '#'}{' '}
|
||||
<span>{` ${activity.channel.name.slice(0, 10)}`}</span>
|
||||
</Tag>
|
||||
)}
|
||||
{type === 'reply' && activity.quote && (
|
||||
<ReplyWrapper>
|
||||
{activity.quote.image && (
|
||||
<ContextHeading>Posted an image in</ContextHeading>
|
||||
)}
|
||||
<Tag onClick={showChannel}>
|
||||
<ReplyIcon /> <span>{activity.quote.content}</span>
|
||||
</Tag>
|
||||
</ReplyWrapper>
|
||||
)}
|
||||
{type === 'invitation' && (
|
||||
<InviteDiv>
|
||||
<ContextHeading>{`To access other communities, `}</ContextHeading>
|
||||
<DownloadButton className="activity" />
|
||||
</InviteDiv>
|
||||
)}
|
||||
</ActivityContent>
|
||||
</>
|
||||
{type === 'request' &&
|
||||
!activity.status &&
|
||||
activity.requestType === 'income' && (
|
||||
<>
|
||||
<ActivityBtn
|
||||
onClick={() => {
|
||||
activityDispatch({
|
||||
type: 'setStatus',
|
||||
payload: { id: activity.id, status: 'accepted' },
|
||||
})
|
||||
}}
|
||||
className="accept"
|
||||
>
|
||||
<CheckIcon width={20} height={20} className="accept" />
|
||||
</ActivityBtn>
|
||||
<ActivityBtn
|
||||
onClick={() => {
|
||||
activityDispatch({
|
||||
type: 'setStatus',
|
||||
payload: { id: activity.id, status: 'declined' },
|
||||
})
|
||||
}}
|
||||
className="decline"
|
||||
>
|
||||
<ClearSvg width={20} height={20} className="decline" />
|
||||
</ActivityBtn>
|
||||
<ActivityBtn
|
||||
onClick={() => {
|
||||
setShowMenu(e => !e)
|
||||
}}
|
||||
ref={ref}
|
||||
>
|
||||
{showMenu && (
|
||||
<ContactMenu id={activity.user} setShowMenu={setShowMenu} />
|
||||
)}
|
||||
<MoreIcon />
|
||||
</ActivityBtn>
|
||||
</>
|
||||
)}
|
||||
{type === 'request' && activity.status === 'accepted' && (
|
||||
<RequestStatus className="accepted">Accepted</RequestStatus>
|
||||
)}
|
||||
{type === 'request' && activity.status === 'declined' && (
|
||||
<RequestStatus className="declined">Declined</RequestStatus>
|
||||
)}
|
||||
{type === 'request' && activity.status === 'sent' && (
|
||||
<RequestStatus>Sent</RequestStatus>
|
||||
)}
|
||||
{(type === 'mention' || type === 'reply') && (
|
||||
<BtnWrapper>
|
||||
<ActivityBtn
|
||||
onClick={() =>
|
||||
activityDispatch({ type: 'setAsRead', payload: activity.id })
|
||||
}
|
||||
className={`${activity.isRead && 'read'}`}
|
||||
>
|
||||
<ReadMessageIcon isRead={activity.isRead} />
|
||||
</ActivityBtn>
|
||||
<Tooltip tip="Mark Read" className="read" />
|
||||
</BtnWrapper>
|
||||
)}
|
||||
</MessageWrapper>
|
||||
</MessageOuterWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
const InviteDiv = styled.div`
|
||||
display: flex;
|
||||
margin-top: -4px;
|
||||
`
|
||||
|
||||
const BtnWrapper = styled.div`
|
||||
position: relative;
|
||||
|
||||
&:hover > div {
|
||||
visibility: visible;
|
||||
}
|
||||
`
|
||||
|
||||
const ActivityDate = styled(DateSeparator)`
|
||||
justify-content: flex-start;
|
||||
padding: 8px 16px;
|
||||
margin: 0;
|
||||
`
|
||||
|
||||
const MessageWrapper = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 8px 16px;
|
||||
|
||||
&.unread {
|
||||
background: ${({ theme }) => theme.buttonBgHover};
|
||||
}
|
||||
`
|
||||
|
||||
const ActivityText = styled(MessageText)`
|
||||
white-space: unset;
|
||||
margin-bottom: 8px;
|
||||
`
|
||||
|
||||
const Tag = styled.div`
|
||||
width: fit-content;
|
||||
max-width: 200px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
border: 1px solid ${({ theme }) => theme.secondary};
|
||||
border-radius: 11px;
|
||||
padding: 0 6px;
|
||||
cursor: pointer;
|
||||
|
||||
font-weight: 500;
|
||||
color: ${({ theme }) => theme.secondary};
|
||||
${textSmallStyles}
|
||||
|
||||
& > span {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
`
|
||||
|
||||
const ContextHeading = styled.p`
|
||||
font-style: italic;
|
||||
color: ${({ theme }) => theme.secondary};
|
||||
flex-shrink: 0;
|
||||
white-space: pre-wrap;
|
||||
${textMediumStyles}
|
||||
`
|
||||
|
||||
const RequestStatus = styled.p`
|
||||
font-weight: 500;
|
||||
align-self: center;
|
||||
text-align: end;
|
||||
color: ${({ theme }) => theme.secondary};
|
||||
${textSmallStyles}
|
||||
|
||||
&.accepted {
|
||||
color: ${({ theme }) => theme.greenColor};
|
||||
}
|
||||
|
||||
&.declined {
|
||||
color: ${({ theme }) => theme.redColor};
|
||||
}
|
||||
`
|
||||
|
||||
const ActivityContent = styled(ContentWrapper)`
|
||||
max-width: calc(100% - 80px);
|
||||
flex: 1;
|
||||
`
|
||||
|
||||
const ActivityUserName = styled(UserName)`
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
`
|
||||
|
||||
const ReplyWrapper = styled.div`
|
||||
max-width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
& > p {
|
||||
margin-right: 4px;
|
||||
}
|
||||
`
|
||||
|
||||
const CommunityLogo = styled(Logo)`
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 0 2px 0 4px;
|
||||
|
||||
${textSmallStyles}
|
||||
`
|
|
@ -5,7 +5,7 @@ import { Dialog, Grid, Text } from '~/src/system'
|
|||
|
||||
// TODO: Add wallet integration
|
||||
export const ConnectWalletDialog = () => {
|
||||
const [wallet, setWallet] = useState<'coinbase' | undefined>()
|
||||
const [, setWallet] = useState<'coinbase' | undefined>()
|
||||
|
||||
// TODO: Add wallet logos
|
||||
return (
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
import React from 'react'
|
||||
|
||||
import { CreateProfileDialog } from '~/src/components/create-profile-dialog'
|
||||
import { useLocalStorage } from '~/src/hooks/use-local-storage'
|
||||
// import { CreateProfileDialog } from '~/src/components/create-profile-dialog'
|
||||
// import { useLocalStorage } from '~/src/hooks/use-local-storage'
|
||||
import { useAccount } from '~/src/protocol'
|
||||
import { Button, Flex } from '~/src/system'
|
||||
import { DialogTrigger } from '~/src/system/dialog'
|
||||
// import { DialogTrigger } from '~/src/system/dialog'
|
||||
import { Grid } from '~/src/system/grid'
|
||||
import { Heading } from '~/src/system/heading'
|
||||
|
||||
// import { ConnectWalletDialog } from './connect-wallet-dialog'
|
||||
// import { SyncStatusProfileDialog } from './sync-status-profile-dialog'
|
||||
import { ThrowawayProfileFoundDialog } from './throwaway-profile-found-dialog'
|
||||
// import { ThrowawayProfileFoundDialog } from './throwaway-profile-found-dialog'
|
||||
|
||||
export const GetStarted = () => {
|
||||
const [throwawayProfile] = useLocalStorage('cipherIdentityt', null)
|
||||
// const [throwawayProfile] = useLocalStorage('cipherIdentityt', null)
|
||||
|
||||
const handleSkip = () => {
|
||||
// TODO: Add skip logic
|
||||
}
|
||||
// const handleSkip = () => {
|
||||
// // TODO: Add skip logic
|
||||
// }
|
||||
|
||||
const { account, createAccount } = useAccount()
|
||||
const { createAccount } = useAccount()
|
||||
|
||||
return (
|
||||
<Flex direction="column" align="center" gap={5} css={{ padding: '30px 0' }}>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-nocheck
|
||||
import React from 'react'
|
||||
|
||||
|
|
|
@ -19,63 +19,6 @@ export type Reactions = {
|
|||
}
|
||||
}
|
||||
|
||||
interface BaseMessage {
|
||||
id: string
|
||||
type: 'text' | 'image' | 'image-text'
|
||||
contact: {
|
||||
name: string
|
||||
imageUrl?: string
|
||||
}
|
||||
owner: boolean
|
||||
pinned: boolean
|
||||
mention: boolean
|
||||
reply?: TextReply | ImageReply | ImageTextReply
|
||||
reactions: Reactions
|
||||
}
|
||||
|
||||
interface TextMessage extends BaseMessage {
|
||||
type: 'text'
|
||||
text: string
|
||||
}
|
||||
|
||||
interface ImageMessage extends BaseMessage {
|
||||
type: 'image'
|
||||
imageUrl: string
|
||||
}
|
||||
interface ImageTextMessage extends BaseMessage {
|
||||
type: 'image-text'
|
||||
text: string
|
||||
imageUrl: string
|
||||
}
|
||||
|
||||
// export type Message = TextMessage | ImageMessage | ImageTextMessage
|
||||
|
||||
interface BaseReply {
|
||||
type: Message['type']
|
||||
contact: {
|
||||
name: string
|
||||
imageUrl?: string
|
||||
}
|
||||
}
|
||||
|
||||
interface TextReply extends BaseReply {
|
||||
type: 'text'
|
||||
text: string
|
||||
}
|
||||
|
||||
interface ImageReply extends BaseReply {
|
||||
type: 'image'
|
||||
imageUrl: string
|
||||
}
|
||||
|
||||
interface ImageTextReply extends BaseReply {
|
||||
type: 'image-text'
|
||||
text: string
|
||||
imageUrl: string
|
||||
}
|
||||
|
||||
export type Reply = TextReply | ImageReply | ImageTextReply
|
||||
|
||||
export type { Message }
|
||||
|
||||
interface Result {
|
||||
|
|
|
@ -2,9 +2,8 @@ import React from 'react'
|
|||
|
||||
import { useChatContext } from '~/src/contexts/chat-context'
|
||||
import { CrossIcon } from '~/src/icons/cross-icon'
|
||||
import { ReplyIcon } from '~/src/icons/reply-icon'
|
||||
import { styled } from '~/src/styles/config'
|
||||
import { Flex, Icon, IconButton, Image, Text } from '~/src/system'
|
||||
import { Flex, IconButton, Image, Text } from '~/src/system'
|
||||
|
||||
import type { Member, Message } from '~/src/protocol'
|
||||
|
||||
|
|
|
@ -6,9 +6,7 @@ interface Props {
|
|||
name?: string
|
||||
}
|
||||
|
||||
const EmojiHash = (props: Props) => {
|
||||
const { name } = props
|
||||
|
||||
const EmojiHash = () => {
|
||||
return (
|
||||
<Base>
|
||||
🎩🍞🥑🦍🌈📡
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
"lint": {
|
||||
"outputs": []
|
||||
},
|
||||
"check": {
|
||||
"typecheck": {
|
||||
"outputs": []
|
||||
},
|
||||
"test": {
|
||||
|
|
49
yarn.lock
49
yarn.lock
|
@ -2104,7 +2104,7 @@
|
|||
semver "^7.3.5"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/utils@5.12.1", "@typescript-eslint/utils@^5.10.0":
|
||||
"@typescript-eslint/utils@5.12.1":
|
||||
version "5.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.12.1.tgz#447c24a05d9c33f9c6c64cb48f251f2371eef920"
|
||||
integrity sha512-Qq9FIuU0EVEsi8fS6pG+uurbhNTtoYr4fq8tKjBupsK5Bgbk2I32UGm0Sh+WOyjOPgo/5URbxxSNV6HYsxV4MQ==
|
||||
|
@ -3248,14 +3248,6 @@ eslint-module-utils@^2.7.2:
|
|||
debug "^3.2.7"
|
||||
find-up "^2.1.0"
|
||||
|
||||
eslint-plugin-es@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893"
|
||||
integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==
|
||||
dependencies:
|
||||
eslint-utils "^2.0.0"
|
||||
regexpp "^3.0.0"
|
||||
|
||||
eslint-plugin-eslint-comments@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz#9e1cd7b4413526abb313933071d7aba05ca12ffa"
|
||||
|
@ -3283,13 +3275,6 @@ eslint-plugin-import@^2.25.2:
|
|||
resolve "^1.20.0"
|
||||
tsconfig-paths "^3.12.0"
|
||||
|
||||
eslint-plugin-jest@^26.1.1:
|
||||
version "26.1.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-26.1.1.tgz#7176dd745ef8bca3070263f62cdf112f2dfc9aa1"
|
||||
integrity sha512-HRKOuPi5ADhza4ZBK5ufyNXy28bXXkib87w+pQqdvBhSTsamndh6sIAKPAUl8y0/n9jSWBdTPslrwtKWqkp8dA==
|
||||
dependencies:
|
||||
"@typescript-eslint/utils" "^5.10.0"
|
||||
|
||||
eslint-plugin-jsx-a11y@^6.5.1:
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz#cdbf2df901040ca140b6ec14715c988889c2a6d8"
|
||||
|
@ -3308,18 +3293,6 @@ eslint-plugin-jsx-a11y@^6.5.1:
|
|||
language-tags "^1.0.5"
|
||||
minimatch "^3.0.4"
|
||||
|
||||
eslint-plugin-node@^11.1.0:
|
||||
version "11.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d"
|
||||
integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==
|
||||
dependencies:
|
||||
eslint-plugin-es "^3.0.0"
|
||||
eslint-utils "^2.0.0"
|
||||
ignore "^5.1.1"
|
||||
minimatch "^3.0.4"
|
||||
resolve "^1.10.1"
|
||||
semver "^6.1.0"
|
||||
|
||||
eslint-plugin-react-hooks@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172"
|
||||
|
@ -3366,13 +3339,6 @@ eslint-scope@^7.1.1:
|
|||
esrecurse "^4.3.0"
|
||||
estraverse "^5.2.0"
|
||||
|
||||
eslint-utils@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
|
||||
integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==
|
||||
dependencies:
|
||||
eslint-visitor-keys "^1.1.0"
|
||||
|
||||
eslint-utils@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672"
|
||||
|
@ -3380,11 +3346,6 @@ eslint-utils@^3.0.0:
|
|||
dependencies:
|
||||
eslint-visitor-keys "^2.0.0"
|
||||
|
||||
eslint-visitor-keys@^1.1.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
|
||||
integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
|
||||
|
||||
eslint-visitor-keys@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
|
||||
|
@ -3944,7 +3905,7 @@ ignore@^4.0.6:
|
|||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
|
||||
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
|
||||
|
||||
ignore@^5.0.5, ignore@^5.1.1, ignore@^5.1.8, ignore@^5.2.0:
|
||||
ignore@^5.0.5, ignore@^5.1.8, ignore@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
|
||||
integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==
|
||||
|
@ -5864,7 +5825,7 @@ regexp.prototype.flags@^1.3.1:
|
|||
call-bind "^1.0.2"
|
||||
define-properties "^1.1.3"
|
||||
|
||||
regexpp@^3.0.0, regexpp@^3.2.0:
|
||||
regexpp@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
|
||||
integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
|
||||
|
@ -5900,7 +5861,7 @@ resolve-from@^4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
||||
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
|
||||
|
||||
resolve@^1.10.1, resolve@^1.20.0:
|
||||
resolve@^1.20.0:
|
||||
version "1.22.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198"
|
||||
integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==
|
||||
|
@ -6022,7 +5983,7 @@ semver@^5.7.0, semver@^5.7.1:
|
|||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||
|
||||
semver@^6.1.0, semver@^6.3.0:
|
||||
semver@^6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||
|
|
Loading…
Reference in New Issue