Implement Web versions of the bottom sheet, toast, and progress circle
parent
af55a89758
commit
041bfa22a9
|
@ -34,6 +34,7 @@
|
||||||
"mobx-react-lite": "^3.4.0",
|
"mobx-react-lite": "^3.4.0",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
|
"react-circular-progressbar": "^2.1.0",
|
||||||
"react-dom": "17.0.2",
|
"react-dom": "17.0.2",
|
||||||
"react-native": "0.68.2",
|
"react-native": "0.68.2",
|
||||||
"react-native-gesture-handler": "^2.5.0",
|
"react-native-gesture-handler": "^2.5.0",
|
||||||
|
|
|
@ -11,6 +11,45 @@
|
||||||
body { overflow: hidden; }
|
body { overflow: hidden; }
|
||||||
/* These styles make the root element full-height */
|
/* These styles make the root element full-height */
|
||||||
#root { display:flex; height:100%; }
|
#root { display:flex; height:100%; }
|
||||||
|
|
||||||
|
/* These styles are for src/view/com/modals/WebModal */
|
||||||
|
div[data-modal-overlay] {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background: #0004;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
div[data-modal-container] {
|
||||||
|
position: fixed;
|
||||||
|
top: 20vh;
|
||||||
|
left: calc(50vw - 300px);
|
||||||
|
width: 600px;
|
||||||
|
padding: 20px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 5px 10px #0005;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* These styles are for src/view/com/util/Toast */
|
||||||
|
div[data-toast-container] {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 5vh;
|
||||||
|
right: 5vh;
|
||||||
|
width: 350px;
|
||||||
|
padding: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 5px 10px #0005;
|
||||||
|
}
|
||||||
|
div[data-toast-container] > div {
|
||||||
|
font-size: 18px;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import React, {useState, useEffect} from 'react'
|
import React, {useState, useEffect} from 'react'
|
||||||
import {RootSiblingParent} from 'react-native-root-siblings'
|
|
||||||
import {GestureHandlerRootView} from 'react-native-gesture-handler'
|
|
||||||
import * as view from './view/index'
|
import * as view from './view/index'
|
||||||
import {RootStoreModel, setupState, RootStoreProvider} from './state'
|
import {RootStoreModel, setupState, RootStoreProvider} from './state'
|
||||||
import * as Routes from './view/routes'
|
import * as Routes from './view/routes'
|
||||||
|
import Toast from './view/com/util/Toast'
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [rootStore, setRootStore] = useState<RootStoreModel | undefined>(
|
const [rootStore, setRootStore] = useState<RootStoreModel | undefined>(
|
||||||
|
@ -22,13 +21,10 @@ function App() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GestureHandlerRootView style={{flex: 1}}>
|
|
||||||
<RootSiblingParent>
|
|
||||||
<RootStoreProvider value={rootStore}>
|
<RootStoreProvider value={rootStore}>
|
||||||
<Routes.Root />
|
<Routes.Root />
|
||||||
|
<Toast.ToastContainer />
|
||||||
</RootStoreProvider>
|
</RootStoreProvider>
|
||||||
</RootSiblingParent>
|
|
||||||
</GestureHandlerRootView>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ export async function unrepost(adx: AdxClient, user: string, uri: string) {
|
||||||
return numDels > 0
|
return numDels > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
type WherePred = (record: GetRecordResponseValidated) => Boolean
|
type WherePred = (_record: GetRecordResponseValidated) => Boolean
|
||||||
async function deleteWhere(
|
async function deleteWhere(
|
||||||
coll: AdxRepoCollectionClient,
|
coll: AdxRepoCollectionClient,
|
||||||
schema: SchemaOpt,
|
schema: SchemaOpt,
|
||||||
|
@ -115,7 +115,7 @@ async function deleteWhere(
|
||||||
return toDelete.length
|
return toDelete.length
|
||||||
}
|
}
|
||||||
|
|
||||||
type IterateAllCb = (record: GetRecordResponseValidated) => void
|
type IterateAllCb = (_record: GetRecordResponseValidated) => void
|
||||||
async function iterateAll(
|
async function iterateAll(
|
||||||
coll: AdxRepoCollectionClient,
|
coll: AdxRepoCollectionClient,
|
||||||
schema: SchemaOpt,
|
schema: SchemaOpt,
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import React, {useState, forwardRef, useImperativeHandle} from 'react'
|
import React, {useState, forwardRef, useImperativeHandle} from 'react'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {KeyboardAvoidingView, StyleSheet, TextInput, View} from 'react-native'
|
import {KeyboardAvoidingView, StyleSheet, TextInput, View} from 'react-native'
|
||||||
import Toast from 'react-native-root-toast'
|
import Toast from '../util/Toast'
|
||||||
// @ts-ignore no type definition -prf
|
import ProgressCircle from '../util/ProgressCircle'
|
||||||
import ProgressCircle from 'react-native-progress/Circle'
|
|
||||||
import {useStores} from '../../../state'
|
import {useStores} from '../../../state'
|
||||||
import {s} from '../../lib/styles'
|
import {s} from '../../lib/styles'
|
||||||
import * as apilib from '../../../state/lib/api'
|
import * as apilib from '../../../state/lib/api'
|
||||||
|
@ -12,15 +11,14 @@ const MAX_TEXT_LENGTH = 256
|
||||||
const WARNING_TEXT_LENGTH = 200
|
const WARNING_TEXT_LENGTH = 200
|
||||||
const DANGER_TEXT_LENGTH = 255
|
const DANGER_TEXT_LENGTH = 255
|
||||||
|
|
||||||
export const Composer = observer(
|
export const Composer = forwardRef(function Composer(
|
||||||
forwardRef(function Composer(
|
|
||||||
{
|
{
|
||||||
replyTo,
|
replyTo,
|
||||||
}: {
|
}: {
|
||||||
replyTo: string | undefined
|
replyTo: string | undefined
|
||||||
},
|
},
|
||||||
ref,
|
ref,
|
||||||
) {
|
) {
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const [text, setText] = useState('')
|
const [text, setText] = useState('')
|
||||||
|
|
||||||
|
@ -63,9 +61,7 @@ export const Composer = observer(
|
||||||
scrollEnabled
|
scrollEnabled
|
||||||
onChangeText={text => onChangeText(text)}
|
onChangeText={text => onChangeText(text)}
|
||||||
value={text}
|
value={text}
|
||||||
placeholder={
|
placeholder={replyTo ? 'Write your reply' : "What's new in the scene?"}
|
||||||
replyTo ? 'Write your reply' : "What's new in the scene?"
|
|
||||||
}
|
|
||||||
style={styles.textInput}
|
style={styles.textInput}
|
||||||
/>
|
/>
|
||||||
<View style={[s.flexRow, s.pt10, s.pb10, s.pr5]}>
|
<View style={[s.flexRow, s.pt10, s.pb10, s.pr5]}>
|
||||||
|
@ -79,8 +75,7 @@ export const Composer = observer(
|
||||||
</View>
|
</View>
|
||||||
</KeyboardAvoidingView>
|
</KeyboardAvoidingView>
|
||||||
)
|
)
|
||||||
}),
|
})
|
||||||
)
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
outer: {
|
outer: {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {Text, View, FlatList} from 'react-native'
|
||||||
import {OnNavigateContent} from '../../routes/types'
|
import {OnNavigateContent} from '../../routes/types'
|
||||||
import {FeedViewModel, FeedViewItemModel} from '../../../state/models/feed-view'
|
import {FeedViewModel, FeedViewItemModel} from '../../../state/models/feed-view'
|
||||||
import {FeedItem} from './FeedItem'
|
import {FeedItem} from './FeedItem'
|
||||||
import {ShareBottomSheet} from '../sheets/SharePost'
|
import {ShareModal} from '../modals/SharePost'
|
||||||
|
|
||||||
export const Feed = observer(function Feed({
|
export const Feed = observer(function Feed({
|
||||||
feed,
|
feed,
|
||||||
|
@ -13,7 +13,7 @@ export const Feed = observer(function Feed({
|
||||||
feed: FeedViewModel
|
feed: FeedViewModel
|
||||||
onNavigateContent: OnNavigateContent
|
onNavigateContent: OnNavigateContent
|
||||||
}) {
|
}) {
|
||||||
const shareSheetRef = useRef<{open: (uri: string) => void}>()
|
const shareSheetRef = useRef<{open: (_uri: string) => void}>()
|
||||||
|
|
||||||
const onPressShare = (uri: string) => {
|
const onPressShare = (uri: string) => {
|
||||||
shareSheetRef.current?.open(uri)
|
shareSheetRef.current?.open(uri)
|
||||||
|
@ -52,7 +52,7 @@ export const Feed = observer(function Feed({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{feed.isEmpty && <Text>This feed is empty!</Text>}
|
{feed.isEmpty && <Text>This feed is empty!</Text>}
|
||||||
<ShareBottomSheet ref={shareSheetRef} />
|
<ShareModal ref={shareSheetRef} />
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -16,7 +16,7 @@ export const FeedItem = observer(function FeedItem({
|
||||||
}: {
|
}: {
|
||||||
item: FeedViewItemModel
|
item: FeedViewItemModel
|
||||||
onNavigateContent: OnNavigateContent
|
onNavigateContent: OnNavigateContent
|
||||||
onPressShare: (uri: string) => void
|
onPressShare: (_uri: string) => void
|
||||||
}) {
|
}) {
|
||||||
const record = item.record as unknown as bsky.Post.Record
|
const record = item.record as unknown as bsky.Post.Record
|
||||||
|
|
||||||
|
|
|
@ -19,14 +19,11 @@ import Animated, {
|
||||||
interpolate,
|
interpolate,
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
import Toast from 'react-native-root-toast'
|
import Toast from '../util/Toast'
|
||||||
import Clipboard from '@react-native-clipboard/clipboard'
|
import Clipboard from '@react-native-clipboard/clipboard'
|
||||||
import {s} from '../../lib/styles'
|
import {s} from '../../lib/styles'
|
||||||
|
|
||||||
export const ShareBottomSheet = forwardRef(function ShareBottomSheet(
|
export const ShareModal = forwardRef(function ShareModal({}: {}, ref) {
|
||||||
{}: {},
|
|
||||||
ref,
|
|
||||||
) {
|
|
||||||
const [isOpen, setIsOpen] = useState<boolean>(false)
|
const [isOpen, setIsOpen] = useState<boolean>(false)
|
||||||
const [uri, setUri] = useState<string>('')
|
const [uri, setUri] = useState<string>('')
|
||||||
const bottomSheetRef = useRef<BottomSheet>(null)
|
const bottomSheetRef = useRef<BottomSheet>(null)
|
||||||
|
@ -41,6 +38,9 @@ export const ShareBottomSheet = forwardRef(function ShareBottomSheet(
|
||||||
|
|
||||||
const onPressCopy = () => {
|
const onPressCopy = () => {
|
||||||
Clipboard.setString(uri)
|
Clipboard.setString(uri)
|
||||||
|
console.log('showing')
|
||||||
|
console.log(Toast)
|
||||||
|
console.log(Toast.show)
|
||||||
Toast.show('Link copied', {
|
Toast.show('Link copied', {
|
||||||
position: Toast.positions.TOP,
|
position: Toast.positions.TOP,
|
||||||
})
|
})
|
||||||
|
@ -56,7 +56,6 @@ export const ShareBottomSheet = forwardRef(function ShareBottomSheet(
|
||||||
}
|
}
|
||||||
|
|
||||||
const CustomBackdrop = ({animatedIndex, style}: BottomSheetBackdropProps) => {
|
const CustomBackdrop = ({animatedIndex, style}: BottomSheetBackdropProps) => {
|
||||||
console.log('hit!', animatedIndex.value)
|
|
||||||
// animated variables
|
// animated variables
|
||||||
const opacity = useAnimatedStyle(() => ({
|
const opacity = useAnimatedStyle(() => ({
|
||||||
opacity: interpolate(
|
opacity: interpolate(
|
|
@ -0,0 +1,57 @@
|
||||||
|
import React, {forwardRef, useState, useImperativeHandle} from 'react'
|
||||||
|
import {Button, StyleSheet, Text, TouchableOpacity, View} from 'react-native'
|
||||||
|
import {Modal} from './WebModal'
|
||||||
|
import Toast from '../util/Toast'
|
||||||
|
import {s} from '../../lib/styles'
|
||||||
|
|
||||||
|
export const ShareModal = forwardRef(function ShareModal({}: {}, ref) {
|
||||||
|
const [isOpen, setIsOpen] = useState<boolean>(false)
|
||||||
|
const [uri, setUri] = useState<string>('')
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
open(uri: string) {
|
||||||
|
console.log('sharing', uri)
|
||||||
|
setUri(uri)
|
||||||
|
setIsOpen(true)
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
|
const onPressCopy = () => {
|
||||||
|
// TODO
|
||||||
|
Toast.show('Link copied', {
|
||||||
|
position: Toast.positions.TOP,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const onClose = () => {
|
||||||
|
setIsOpen(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isOpen && (
|
||||||
|
<Modal onClose={onClose}>
|
||||||
|
<View>
|
||||||
|
<Text style={[s.textCenter, s.bold, s.mb10]}>Share this post</Text>
|
||||||
|
<Text style={[s.textCenter, s.mb10]}>{uri}</Text>
|
||||||
|
<Button title="Copy to clipboard" onPress={onPressCopy} />
|
||||||
|
<View style={s.p10}>
|
||||||
|
<TouchableOpacity onPress={onClose} style={styles.closeBtn}>
|
||||||
|
<Text style={s.textCenter}>Close</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
closeBtn: {
|
||||||
|
width: '100%',
|
||||||
|
borderColor: '#000',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 4,
|
||||||
|
padding: 10,
|
||||||
|
},
|
||||||
|
})
|
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
* Use this for the Web build only.
|
||||||
|
* It's intended to replace the BottomSheet.
|
||||||
|
*
|
||||||
|
* Note: the dataSet properties are used to leverage custom CSS in public/index.html
|
||||||
|
*/
|
||||||
|
import React from 'react'
|
||||||
|
// @ts-ignore no declarations available -prf
|
||||||
|
import {TouchableWithoutFeedback, View} from 'react-native-web'
|
||||||
|
|
||||||
|
type Props = {onClose: () => void}
|
||||||
|
export const Modal: React.FC<Props> = ({onClose, children}) => {
|
||||||
|
return (
|
||||||
|
<TouchableWithoutFeedback onPress={onClose}>
|
||||||
|
<View dataSet={{'modal-overlay': 1}}>
|
||||||
|
<View dataSet={{'modal-container': 1}}>{children}</View>
|
||||||
|
</View>
|
||||||
|
</TouchableWithoutFeedback>
|
||||||
|
)
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ import {
|
||||||
} from '../../../state/models/post-thread-view'
|
} from '../../../state/models/post-thread-view'
|
||||||
import {useStores} from '../../../state'
|
import {useStores} from '../../../state'
|
||||||
import {PostThreadItem} from './PostThreadItem'
|
import {PostThreadItem} from './PostThreadItem'
|
||||||
import {ShareBottomSheet} from '../sheets/SharePost'
|
import {ShareModal} from '../modals/SharePost'
|
||||||
import {s} from '../../lib/styles'
|
import {s} from '../../lib/styles'
|
||||||
|
|
||||||
const UPDATE_DELAY = 2e3 // wait 2s before refetching the thread for updates
|
const UPDATE_DELAY = 2e3 // wait 2s before refetching the thread for updates
|
||||||
|
@ -24,7 +24,7 @@ export const PostThread = observer(function PostThread({
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const [view, setView] = useState<PostThreadViewModel | undefined>()
|
const [view, setView] = useState<PostThreadViewModel | undefined>()
|
||||||
const [lastUpdate, setLastUpdate] = useState<number>(Date.now())
|
const [lastUpdate, setLastUpdate] = useState<number>(Date.now())
|
||||||
const shareSheetRef = useRef<{open: (uri: string) => void}>()
|
const shareSheetRef = useRef<{open: (_uri: string) => void}>()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (view?.params.uri === uri) {
|
if (view?.params.uri === uri) {
|
||||||
|
@ -94,7 +94,7 @@ export const PostThread = observer(function PostThread({
|
||||||
refreshing={view.isRefreshing}
|
refreshing={view.isRefreshing}
|
||||||
onRefresh={onRefresh}
|
onRefresh={onRefresh}
|
||||||
/>
|
/>
|
||||||
<ShareBottomSheet ref={shareSheetRef} />
|
<ShareModal ref={shareSheetRef} />
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -25,7 +25,7 @@ export const PostThreadItem = observer(function PostThreadItem({
|
||||||
}: {
|
}: {
|
||||||
item: PostThreadViewPostModel
|
item: PostThreadViewPostModel
|
||||||
onNavigateContent: OnNavigateContent
|
onNavigateContent: OnNavigateContent
|
||||||
onPressShare: (uri: string) => void
|
onPressShare: (_uri: string) => void
|
||||||
}) {
|
}) {
|
||||||
const record = item.record as unknown as bsky.Post.Record
|
const record = item.record as unknown as bsky.Post.Record
|
||||||
const hasEngagement = item.likeCount || item.repostCount
|
const hasEngagement = item.likeCount || item.repostCount
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
// @ts-ignore no type definition -prf
|
||||||
|
import ProgressCircle from 'react-native-progress/Circle'
|
||||||
|
export default ProgressCircle
|
|
@ -0,0 +1,20 @@
|
||||||
|
import {View} from 'react-native'
|
||||||
|
import {CircularProgressbar, buildStyles} from 'react-circular-progressbar'
|
||||||
|
|
||||||
|
const ProgressCircle = ({
|
||||||
|
color,
|
||||||
|
progress,
|
||||||
|
}: {
|
||||||
|
color?: string
|
||||||
|
progress: number
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<View style={{width: 20, height: 20}}>
|
||||||
|
<CircularProgressbar
|
||||||
|
value={progress * 100}
|
||||||
|
styles={buildStyles({pathColor: color || '#00f'})}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default ProgressCircle
|
|
@ -0,0 +1,2 @@
|
||||||
|
import Toast from 'react-native-root-toast'
|
||||||
|
export default Toast
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Note: the dataSet properties are used to leverage custom CSS in public/index.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, {useState, useEffect} from 'react'
|
||||||
|
// @ts-ignore no declarations available -prf
|
||||||
|
import {Text, View} from 'react-native-web'
|
||||||
|
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||||
|
|
||||||
|
interface ActiveToast {
|
||||||
|
text: string
|
||||||
|
}
|
||||||
|
type GlobalSetActiveToast = (_activeToast: ActiveToast | undefined) => void
|
||||||
|
|
||||||
|
// globals
|
||||||
|
// =
|
||||||
|
let globalSetActiveToast: GlobalSetActiveToast | undefined
|
||||||
|
let toastTimeout: NodeJS.Timeout | undefined
|
||||||
|
|
||||||
|
// components
|
||||||
|
// =
|
||||||
|
type ToastContainerProps = {}
|
||||||
|
const ToastContainer: React.FC<ToastContainerProps> = ({}) => {
|
||||||
|
const [activeToast, setActiveToast] = useState<ActiveToast | undefined>()
|
||||||
|
useEffect(() => {
|
||||||
|
globalSetActiveToast = (t: ActiveToast | undefined) => {
|
||||||
|
setActiveToast(t)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{activeToast && (
|
||||||
|
<View dataSet={{'toast-container': 1}}>
|
||||||
|
<FontAwesomeIcon icon="check" size={24} />
|
||||||
|
<Text>{activeToast.text}</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// exports
|
||||||
|
// =
|
||||||
|
export default {
|
||||||
|
show(text: string, _opts: any) {
|
||||||
|
console.log('TODO: toast', text)
|
||||||
|
if (toastTimeout) {
|
||||||
|
clearTimeout(toastTimeout)
|
||||||
|
}
|
||||||
|
globalSetActiveToast?.({text})
|
||||||
|
toastTimeout = setTimeout(() => {
|
||||||
|
globalSetActiveToast?.(undefined)
|
||||||
|
}, 2e3)
|
||||||
|
},
|
||||||
|
positions: {
|
||||||
|
TOP: 0,
|
||||||
|
},
|
||||||
|
durations: {
|
||||||
|
LONG: 0,
|
||||||
|
},
|
||||||
|
ToastContainer,
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import {library} from '@fortawesome/fontawesome-svg-core'
|
||||||
import {faArrowLeft} from '@fortawesome/free-solid-svg-icons/faArrowLeft'
|
import {faArrowLeft} from '@fortawesome/free-solid-svg-icons/faArrowLeft'
|
||||||
import {faBars} from '@fortawesome/free-solid-svg-icons/faBars'
|
import {faBars} from '@fortawesome/free-solid-svg-icons/faBars'
|
||||||
import {faBell} from '@fortawesome/free-solid-svg-icons/faBell'
|
import {faBell} from '@fortawesome/free-solid-svg-icons/faBell'
|
||||||
|
import {faCheck} from '@fortawesome/free-solid-svg-icons/faCheck'
|
||||||
import {faComment} from '@fortawesome/free-regular-svg-icons/faComment'
|
import {faComment} from '@fortawesome/free-regular-svg-icons/faComment'
|
||||||
import {faHeart} from '@fortawesome/free-regular-svg-icons/faHeart'
|
import {faHeart} from '@fortawesome/free-regular-svg-icons/faHeart'
|
||||||
import {faHeart as fasHeart} from '@fortawesome/free-solid-svg-icons/faHeart'
|
import {faHeart as fasHeart} from '@fortawesome/free-solid-svg-icons/faHeart'
|
||||||
|
@ -39,6 +40,7 @@ export function setup() {
|
||||||
faArrowLeft,
|
faArrowLeft,
|
||||||
faBars,
|
faBars,
|
||||||
faBell,
|
faBell,
|
||||||
|
faCheck,
|
||||||
faComment,
|
faComment,
|
||||||
faHeart,
|
faHeart,
|
||||||
fasHeart,
|
fasHeart,
|
||||||
|
|
|
@ -12,3 +12,5 @@ Paul's todo list
|
||||||
- Linking
|
- Linking
|
||||||
- Web linking
|
- Web linking
|
||||||
- App linking
|
- App linking
|
||||||
|
- Housekeeping
|
||||||
|
- Remove moment.js -- it's too heavy a dependency
|
|
@ -11300,6 +11300,11 @@ react-app-polyfill@^3.0.0:
|
||||||
regenerator-runtime "^0.13.9"
|
regenerator-runtime "^0.13.9"
|
||||||
whatwg-fetch "^3.6.2"
|
whatwg-fetch "^3.6.2"
|
||||||
|
|
||||||
|
react-circular-progressbar@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-circular-progressbar/-/react-circular-progressbar-2.1.0.tgz#99e5ae499c21de82223b498289e96f66adb8fa3a"
|
||||||
|
integrity sha512-xp4THTrod4aLpGy68FX/k1Q3nzrfHUjUe5v6FsdwXBl3YVMwgeXYQKDrku7n/D6qsJA9CuunarAboC2xCiKs1g==
|
||||||
|
|
||||||
react-dev-utils@^12.0.1:
|
react-dev-utils@^12.0.1:
|
||||||
version "12.0.1"
|
version "12.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.1.tgz#ba92edb4a1f379bd46ccd6bcd4e7bc398df33e73"
|
resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.1.tgz#ba92edb4a1f379bd46ccd6bcd4e7bc398df33e73"
|
||||||
|
|
Loading…
Reference in New Issue