File size: 7,225 Bytes
cf1fb4e
 
 
 
 
 
 
7e454f3
 
 
 
 
 
 
 
 
 
 
 
 
 
7b84ed4
40c26bb
 
 
 
 
7e454f3
 
40c26bb
 
7b84ed4
 
 
6c20801
 
 
 
5d4d8d0
6c20801
5d4d8d0
6c20801
 
 
7e454f3
 
 
6c20801
 
 
 
 
 
 
40c26bb
 
6c20801
 
7b84ed4
 
 
 
 
5d4d8d0
 
 
 
7b84ed4
 
5d4d8d0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dda464b
 
5d4d8d0
 
 
 
 
 
 
 
 
 
 
7b84ed4
5d4d8d0
7b84ed4
 
5d4d8d0
 
7b84ed4
 
dda464b
7b84ed4
5d4d8d0
 
 
 
 
7b84ed4
 
6c20801
40c26bb
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>News Feed Hub</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; background-color: #f5f5f5; color: #333; }
        h1 { text-align: center; color: #2c3e50; }
        .search-container { text-align: center; margin: 20px 0; }
        .search-bar { width: 50%; padding: 10px; border: 2px solid #3498db; border-radius: 25px; }
        .category-section { margin: 20px 0; }
        .category-title { background-color: #3498db; color: white; padding: 10px; border-radius: 5px; }
        .tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; }
        .article-tile { background: white; padding: 15px; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
        .article-tile img, .article-tile svg { width: 100%; height: 150px; object-fit: cover; border-radius: 5px; }
        .title a { font-size: 1.1em; color: #2c3e50; text-decoration: none; }
        .title a:hover { color: #3498db; }
        .description { color: #555; font-size: 0.9em; }
        .published { font-size: 0.8em; color: #95a5a6; }
        .no-articles { text-align: center; color: #2c3e50; margin-top: 20px; }
        .loading-message { text-align: center; color: #3498db; margin: 10px 0; }
    </style>
</head>
<body>
    <h1>News Feed Hub</h1>
    <div class="search-container">
        <form method="POST" action="/search">
            <input type="text" name="search" class="search-bar" placeholder="Search news...">
        </form>
    </div>
    {% if loading %}
        <div class="loading-message">Fetching new RSS feeds in the background...</div>
    {% endif %}
    {% if has_articles %}
        {% for category, articles in categorized_articles.items() %}
        <div class="category-section">
            <div class="category-title">{{ category }}</div>
            <div class="tiles" id="category-{{ category }}" data-last-update="0">
                {% for article in articles %}
                <div class="article-tile" data-published="{{ article.published }}" data-id="{{ loop.index }}">
                    {% if article.image != "svg" %}
                    <img src="{{ article.image }}" alt="Article Image">
                    {% else %}
                    <svg width="100%" height="150" xmlns="http://www.w3.org/2000/svg">
                        <rect width="100%" height="100%" fill="#e0e0e0"/>
                        <text x="50%" y="50%" text-anchor="middle" dy=".3em" fill="#666">No Image</text>
                    </svg>
                    {% endif %}
                    <div class="title"><a href="{{ article.link }}" target="_blank">{{ article.title }}</a></div>
                    <div class="description">{{ article.description }}</div>
                    <div class="published">Published: {{ article.published }}</div>
                </div>
                {% endfor %}
            </div>
        </div>
        {% endfor %}
    {% else %}
        <div class="no-articles">No articles available yet. Loading new feeds...</div>
    {% endif %}

    {% if loading %}
    <script>
        let lastUpdate = 0;

        function updateArticles() {
            fetch('/get_updates')
                .then(response => response.json())
                .then(data => {
                    if (data.articles && data.last_update > lastUpdate) {
                        lastUpdate = data.last_update;
                        const newArticles = data.articles;
                        for (const [category, articles] of Object.entries(newArticles)) {
                            const tilesDiv = document.getElementById(`category-${category}`);
                            if (tilesDiv) {
                                const existingArticles = Array.from(tilesDiv.querySelectorAll('.article-tile'));
                                let currentIds = new Set(existingArticles.map(a => a.dataset.id));
                                let newHtml = '';

                                // Sort new articles by published date
                                articles.sort((a, b) => new Date(b.published) - new Date(a.published));

                                // Add new articles (up to 10 total, keeping most recent)
                                articles.forEach((article, index) => {
                                    if (index < 10 && !currentIds.has(index.toString())) {
                                        newHtml += `
                                            <div class="article-tile" data-published="${article.published}" data-id="${index}">
                                                ${article.image !== "svg" ? `<img src="${article.image}" alt="Article Image">` : `
                                                    <svg width="100%" height="150" xmlns="http://www.w3.org/2000/svg">
                                                        <rect width="100%" height="100%" fill="#e0e0e0"/>
                                                        <text x="50%" y="50%" text-anchor="middle" dy=".3em" fill="#666">No Image</text>
                                                    </svg>
                                                `}
                                                <div class="title"><a href="${article.link}" target="_blank">${article.title}</a></div>
                                                <div class="description">${article.description}</div>
                                                <div class="published">Published: ${article.published}</div>
                                            </div>
                                        `;
                                    }
                                });

                                // Append new articles, maintaining limit of 10
                                if (newHtml) {
                                    tilesDiv.innerHTML += newHtml;
                                    const allArticles = Array.from(tilesDiv.querySelectorAll('.article-tile'));
                                    allArticles.sort((a, b) => new Date(b.dataset.published) - new Date(a.dataset.published));
                                    tilesDiv.innerHTML = allArticles.slice(0, 10).map(a => a.outerHTML).join('');
                                }
                            }
                        }
                        document.querySelector('.loading-message').style.display = 'none';
                    }
                    setTimeout(updateArticles, 2000);  // Check every 2 seconds
                })
                .catch(error => {
                    console.error('Error updating articles:', error);
                    setTimeout(updateArticles, 2000);  // Retry on error
                });
        }

        document.addEventListener('DOMContentLoaded', () => {
            const tiles = document.querySelectorAll('.tiles');
            tiles.forEach(tile => {
                lastUpdate = Math.max(lastUpdate, parseFloat(tile.dataset.lastUpdate) || 0);
            });
            updateArticles();
        });
    </script>
    {% endif %}
</body>
</html>