Update app.py
Browse files
app.py
CHANGED
|
@@ -119,7 +119,7 @@ def update_last_seen(data, username):
|
|
| 119 |
data['users'][username]['last_seen'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
| 120 |
save_data(data)
|
| 121 |
|
| 122 |
-
# Новый стиль 2025 года
|
| 123 |
BASE_STYLE = '''
|
| 124 |
:root {
|
| 125 |
--primary: #ff3b8e;
|
|
@@ -264,11 +264,13 @@ body {
|
|
| 264 |
|
| 265 |
.container {
|
| 266 |
margin: 2rem 2rem 2rem 340px;
|
| 267 |
-
padding:
|
| 268 |
background: var(--surface);
|
| 269 |
border-radius: 20px;
|
| 270 |
box-shadow: var(--shadow);
|
| 271 |
transition: var(--transition);
|
|
|
|
|
|
|
| 272 |
}
|
| 273 |
|
| 274 |
.btn {
|
|
@@ -376,9 +378,141 @@ input:focus, textarea:focus, select:focus {
|
|
| 376 |
display: block;
|
| 377 |
}
|
| 378 |
.container {
|
| 379 |
-
margin:
|
| 380 |
}
|
| 381 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 382 |
'''
|
| 383 |
|
| 384 |
NAV_HTML = '''
|
|
@@ -671,9 +805,21 @@ def feed():
|
|
| 671 |
user_count = len(data['users'])
|
| 672 |
is_online = is_user_online(data, username) if is_authenticated else False
|
| 673 |
|
| 674 |
-
|
| 675 |
-
|
| 676 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 677 |
|
| 678 |
html = '''
|
| 679 |
<!DOCTYPE html>
|
|
@@ -686,66 +832,6 @@ def feed():
|
|
| 686 |
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&display=swap" rel="stylesheet">
|
| 687 |
<style>
|
| 688 |
''' + BASE_STYLE + '''
|
| 689 |
-
h1 {
|
| 690 |
-
font-size: 2.5rem;
|
| 691 |
-
background: var(--gradient);
|
| 692 |
-
-webkit-background-clip: text;
|
| 693 |
-
color: transparent;
|
| 694 |
-
margin-bottom: 2rem;
|
| 695 |
-
}
|
| 696 |
-
.search-container {
|
| 697 |
-
margin-bottom: 2rem;
|
| 698 |
-
display: flex;
|
| 699 |
-
gap: 1rem;
|
| 700 |
-
}
|
| 701 |
-
.search-input {
|
| 702 |
-
flex-grow: 1;
|
| 703 |
-
box-shadow: var(--shadow);
|
| 704 |
-
}
|
| 705 |
-
.post-grid {
|
| 706 |
-
display: grid;
|
| 707 |
-
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
| 708 |
-
gap: 1.5rem;
|
| 709 |
-
}
|
| 710 |
-
.post-item {
|
| 711 |
-
background: var(--glass);
|
| 712 |
-
padding: 1.5rem;
|
| 713 |
-
border-radius: 20px;
|
| 714 |
-
box-shadow: var(--shadow);
|
| 715 |
-
transition: var(--transition);
|
| 716 |
-
backdrop-filter: blur(10px);
|
| 717 |
-
}
|
| 718 |
-
.post-item:hover {
|
| 719 |
-
transform: translateY(-5px) scale(1.02);
|
| 720 |
-
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
|
| 721 |
-
}
|
| 722 |
-
.post-preview {
|
| 723 |
-
width: 100%;
|
| 724 |
-
height: 220px;
|
| 725 |
-
object-fit: cover;
|
| 726 |
-
border-radius: 15px;
|
| 727 |
-
transition: var(--transition);
|
| 728 |
-
}
|
| 729 |
-
.post-item h2 {
|
| 730 |
-
font-size: 1.4rem;
|
| 731 |
-
margin: 1rem 0 0.5rem;
|
| 732 |
-
}
|
| 733 |
-
.post-item p {
|
| 734 |
-
font-size: 0.9rem;
|
| 735 |
-
opacity: 0.8;
|
| 736 |
-
}
|
| 737 |
-
.stats {
|
| 738 |
-
font-size: 0.85rem;
|
| 739 |
-
opacity: 0.6;
|
| 740 |
-
}
|
| 741 |
-
.username-link {
|
| 742 |
-
color: var(--primary);
|
| 743 |
-
text-decoration: none;
|
| 744 |
-
font-weight: 600;
|
| 745 |
-
}
|
| 746 |
-
.username-link:hover {
|
| 747 |
-
color: var(--accent);
|
| 748 |
-
}
|
| 749 |
</style>
|
| 750 |
</head>
|
| 751 |
<body>
|
|
@@ -753,28 +839,54 @@ def feed():
|
|
| 753 |
''' + NAV_HTML + '''
|
| 754 |
<button class="theme-toggle" onclick="toggleTheme()">🌙</button>
|
| 755 |
<div class="container">
|
| 756 |
-
<
|
| 757 |
-
<div class="search-container">
|
| 758 |
-
<form method="POST" class="search-form">
|
| 759 |
-
<input type="text" name="search" class="search-input" placeholder="Search posts..." value="{{ search_query }}">
|
| 760 |
-
<button type="submit" class="btn">🔍</button>
|
| 761 |
-
</form>
|
| 762 |
-
</div>
|
| 763 |
-
<div class="post-grid">
|
| 764 |
{% for post in posts %}
|
| 765 |
-
<
|
| 766 |
{% if post['type'] == 'video' %}
|
| 767 |
-
<video class="post-
|
| 768 |
<source src="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/{{ post['type'] }}s/{{ post['filename'] }}" type="video/mp4">
|
| 769 |
</video>
|
| 770 |
{% else %}
|
| 771 |
-
<img class="post-
|
| 772 |
{% endif %}
|
| 773 |
-
<
|
| 774 |
-
|
| 775 |
-
|
| 776 |
-
|
| 777 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 778 |
{% endfor %}
|
| 779 |
</div>
|
| 780 |
</div>
|
|
@@ -787,30 +899,40 @@ def feed():
|
|
| 787 |
document.body.classList.toggle('dark');
|
| 788 |
localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
|
| 789 |
}
|
| 790 |
-
function
|
| 791 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 792 |
document.getElementById('imageModal').style.display = 'flex';
|
| 793 |
document.getElementById('modalImage').src = src;
|
| 794 |
-
fetch('/increment_view/' + postId, { method: 'POST' });
|
| 795 |
}
|
| 796 |
function closeModal(event) {
|
| 797 |
if (event.target.tagName !== 'IMG') document.getElementById('imageModal').style.display = 'none';
|
| 798 |
}
|
| 799 |
window.onload = () => {
|
| 800 |
if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
|
| 801 |
-
document.
|
| 802 |
-
|
| 803 |
-
|
| 804 |
-
|
| 805 |
-
|
| 806 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 807 |
});
|
| 808 |
};
|
| 809 |
</script>
|
| 810 |
</body>
|
| 811 |
</html>
|
| 812 |
'''
|
| 813 |
-
return render_template_string(html, posts=posts, is_authenticated=is_authenticated, username=username, repo_id=REPO_ID,
|
| 814 |
|
| 815 |
@app.route('/post/<post_id>', methods=['GET', 'POST'])
|
| 816 |
def post_page(post_id):
|
|
|
|
| 119 |
data['users'][username]['last_seen'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
| 120 |
save_data(data)
|
| 121 |
|
| 122 |
+
# Новый стиль 2025 года с изменениями для TikTok-подобной ленты
|
| 123 |
BASE_STYLE = '''
|
| 124 |
:root {
|
| 125 |
--primary: #ff3b8e;
|
|
|
|
| 264 |
|
| 265 |
.container {
|
| 266 |
margin: 2rem 2rem 2rem 340px;
|
| 267 |
+
padding: 0;
|
| 268 |
background: var(--surface);
|
| 269 |
border-radius: 20px;
|
| 270 |
box-shadow: var(--shadow);
|
| 271 |
transition: var(--transition);
|
| 272 |
+
height: calc(100vh - 4rem);
|
| 273 |
+
overflow: hidden;
|
| 274 |
}
|
| 275 |
|
| 276 |
.btn {
|
|
|
|
| 378 |
display: block;
|
| 379 |
}
|
| 380 |
.container {
|
| 381 |
+
margin: 2rem 1rem;
|
| 382 |
}
|
| 383 |
}
|
| 384 |
+
|
| 385 |
+
/* Стили для TikTok-подобной ленты */
|
| 386 |
+
.feed-container {
|
| 387 |
+
height: 100%;
|
| 388 |
+
overflow-y: scroll;
|
| 389 |
+
scroll-snap-type: y mandatory;
|
| 390 |
+
-webkit-overflow-scrolling: touch;
|
| 391 |
+
}
|
| 392 |
+
|
| 393 |
+
.post-slide {
|
| 394 |
+
height: 100vh;
|
| 395 |
+
scroll-snap-align: start;
|
| 396 |
+
position: relative;
|
| 397 |
+
display: flex;
|
| 398 |
+
flex-direction: column;
|
| 399 |
+
justify-content: center;
|
| 400 |
+
align-items: center;
|
| 401 |
+
background: var(--glass);
|
| 402 |
+
}
|
| 403 |
+
|
| 404 |
+
.post-media {
|
| 405 |
+
width: 100%;
|
| 406 |
+
height: 80%;
|
| 407 |
+
object-fit: contain;
|
| 408 |
+
border-radius: 20px;
|
| 409 |
+
box-shadow: var(--shadow);
|
| 410 |
+
}
|
| 411 |
+
|
| 412 |
+
.post-overlay {
|
| 413 |
+
position: absolute;
|
| 414 |
+
bottom: 0;
|
| 415 |
+
left: 0;
|
| 416 |
+
width: 100%;
|
| 417 |
+
padding: 1rem;
|
| 418 |
+
background: linear-gradient(to top, rgba(0, 0, 0, 0.8), transparent);
|
| 419 |
+
}
|
| 420 |
+
|
| 421 |
+
.post-info {
|
| 422 |
+
padding: 1rem;
|
| 423 |
+
width: 100%;
|
| 424 |
+
}
|
| 425 |
+
|
| 426 |
+
.post-info h2 {
|
| 427 |
+
font-size: 1.5rem;
|
| 428 |
+
margin-bottom: 0.5rem;
|
| 429 |
+
}
|
| 430 |
+
|
| 431 |
+
.post-info p {
|
| 432 |
+
font-size: 1rem;
|
| 433 |
+
opacity: 0.8;
|
| 434 |
+
}
|
| 435 |
+
|
| 436 |
+
.actions {
|
| 437 |
+
position: absolute;
|
| 438 |
+
right: 1rem;
|
| 439 |
+
top: 50%;
|
| 440 |
+
transform: translateY(-50%);
|
| 441 |
+
display: flex;
|
| 442 |
+
flex-direction: column;
|
| 443 |
+
gap: 1rem;
|
| 444 |
+
align-items: center;
|
| 445 |
+
}
|
| 446 |
+
|
| 447 |
+
.action-btn {
|
| 448 |
+
background: var(--glass);
|
| 449 |
+
border: none;
|
| 450 |
+
border-radius: 50%;
|
| 451 |
+
width: 50px;
|
| 452 |
+
height: 50px;
|
| 453 |
+
display: flex;
|
| 454 |
+
align-items: center;
|
| 455 |
+
justify-content: center;
|
| 456 |
+
cursor: pointer;
|
| 457 |
+
transition: var(--transition);
|
| 458 |
+
backdrop-filter: blur(10px);
|
| 459 |
+
}
|
| 460 |
+
|
| 461 |
+
.action-btn:hover {
|
| 462 |
+
background: var(--primary);
|
| 463 |
+
transform: scale(1.1);
|
| 464 |
+
}
|
| 465 |
+
|
| 466 |
+
.action-btn.liked {
|
| 467 |
+
background: var(--secondary);
|
| 468 |
+
}
|
| 469 |
+
|
| 470 |
+
.action-count {
|
| 471 |
+
font-size: 0.9rem;
|
| 472 |
+
margin-top: 0.3rem;
|
| 473 |
+
}
|
| 474 |
+
|
| 475 |
+
.comments-container {
|
| 476 |
+
position: absolute;
|
| 477 |
+
right: 0;
|
| 478 |
+
top: 0;
|
| 479 |
+
height: 100%;
|
| 480 |
+
width: 350px;
|
| 481 |
+
background: rgba(0, 0, 0, 0.9);
|
| 482 |
+
padding: 1rem;
|
| 483 |
+
overflow-y: auto;
|
| 484 |
+
transform: translateX(100%);
|
| 485 |
+
transition: var(--transition);
|
| 486 |
+
z-index: 10;
|
| 487 |
+
}
|
| 488 |
+
|
| 489 |
+
.comments-container.active {
|
| 490 |
+
transform: translateX(0);
|
| 491 |
+
}
|
| 492 |
+
|
| 493 |
+
.comment {
|
| 494 |
+
background: var(--glass);
|
| 495 |
+
padding: 0.8rem;
|
| 496 |
+
border-radius: 10px;
|
| 497 |
+
margin-bottom: 0.8rem;
|
| 498 |
+
}
|
| 499 |
+
|
| 500 |
+
.comment-form {
|
| 501 |
+
position: sticky;
|
| 502 |
+
bottom: 0;
|
| 503 |
+
background: rgba(0, 0, 0, 0.9);
|
| 504 |
+
padding: 1rem;
|
| 505 |
+
}
|
| 506 |
+
|
| 507 |
+
.username-link {
|
| 508 |
+
color: var(--primary);
|
| 509 |
+
text-decoration: none;
|
| 510 |
+
font-weight: 600;
|
| 511 |
+
}
|
| 512 |
+
|
| 513 |
+
.username-link:hover {
|
| 514 |
+
color: var(--accent);
|
| 515 |
+
}
|
| 516 |
'''
|
| 517 |
|
| 518 |
NAV_HTML = '''
|
|
|
|
| 805 |
user_count = len(data['users'])
|
| 806 |
is_online = is_user_online(data, username) if is_authenticated else False
|
| 807 |
|
| 808 |
+
if request.method == 'POST' and is_authenticated:
|
| 809 |
+
post_id = request.form.get('post_id')
|
| 810 |
+
action = request.form.get('action')
|
| 811 |
+
post = next((p for p in data['posts'] if p['id'] == post_id), None)
|
| 812 |
+
if post:
|
| 813 |
+
if action == 'like':
|
| 814 |
+
if username not in post.get('likes', []):
|
| 815 |
+
post['likes'] = post.get('likes', []) + [username]
|
| 816 |
+
else:
|
| 817 |
+
post['likes'] = [user for user in post.get('likes', []) if user != username]
|
| 818 |
+
elif action == 'comment':
|
| 819 |
+
comment_text = request.form.get('comment')
|
| 820 |
+
if comment_text:
|
| 821 |
+
post['comments'] = post.get('comments', []) + [{'user': username, 'text': comment_text, 'date': datetime.now().strftime('%Y-%m-%d %H:%M:%S')}]
|
| 822 |
+
save_data(data)
|
| 823 |
|
| 824 |
html = '''
|
| 825 |
<!DOCTYPE html>
|
|
|
|
| 832 |
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&display=swap" rel="stylesheet">
|
| 833 |
<style>
|
| 834 |
''' + BASE_STYLE + '''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 835 |
</style>
|
| 836 |
</head>
|
| 837 |
<body>
|
|
|
|
| 839 |
''' + NAV_HTML + '''
|
| 840 |
<button class="theme-toggle" onclick="toggleTheme()">🌙</button>
|
| 841 |
<div class="container">
|
| 842 |
+
<div class="feed-container">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 843 |
{% for post in posts %}
|
| 844 |
+
<div class="post-slide" id="post-{{ post['id'] }}">
|
| 845 |
{% if post['type'] == 'video' %}
|
| 846 |
+
<video class="post-media" controls autoplay muted loop>
|
| 847 |
<source src="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/{{ post['type'] }}s/{{ post['filename'] }}" type="video/mp4">
|
| 848 |
</video>
|
| 849 |
{% else %}
|
| 850 |
+
<img class="post-media" src="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/{{ post['type'] }}s/{{ post['filename'] }}" alt="{{ post['title'] }}">
|
| 851 |
{% endif %}
|
| 852 |
+
<div class="post-overlay">
|
| 853 |
+
<div class="post-info">
|
| 854 |
+
<h2>{{ post['title'] }}</h2>
|
| 855 |
+
<p>{{ post['description']|truncate(100) }}</p>
|
| 856 |
+
<p>By: <a href="{{ url_for('user_profile', username=post['uploader']) }}" class="username-link">{{ post['uploader'] }}</a>
|
| 857 |
+
<span class="status-dot {{ 'online' if is_user_online(post['uploader']) else 'offline' }}"></span> | {{ post['upload_date'] }}</p>
|
| 858 |
+
</div>
|
| 859 |
+
</div>
|
| 860 |
+
<div class="actions">
|
| 861 |
+
<form method="POST" style="display: inline;">
|
| 862 |
+
<input type="hidden" name="post_id" value="{{ post['id'] }}">
|
| 863 |
+
<input type="hidden" name="action" value="like">
|
| 864 |
+
<button type="submit" class="action-btn {% if is_authenticated and username in post.get('likes', []) %}liked{% endif %}" {% if not is_authenticated %}disabled{% endif %}>
|
| 865 |
+
❤️
|
| 866 |
+
</button>
|
| 867 |
+
</form>
|
| 868 |
+
<span class="action-count">{{ post.get('likes', [])|length }}</span>
|
| 869 |
+
<button class="action-btn" onclick="toggleComments('{{ post['id'] }}')">💬</button>
|
| 870 |
+
<span class="action-count">{{ post.get('comments', [])|length }}</span>
|
| 871 |
+
<button class="action-btn" onclick="sharePost('{{ post['id'] }}')">↪️</button>
|
| 872 |
+
</div>
|
| 873 |
+
<div class="comments-container" id="comments-{{ post['id'] }}">
|
| 874 |
+
{% for comment in post.get('comments', []) %}
|
| 875 |
+
<div class="comment">
|
| 876 |
+
<p><strong><a href="{{ url_for('user_profile', username=comment['user']) }}" class="username-link">{{ comment['user'] }}</a></strong>
|
| 877 |
+
<span class="status-dot {{ 'online' if is_user_online(comment['user']) else 'offline' }}"></span> ({{ comment['date'] }}): {{ comment['text'] }}</p>
|
| 878 |
+
</div>
|
| 879 |
+
{% endfor %}
|
| 880 |
+
{% if is_authenticated %}
|
| 881 |
+
<form method="POST" class="comment-form">
|
| 882 |
+
<input type="hidden" name="post_id" value="{{ post['id'] }}">
|
| 883 |
+
<input type="hidden" name="action" value="comment">
|
| 884 |
+
<textarea name="comment" placeholder="Add a comment..." rows="2"></textarea>
|
| 885 |
+
<button type="submit" class="btn">Send</button>
|
| 886 |
+
</form>
|
| 887 |
+
{% endif %}
|
| 888 |
+
</div>
|
| 889 |
+
</div>
|
| 890 |
{% endfor %}
|
| 891 |
</div>
|
| 892 |
</div>
|
|
|
|
| 899 |
document.body.classList.toggle('dark');
|
| 900 |
localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
|
| 901 |
}
|
| 902 |
+
function toggleComments(postId) {
|
| 903 |
+
const comments = document.getElementById(`comments-${postId}`);
|
| 904 |
+
comments.classList.toggle('active');
|
| 905 |
+
}
|
| 906 |
+
function sharePost(postId) {
|
| 907 |
+
const url = `${window.location.origin}/post/${postId}`;
|
| 908 |
+
navigator.clipboard.writeText(url).then(() => alert('Link copied!'));
|
| 909 |
+
}
|
| 910 |
+
function openModal(src) {
|
| 911 |
document.getElementById('imageModal').style.display = 'flex';
|
| 912 |
document.getElementById('modalImage').src = src;
|
|
|
|
| 913 |
}
|
| 914 |
function closeModal(event) {
|
| 915 |
if (event.target.tagName !== 'IMG') document.getElementById('imageModal').style.display = 'none';
|
| 916 |
}
|
| 917 |
window.onload = () => {
|
| 918 |
if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
|
| 919 |
+
const feed = document.querySelector('.feed-container');
|
| 920 |
+
feed.addEventListener('scroll', () => {
|
| 921 |
+
const slides = document.querySelectorAll('.post-slide');
|
| 922 |
+
slides.forEach(slide => {
|
| 923 |
+
const rect = slide.getBoundingClientRect();
|
| 924 |
+
if (rect.top >= 0 && rect.bottom <= window.innerHeight) {
|
| 925 |
+
const postId = slide.id.split('-')[1];
|
| 926 |
+
fetch('/increment_view/' + postId, { method: 'POST' });
|
| 927 |
+
}
|
| 928 |
+
});
|
| 929 |
});
|
| 930 |
};
|
| 931 |
</script>
|
| 932 |
</body>
|
| 933 |
</html>
|
| 934 |
'''
|
| 935 |
+
return render_template_string(html, posts=posts, is_authenticated=is_authenticated, username=username, repo_id=REPO_ID, unread_count=unread_count, user_count=user_count, private_unread_count=private_unread_count, is_online=is_online, is_user_online=lambda u: is_user_online(data, u))
|
| 936 |
|
| 937 |
@app.route('/post/<post_id>', methods=['GET', 'POST'])
|
| 938 |
def post_page(post_id):
|