Skip to content

Commit f6b8755

Browse files
authored
Merge pull request #141 from medyo/develop
New version
2 parents c6d4b07 + 793d366 commit f6b8755

15 files changed

Lines changed: 201 additions & 68 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"react-contexify": "^5.0.0",
2222
"react-device-detect": "^1.17.0",
2323
"react-dom": "^17.0.1",
24+
"react-easy-sort": "^1.5.1",
2425
"react-error-boundary": "^3.1.4",
2526
"react-icons": "^4.4.0",
2627
"react-markdown": "^7.0.1",

src/App.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { Suspense, useEffect, useLayoutEffect, useState } from 'react'
22
import 'react-contexify/dist/ReactContexify.css'
33
import 'src/assets/App.css'
4-
import { Footer, Header } from 'src/components/Layout'
4+
import { Header } from 'src/components/Layout'
55
import { BookmarksSidebar } from 'src/features/bookmarks'
66
import { MarketingBanner } from 'src/features/MarketingBanner'
77
import { setupAnalytics, setupIdentification, trackPageView } from 'src/lib/analytics'
@@ -59,8 +59,6 @@ function App() {
5959
<ScrollCardsNavigator />
6060
<AppContentLayout setShowSettings={setShowSettings} />
6161
<BookmarksSidebar showSidebar={showSideBar} onClose={() => setShowSideBar(false)} />
62-
63-
<Footer />
6462
</div>
6563
</>
6664
)

src/assets/App.css

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -67,16 +67,16 @@ a {
6767
}
6868

6969
.AppFooter {
70-
flex: 0 0 auto;
70+
display: flex;
7171
flex-direction: row;
72-
text-align: right;
73-
margin-top: 12px;
72+
justify-content: center;
73+
align-items: center;
74+
margin-top: 24px;
7475
}
7576
.AppFooter .linkItem {
7677
font-size: 12px;
7778
color: var(--primary-text-color);
7879
text-decoration: none;
79-
text-transform: uppercase;
8080
margin-right: 12px;
8181
cursor: pointer;
8282
display: inline-flex;
@@ -90,16 +90,20 @@ a {
9090
}
9191

9292
.AppContent {
93+
position: relative;
94+
overflow-y: hidden;
95+
padding: 12px 0;
96+
}
97+
.Cards {
98+
padding: 1%;
9399
flex: 1 1 auto;
94100
display: flex;
95101
gap: 12px;
96-
padding: 1%;
97102
position: relative;
98103
overflow-y: hidden;
99-
padding-bottom: 12px;
100104
scroll-snap-type: x mandatory;
105+
scroll-padding-left: 12px;
101106
}
102-
103107
.HorizontalScroll {
104108
-ms-overflow-style: none;
105109
scrollbar-width: none;
@@ -195,7 +199,7 @@ a {
195199
border-radius: 10px;
196200
overflow: hidden;
197201
flex-direction: column;
198-
height: 78vh;
202+
height: 82vh;
199203
width: 10vw;
200204
flex: 0 0 auto;
201205
scroll-snap-align: start;
@@ -207,7 +211,7 @@ a {
207211
flex-direction: column;
208212
overflow-x: hidden;
209213
scroll-snap-type: y mandatory;
210-
height: calc(80vh - 1% - 46px);
214+
height: calc(86vh - 1% - 46px);
211215
}
212216

213217
.scrollable {
@@ -250,7 +254,17 @@ a {
250254
font-size: 16px;
251255
padding-top: 16px;
252256
padding-bottom: 8px;
253-
cursor: pointer;
257+
position: relative;
258+
}
259+
260+
.blockHeader .maxTitle {
261+
margin: 0;
262+
padding: 0;
263+
line-height: 13px;
264+
white-space: nowrap;
265+
overflow: hidden;
266+
text-overflow: ellipsis;
267+
max-width: 180px;
254268
}
255269
.blockHeader:hover .blockHeaderLink {
256270
opacity: 1;
@@ -263,6 +277,32 @@ a {
263277
opacity: 0;
264278
transition: opacity 0.2s linear;
265279
}
280+
.blockHeaderDragButton {
281+
position: absolute;
282+
top: 0;
283+
left: 0;
284+
background: linear-gradient(to left, transparent, var(--card-actions-background-shadow));
285+
border: none;
286+
height: 100%;
287+
padding: 0 12px;
288+
width: 32%;
289+
align-items: center;
290+
justify-content: start;
291+
z-index: 1;
292+
cursor: grab;
293+
display: none;
294+
color: #96a2ae;
295+
font-size: 24px;
296+
}
297+
298+
.blockHeader:hover .blockHeaderDragButton {
299+
display: flex;
300+
}
301+
.draggedBlock .block {
302+
transform: rotate(3deg);
303+
opacity: 0.5;
304+
}
305+
266306
.blockHeaderIcon {
267307
position: relative;
268308
top: 4px;
@@ -273,7 +313,7 @@ a {
273313
height: 18px;
274314
}
275315
.blockHeaderIcon .rss {
276-
color:#ee802f;
316+
color: #ee802f;
277317
}
278318
.blockRow {
279319
scroll-snap-align: start;
@@ -449,7 +489,7 @@ a {
449489
flex-direction: row;
450490
flex-wrap: wrap;
451491
gap: 4px;
452-
margin-top: 12px;
492+
margin-top: 24px;
453493
}
454494

455495
.tag {
@@ -662,10 +702,6 @@ Producthunt item
662702
font-size: 14px;
663703
}
664704

665-
.test3 {
666-
flex-direction: column;
667-
}
668-
669705
.bottomNavigation {
670706
display: none;
671707
flex-grow: 1;
@@ -686,6 +722,9 @@ Producthunt item
686722
height: 100%;
687723
line-height: 56px;
688724
font-size: 24px;
725+
margin: 0;
726+
border: none;
727+
background: none;
689728
}
690729
.navigationItem img {
691730
width: 18px;

src/components/Elements/BottomNavigation/BottomNavigation.tsx

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
import { AiOutlineMenu } from 'react-icons/ai'
2+
import { BsRssFill } from 'react-icons/bs'
13
import { SUPPORTED_CARDS } from 'src/config'
2-
import { SelectedCard } from 'src/types'
34
import { useUserPreferences } from 'src/stores/preferences'
4-
import { AiOutlineMenu } from 'react-icons/ai'
5+
import { SelectedCard } from 'src/types'
56

67
type BottomNavigationProps = {
78
selectedCard: SelectedCard
@@ -14,31 +15,33 @@ export const BottomNavigation = ({
1415
setSelectedCard,
1516
setShowSettings,
1617
}: BottomNavigationProps) => {
17-
const { cards } = useUserPreferences()
18+
const { cards, userCustomCards } = useUserPreferences()
19+
const AVAILABLE_CARDS = [...SUPPORTED_CARDS, ...userCustomCards]
1820

1921
return (
2022
<div className="bottomNavigation">
2123
{cards.map((card) => {
22-
const constantCard = SUPPORTED_CARDS.find((c) => c.value === card.name)
24+
const constantCard = AVAILABLE_CARDS.find((c) => c.value === card.name)
25+
2326
return (
24-
<a
27+
<button
2528
key={card.name}
2629
className={
2730
'navigationItem ' + (selectedCard && selectedCard.name === card.name ? 'active' : '')
2831
}
29-
href="/#"
30-
onClick={(e) => setSelectedCard(card)}>
31-
{constantCard?.icon}
32-
</a>
32+
onClick={() => setSelectedCard(card)}>
33+
{card.type === 'supported'
34+
? constantCard?.icon
35+
: <img src={constantCard?.icon as string} alt="" /> || <BsRssFill className="rss" />}
36+
</button>
3337
)
3438
})}
3539
{
36-
<a
40+
<button
3741
className={'navigationItem '}
38-
href="/#"
39-
onClick={(e) => setShowSettings((prev: boolean) => !prev)}>
42+
onClick={() => setShowSettings((prev: boolean) => !prev)}>
4043
{<AiOutlineMenu />}
41-
</a>
44+
</button>
4245
}
4346
</div>
4447
)

src/components/Elements/Card/Card.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import React from 'react'
2+
import { isDesktop } from 'react-device-detect'
3+
import { SortableKnob } from 'react-easy-sort'
24
import { BsBoxArrowInUpRight } from 'react-icons/bs'
5+
import { MdOutlineDragIndicator } from 'react-icons/md'
36
import { ref } from 'src/config'
47
import { useUserPreferences } from 'src/stores/preferences'
58
import { SupportedCardType } from 'src/types'
@@ -23,13 +26,21 @@ export const Card = ({ card, titleComponent, children, fullBlock = false }: Card
2326
return (
2427
<div className={'block' + (fullBlock ? ' fullBlock' : '')}>
2528
<div className="blockHeader">
29+
{isDesktop && (
30+
<SortableKnob>
31+
<button className="blockHeaderDragButton">
32+
<MdOutlineDragIndicator />
33+
</button>
34+
</SortableKnob>
35+
)}
2636
<span className="blockHeaderIcon">{icon}</span> {titleComponent || label}{' '}
2737
{link && (
2838
<a className="blockHeaderLink" href={link} onClick={handleHeaderLinkClick}>
2939
<BsBoxArrowInUpRight />
3040
</a>
3141
)}
3242
</div>
43+
3344
<div className="blockContent scrollable">{children}</div>
3445
</div>
3546
)

src/components/Layout/AppContentLayout.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@ export const AppContentLayout = ({
1515

1616
return (
1717
<>
18-
<main className="AppContent HorizontalScroll">
18+
<main className="AppContent">
1919
{isDesktop ? (
2020
<DesktopCards cards={cards} userCustomCards={userCustomCards} />
2121
) : (
22-
<MobileCards selectedCard={selectedCard} />
22+
<div className="HorizontalScroll">
23+
<MobileCards selectedCard={selectedCard} />
24+
</div>
2325
)}
2426
</main>
25-
2627
<BottomNavigation
2728
selectedCard={selectedCard}
2829
setSelectedCard={setSelectedCard}
Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
import React from 'react'
1+
import { useLayoutEffect, useRef } from 'react'
2+
import SortableList, { SortableItem } from 'react-easy-sort'
23
import { SUPPORTED_CARDS } from 'src/config'
34
import { CustomRssCard } from 'src/features/cards'
5+
import { trackPageDrag } from 'src/lib/analytics'
6+
import { useUserPreferences } from 'src/stores/preferences'
47
import { SelectedCard, SupportedCardType } from 'src/types'
58

69
export const DesktopCards = ({
@@ -11,20 +14,47 @@ export const DesktopCards = ({
1114
userCustomCards: SupportedCardType[]
1215
}) => {
1316
const AVAILABLE_CARDS = [...SUPPORTED_CARDS, ...userCustomCards]
17+
const { updateCardOrder } = useUserPreferences()
18+
const scrollHolderRef = useRef<HTMLElement | null>(null)
19+
20+
const onSortEnd = (oldIndex: number, newIndex: number) => {
21+
updateCardOrder(oldIndex, newIndex)
22+
trackPageDrag()
23+
if (newIndex === 0 || (oldIndex > 3 && newIndex < 3)) {
24+
scrollHolderRef.current?.scrollTo(0, 0)
25+
}
26+
}
27+
28+
useLayoutEffect(() => {
29+
scrollHolderRef.current = document.querySelector('.Cards')
30+
}, [])
31+
1432
return (
15-
<>
16-
{cards.map((card, index) => {
17-
const constantCard = AVAILABLE_CARDS.find((c) => c.value === card.name)
18-
if (!constantCard) {
19-
return null
20-
}
33+
<SortableList
34+
as="div"
35+
onSortEnd={onSortEnd}
36+
lockAxis="x"
37+
customHolderRef={scrollHolderRef}
38+
className="Cards HorizontalScroll"
39+
draggedItemClassName="draggedBlock">
40+
{cards
41+
.sort((a, b) => a.id - b.id)
42+
.map((card, index) => {
43+
const constantCard = AVAILABLE_CARDS.find((c) => c.value === card.name)
44+
if (!constantCard) {
45+
return null
46+
}
47+
48+
const Component = constantCard?.component || CustomRssCard
2149

22-
return React.createElement(constantCard?.component || CustomRssCard, {
23-
key: card.name,
24-
meta: constantCard,
25-
withAds: index === 0,
26-
})
27-
})}
28-
</>
50+
return (
51+
<SortableItem key={card.name}>
52+
<div>
53+
<Component key={card.name} meta={constantCard} withAds={index === 0} />
54+
</div>
55+
</SortableItem>
56+
)
57+
})}
58+
</SortableList>
2959
)
3060
}

src/components/Layout/Footer.tsx

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
1-
import React from 'react'
2-
import {
3-
repository,
4-
supportLink,
5-
privacyPolicyLink,
6-
termsAndConditionsLink,
7-
dataSourcesLink,
8-
} from 'src/config'
9-
import { RiCodeSSlashFill } from 'react-icons/ri'
101
import { HiLightBulb } from 'react-icons/hi'
2+
import { RiCodeSSlashFill } from 'react-icons/ri'
3+
import { privacyPolicyLink, repository, supportLink, termsAndConditionsLink } from 'src/config'
114
import { trackPageView } from 'src/lib/analytics'
5+
import { getAppVersion } from 'src/utils/Os'
126

137
export const Footer = () => {
8+
const appVersion = getAppVersion()
149
return (
1510
<footer className="AppFooter">
1611
<a className="linkItem" href={supportLink} onClick={() => trackPageView('Feature Request')}>
@@ -34,9 +29,16 @@ export const Footer = () => {
3429
onClick={() => trackPageView('Privacy Policy')}>
3530
Privacy policy
3631
</a>
37-
<a className="linkItem" href={dataSourcesLink} onClick={() => trackPageView('Data Sources')}>
38-
Data sources
39-
</a>
32+
{appVersion && (
33+
<a
34+
className="linkItem"
35+
href={repository}
36+
target="_blank"
37+
rel="noreferrer"
38+
onClick={() => trackPageView('Source Code')}>
39+
v{appVersion}
40+
</a>
41+
)}
4042
</footer>
4143
)
4244
}

0 commit comments

Comments
 (0)