mirror of
https://github.com/dergigi/boris.git
synced 2026-01-26 02:04:58 +01:00
feat: add highlights filter button to reading progress filters
- Add 'highlighted' filter type to ReadingProgressFilterType - New filter button with yellow highlighter icon - Filter shows only articles that have highlights - Highlights filter checks both eventReference and urlReference tags - Color-coded: green for completed, yellow for highlighted, blue for others - Applies to reads and links tabs in /me page
This commit is contained in:
@@ -44,7 +44,7 @@ interface MeProps {
|
||||
type TabType = 'highlights' | 'reading-list' | 'reads' | 'links' | 'writings'
|
||||
|
||||
// Valid reading progress filters
|
||||
const VALID_FILTERS: ReadingProgressFilterType[] = ['all', 'unopened', 'started', 'reading', 'completed']
|
||||
const VALID_FILTERS: ReadingProgressFilterType[] = ['all', 'unopened', 'started', 'reading', 'completed', 'highlighted']
|
||||
|
||||
const Me: React.FC<MeProps> = ({
|
||||
relayPool,
|
||||
@@ -481,8 +481,8 @@ const Me: React.FC<MeProps> = ({
|
||||
const groups = groupIndividualBookmarks(filteredBookmarks)
|
||||
|
||||
// Apply reading progress filter
|
||||
const filteredReads = filterByReadingProgress(reads, readingProgressFilter)
|
||||
const filteredLinks = filterByReadingProgress(links, readingProgressFilter)
|
||||
const filteredReads = filterByReadingProgress(reads, readingProgressFilter, highlights)
|
||||
const filteredLinks = filterByReadingProgress(links, readingProgressFilter, highlights)
|
||||
const sections: Array<{ key: string; title: string; items: IndividualBookmark[] }> =
|
||||
groupingMode === 'flat'
|
||||
? [{ key: 'all', title: `All Bookmarks (${filteredBookmarks.length})`, items: filteredBookmarks }]
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React from 'react'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faBookOpen, faCheckCircle, faAsterisk } from '@fortawesome/free-solid-svg-icons'
|
||||
import { faBookOpen, faCheckCircle, faAsterisk, faHighlighter } from '@fortawesome/free-solid-svg-icons'
|
||||
import { faEnvelope, faEnvelopeOpen } from '@fortawesome/free-regular-svg-icons'
|
||||
|
||||
export type ReadingProgressFilterType = 'all' | 'unopened' | 'started' | 'reading' | 'completed'
|
||||
export type ReadingProgressFilterType = 'all' | 'unopened' | 'started' | 'reading' | 'completed' | 'highlighted'
|
||||
|
||||
interface ReadingProgressFiltersProps {
|
||||
selectedFilter: ReadingProgressFilterType
|
||||
@@ -16,15 +16,23 @@ const ReadingProgressFilters: React.FC<ReadingProgressFiltersProps> = ({ selecte
|
||||
{ type: 'unopened' as const, icon: faEnvelope, label: 'Unopened' },
|
||||
{ type: 'started' as const, icon: faEnvelopeOpen, label: 'Started' },
|
||||
{ type: 'reading' as const, icon: faBookOpen, label: 'Reading' },
|
||||
{ type: 'completed' as const, icon: faCheckCircle, label: 'Completed' }
|
||||
{ type: 'completed' as const, icon: faCheckCircle, label: 'Completed' },
|
||||
{ type: 'highlighted' as const, icon: faHighlighter, label: 'Highlighted' }
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="bookmark-filters">
|
||||
{filters.map(filter => {
|
||||
const isActive = selectedFilter === filter.type
|
||||
// Only "completed" gets green color, everything else uses default blue
|
||||
const activeStyle = isActive && filter.type === 'completed' ? { color: '#10b981' } : undefined
|
||||
// Only "completed" gets green color, "highlighted" gets yellow, everything else uses default blue
|
||||
let activeStyle: Record<string, string> | undefined = undefined
|
||||
if (isActive) {
|
||||
if (filter.type === 'completed') {
|
||||
activeStyle = { color: '#10b981' } // green
|
||||
} else if (filter.type === 'highlighted') {
|
||||
activeStyle = { color: '#fde047' } // yellow
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
|
||||
@@ -1,16 +1,35 @@
|
||||
import { ReadItem } from '../services/readsService'
|
||||
import { ReadingProgressFilterType } from '../components/ReadingProgressFilters'
|
||||
import { Highlight } from '../types/highlights'
|
||||
|
||||
/**
|
||||
* Filters ReadItems by reading progress
|
||||
*/
|
||||
export function filterByReadingProgress(
|
||||
items: ReadItem[],
|
||||
filter: ReadingProgressFilterType
|
||||
filter: ReadingProgressFilterType,
|
||||
highlights?: Highlight[]
|
||||
): ReadItem[] {
|
||||
// Build a map of article references to highlight count
|
||||
const articleHighlightCount = new Map<string, number>()
|
||||
if (highlights) {
|
||||
highlights.forEach(h => {
|
||||
if (h.eventReference) {
|
||||
const count = articleHighlightCount.get(h.eventReference) || 0
|
||||
articleHighlightCount.set(h.eventReference, count + 1)
|
||||
}
|
||||
if (h.urlReference) {
|
||||
const count = articleHighlightCount.get(h.urlReference) || 0
|
||||
articleHighlightCount.set(h.urlReference, count + 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return items.filter((item) => {
|
||||
const progress = item.readingProgress || 0
|
||||
const isMarked = item.markedAsRead || false
|
||||
const hasHighlights = (articleHighlightCount.get(item.id) || 0) > 0 ||
|
||||
(item.url && (articleHighlightCount.get(item.url) || 0) > 0)
|
||||
|
||||
switch (filter) {
|
||||
case 'unopened':
|
||||
@@ -21,6 +40,8 @@ export function filterByReadingProgress(
|
||||
return progress > 0.10 && progress <= 0.94 && !isMarked
|
||||
case 'completed':
|
||||
return progress >= 0.95 || isMarked
|
||||
case 'highlighted':
|
||||
return hasHighlights
|
||||
case 'all':
|
||||
default:
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user