Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/deploy-docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Push Docker image to Docker Hub

on:
push:
branches:
- main

jobs:
build-and-push:
runs-on: ubuntu-latest
if: github.repository == 'electh/ReactFlux'
steps:
- uses: actions/checkout@v4

- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: electh/ReactFlux:latest
1 change: 1 addition & 0 deletions .github/workflows/deploy-gh-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ jobs:
build-and-deploy:
concurrency: ci-${{github.ref}}
runs-on: ubuntu-latest
if: github.repository == 'electh/ReactFlux'
steps:
- name: Checkout
uses: actions/checkout@v3
Expand Down
13 changes: 9 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
# Stage 1: Build the React application
FROM node:alpine as build
# Specify the version to ensure consistent builds
FROM node:21-alpine AS build

# Set the working directory in the container
WORKDIR /app

# Copy the package.json files and install dependencies
# Copy the package.json files
COPY package*.json ./
RUN npm install

# Install dependencies
RUN npm ci

# Copy the rest of the code
COPY . .
Expand All @@ -15,7 +18,9 @@ COPY . .
RUN npm run build

# Stage 2: Run the server using Caddy
FROM caddy:alpine
# Specify the version for consistency
FROM caddy:2-alpine


# Copy built assets from the builder stage
COPY --from=build /app/build /srv
Expand Down
15 changes: 15 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "https://biomejs.dev/schemas/1.6.1/schema.json",
"organizeImports": {
"enabled": true
},
"formatter": {
"enabled": false
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
}
}
156 changes: 156 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
]
},
"devDependencies": {
"@biomejs/biome": "1.6.1",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"husky": "^9.0.11",
"lint-staged": "^15.2.2",
Expand Down
10 changes: 10 additions & 0 deletions src/Store.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ const useStore = create((set, get) => ({
theme: getConfig("theme") || "light",
layout: getConfig("layout") || "large",
fontSize: getConfig("fontSize") || 1.05,
showFeedIcon: getConfig("showFeedIcon") || true,
collapsed: window.innerWidth <= 992,
activeContent: null,

setUnreadTotal: (unreadTotal) => {
set({ unreadTotal: unreadTotal });
Expand All @@ -41,6 +43,9 @@ const useStore = create((set, get) => ({
setReadCount: (readCount) => {
set({ readCount: readCount });
},
setActiveContent: (activeContent) => {
set({ activeContent: activeContent });
},

initData: async () => {
set({ loading: true });
Expand Down Expand Up @@ -169,6 +174,11 @@ const useStore = create((set, get) => ({
setConfig("fontSize", sizeStr);
},

setShowFeedIcon: (showFeedIcon) => {
set({ showFeedIcon: showFeedIcon });
setConfig("showFeedIcon", showFeedIcon);
},

setVisible: (modalName, visible) => {
set((state) => ({ visible: { ...state.visible, [modalName]: visible } }));
},
Expand Down
15 changes: 13 additions & 2 deletions src/apis/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,23 @@ export async function editGroup(id, newTitle) {
});
}

export async function editFeed(feed_id, newTitle, group_id, is_full_text) {
export async function editFeed(
feed_id,
newUrl,
newTitle,
group_id,
is_full_text,
) {
return await thunder.request({
method: "put",
url: `/v1/feeds/${feed_id}`,
headers: { "Content-Type": "application/json" },
data: { title: newTitle, category_id: group_id, crawler: is_full_text },
data: {
feed_url: newUrl,
title: newTitle,
category_id: group_id,
crawler: is_full_text,
},
});
}

Expand Down
5 changes: 2 additions & 3 deletions src/components/Article/ActionButtons.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ import {
IconStar,
IconStarFill,
} from "@arco-design/web-react/icon";
import { useContext } from "react";

import useStore from "../../Store";
import useEntryActions from "../../hooks/useEntryActions";
import useKeyHandlers from "../../hooks/useKeyHandlers";
import ContentContext from "../Content/ContentContext";

const ActionButtons = ({ handleEntryClick }) => {
const { activeContent } = useContext(ContentContext);
const activeContent = useStore((state) => state.activeContent);
const { toggleEntryStarred, toggleEntryStatus } = useEntryActions();
const { handleLeftKey, handleRightKey } = useKeyHandlers();

Expand Down
5 changes: 2 additions & 3 deletions src/components/Article/ActionButtonsMobile.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@ import {
IconStar,
IconStarFill,
} from "@arco-design/web-react/icon";
import { useContext } from "react";

import useStore from "../../Store";
import useEntryActions from "../../hooks/useEntryActions";
import useKeyHandlers from "../../hooks/useKeyHandlers";
import ContentContext from "../Content/ContentContext";

const ActionButtonsMobile = ({ handleEntryClick }) => {
const { activeContent } = useContext(ContentContext);
const activeContent = useStore((state) => state.activeContent);
const { toggleEntryStarred, toggleEntryStatus } = useEntryActions();
const { handleLeftKey, handleRightKey, handleEscapeKey } = useKeyHandlers();

Expand Down
24 changes: 16 additions & 8 deletions src/components/Article/ArticleCard.jsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import { Card, Typography } from "@arco-design/web-react";
import { IconStarFill } from "@arco-design/web-react/icon";
import classNames from "classnames";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import { useContext } from "react";

import ContentContext from "../Content/ContentContext";
import useStore from "../../Store";
import { generateRelativeTime } from "../../utils/Date";
import "./ArticleCard.css";
import ImageWithLazyLoading from "./ImageWithLazyLoading";

dayjs.extend(relativeTime);

const ArticleCard = ({ entry, handleEntryClick }) => {
const { activeContent } = useContext(ContentContext);
const activeContent = useStore((state) => state.activeContent);
const showFeedIcon = useStore((state) => state.showFeedIcon);

return (
<div style={{ marginBottom: "10px" }} key={entry.id}>
Expand Down Expand Up @@ -69,9 +66,20 @@ const ArticleCard = ({ entry, handleEntryClick }) => {
}}
>
<br />
{showFeedIcon && (
<img
src={`https://icons.duckduckgo.com/ip3/${new URL(entry.feed.site_url).hostname}.ico`}
alt="Icon"
style={{
marginRight: "8px",
width: "16px",
height: "16px",
}}
/>
)}
{entry.feed.title}
<br />
{dayjs().to(dayjs(entry.published_at))}
{generateRelativeTime(entry.published_at)}
</Typography.Text>
{entry.starred && (
<IconStarFill
Expand Down
Loading