Skip to content

Commit

Permalink
feat: show thumbnail on article list
Browse files Browse the repository at this point in the history
Fixes: #140
  • Loading branch information
Xstoudi committed Jul 18, 2023
1 parent 35cb063 commit b9d68e3
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 10 deletions.
21 changes: 21 additions & 0 deletions src-tauri/src/structs/article.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use chrono::Utc;
use feed_rs::model::Entry;
use serde::Serialize;
use crate::structs::image::Image;

#[derive(Debug, Serialize)]
pub struct Article {
Expand All @@ -9,6 +10,7 @@ pub struct Article {
pub content: String,
pub date: String,
pub read: bool,
pub image: Option<Image>
}

impl From<Entry> for Article {
Expand All @@ -30,12 +32,31 @@ impl From<Entry> for Article {
.unwrap_or_else(|| entry.updated.unwrap_or_else(|| Utc::now()))
.to_rfc3339();



let image = if entry.media.is_empty() {
None
} else {
let media = entry.media.iter().filter(|m| !m.thumbnails.is_empty()).next();
match media {
Some(m) => {
let thumbnail = m.thumbnails.iter().next();
match thumbnail {
Some(t) => Some(Image::from(t.image.clone())),
None => None
}
},
None => None
}
};

Article {
id,
title,
content,
date,
read: false,
image,
}
}
}
2 changes: 0 additions & 2 deletions src-tauri/src/structs/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use serde::Serialize;
#[derive(Debug, Serialize)]
pub struct Image {
pub uri: String,
pub title: Option<String>,
pub width: Option<u32>,
pub height: Option<u32>,
pub description: Option<String>,
Expand All @@ -13,7 +12,6 @@ impl From<feed_rs::model::Image> for Image {
fn from(image: feed_rs::model::Image) -> Self {
Image {
uri: image.uri,
title: image.title,
width: image.width,
height: image.height,
description: image.description,
Expand Down
31 changes: 26 additions & 5 deletions src/components/layout/Article.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useLocation, useNavigate } from 'react-router-dom';

import useActiveFeed from '../../hooks/useActiveFeed';
import useDataDispatch from '../../hooks/useDataDispatch';
import usePreference from '../../hooks/usePreference';
import useViewDispatch from '../../hooks/useViewDispatch';
import { READ_ARTICLE } from '../../state/data/DataActionType';
import { SET_ACTIVE_ARTICLE } from '../../state/view/ViewActionType';
Expand All @@ -13,9 +14,17 @@ interface ArticleProps extends ArticleType {
active: boolean;
}

function Article({ identifier, title, date, read, active }: ArticleProps) {
function Article({
identifier,
title,
date,
read,
image,
active,
}: ArticleProps) {
const navigate = useNavigate();
const location = useLocation();
const { showArticleThumbnails } = usePreference();
const viewDispatch = useViewDispatch();
const dataDispatch = useDataDispatch();
const feed = useActiveFeed();
Expand All @@ -40,11 +49,12 @@ function Article({ identifier, title, date, read, active }: ArticleProps) {
navigate,
viewDispatch,
]);
console.log(image);

return (
<div
className={clsx(
'flex justify-between items-center text-xl p-3 font-bold border-l-[3px] cursor-pointer transition-all duration-300 hover:pl-6 hover:bg-neutral-100 hover:dark:bg-neutral-600',
'flex justify-between items-center gap-2 text-lg p-3 font-bold border-l-[3px] cursor-pointer hover:bg-neutral-100 hover:dark:bg-neutral-600',
read
? 'border-neutral-50 dark:border-neutral-700 hover:border-neutral-100 dark:hover:border-neutral-600'
: 'border-orange-400',
Expand All @@ -53,10 +63,21 @@ function Article({ identifier, title, date, read, active }: ArticleProps) {
)}
onClick={selectArticle}
>
<div className="text-black dark:text-white">
{title.length > 40 ? `${title.slice(0, 40)}...` : title}
<div className="flex items-center text-black dark:text-white transition-all duration-300 hover:pl-6 h-12">
{/* Hacky way to preserve emojis */}
{title.length > 35 ? `${[...title].slice(0, 35).join('')}...` : title}
</div>

<div className="flex items-center text-orange-400 text-xl flex gap-4 flex-nowrap">
{showArticleThumbnails && image !== null && (
<img
src={image.uri}
alt={image.description ?? ''}
className="w-12 h-12 object-cover rounded-full"
/>
)}
{date.toLocaleDateString()}
</div>
<div className="text-orange-400 text-xl">{date.toLocaleDateString()}</div>
</div>
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/layout/FeedIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface FeedIconProps {
const ImageIcon = styled.img`
width: 2rem;
height: 2rem;
border-radius: 50%;
border-radius: 9999px;
object-fit: cover;
object-position: center;
`;
Expand Down
17 changes: 16 additions & 1 deletion src/components/modal/PreferenceModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,14 @@ function PreferenceModal() {
useModal<PreferenceState>(modalIdentifier);

const defaultForm = useMemo(
() => (isStateEmpty ? { darkMode: false, showFeedIcons: false } : state),
() =>
isStateEmpty
? {
darkMode: false,
showFeedIcons: false,
showArticleThumbnails: false,
}
: state,
[isStateEmpty, state],
);

Expand Down Expand Up @@ -78,6 +85,14 @@ function PreferenceModal() {
value={form.showFeedIcons}
onChange={(showFeedIcons) => setForm({ ...form, showFeedIcons })}
/>
<Switch
label="Show article thumbnails"
name="showArticleThumbnails"
value={form.showArticleThumbnails}
onChange={(showArticleThumbnails) =>
setForm({ ...form, showArticleThumbnails })
}
/>

<div className={clsx('mt-4 flex justify-between flex-row-reverse')}>
<Form.Submit asChild>
Expand Down
4 changes: 4 additions & 0 deletions src/data/transformers/v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export default {
feeds: backup.state.feeds.map((feed) => ({
...feed,
image: null,
articles: feed.articles.map((article) => ({
...article,
image: null,
})),
})),
},
};
Expand Down
2 changes: 2 additions & 0 deletions src/state/preference/PreferenceReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import { SetPreferencesAction } from './actions/GeneralActions';
export interface PreferenceState {
darkMode: boolean;
showFeedIcons: boolean;
showArticleThumbnails: boolean;
}

export const initialPreferenceState: PreferenceState = {
darkMode: true,
showFeedIcons: true,
showArticleThumbnails: true,
};

export type PreferenceActions = SetPreferencesAction;
Expand Down
1 change: 1 addition & 0 deletions src/state/preference/actions/GeneralActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ export function setPreferences(
) {
draft.darkMode = payload.darkMode;
draft.showFeedIcons = payload.showFeedIcons;
draft.showArticleThumbnails = payload.showArticleThumbnails;
}
3 changes: 3 additions & 0 deletions src/types/Article.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import ImageStructure from './ImageStructure';

export default interface Article {
identifier: string;
title: string;
content: string;
date: Date;
read: boolean;
image: ImageStructure | null;
}
1 change: 1 addition & 0 deletions src/types/SyncResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export interface ArticleResponse {
content: string;
date: string;
read: boolean;
image: ImageStructure | null;
}

export default interface SyncResponse {
Expand Down
5 changes: 4 additions & 1 deletion src/utils/articleMapper.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import { xxHash32 } from 'js-xxhash';

import Article from '../types/Article';
import { ArticleResponse } from '../types/SyncResponse';

export default function articleMapper({
id,
title,
content,
date,
}: ArticleResponse) {
image,
}: ArticleResponse): Article {
return {
identifier: xxHash32(id).toString(16),
title,
content,
image,
read: false,
date: new Date(date),
};
Expand Down

0 comments on commit b9d68e3

Please sign in to comment.