feat: added homepage feed showing followed accounts
This commit is contained in:
@@ -37,6 +37,10 @@ function fetchAndParse(url) {
|
||||
window.onload = function () {
|
||||
const url = window.location.pathname;
|
||||
const isTweet = url.indexOf("/status/") !== -1;
|
||||
const isHomepage = url === "/" || url === "";
|
||||
|
||||
if (isHomepage) return;
|
||||
|
||||
const isIncompleteThread =
|
||||
isTweet && document.querySelector(".timeline-item.more-replies") != null;
|
||||
|
||||
|
||||
@@ -6,8 +6,9 @@ from os import getEnv
|
||||
|
||||
import jester
|
||||
|
||||
import types, config, prefs, formatters, redis_cache, http_pool, auth
|
||||
import views/[general, about]
|
||||
import types, config, prefs, formatters, redis_cache, http_pool, auth, query
|
||||
import views/[general, about, search, profile]
|
||||
import karax/[karaxdsl, vdom]
|
||||
import routes/[
|
||||
preferences, timeline, status, media, search, rss, list, debug,
|
||||
unsupported, embed, resolver, router_utils, follow]
|
||||
@@ -98,6 +99,42 @@ settings:
|
||||
|
||||
routes:
|
||||
get "/":
|
||||
let prefs = cookiePrefs()
|
||||
|
||||
if prefs.following.len > 0:
|
||||
let
|
||||
cursor = getCursor()
|
||||
|
||||
var homepageQuery = initQuery(params(request))
|
||||
if @"f".len == 0:
|
||||
homepageQuery.kind = tweets
|
||||
|
||||
homepageQuery.fromUser = prefs.following
|
||||
|
||||
let
|
||||
timeline = await getGraphTweetSearch(homepageQuery, cursor)
|
||||
html = renderHomepageTimeline(timeline, prefs, getPath())
|
||||
|
||||
var users: seq[User]
|
||||
for username in prefs.following:
|
||||
try:
|
||||
let user = await getCachedUser(username)
|
||||
users.add(user)
|
||||
except:
|
||||
continue
|
||||
|
||||
let homepageHtml = buildHtml(tdiv(class="homepage-container")):
|
||||
tdiv(class="following-column"):
|
||||
tdiv(class="profile-cards"):
|
||||
for user in users:
|
||||
let currentPath = if @"f".len > 0: "/?f=" & @"f" else: "/"
|
||||
renderUserCard(user, prefs, currentPath)
|
||||
|
||||
tdiv(class="timeline"):
|
||||
html
|
||||
|
||||
resp renderMain(homepageHtml, request, cfg, prefs, "Following")
|
||||
else:
|
||||
resp renderMain(renderSearch(), request, cfg, themePrefs())
|
||||
|
||||
get "/about":
|
||||
|
||||
@@ -59,7 +59,10 @@ proc genQueryParam*(query: Query): string =
|
||||
if i < query.fromUser.high:
|
||||
param &= "OR "
|
||||
|
||||
if query.fromUser.len > 0 and query.kind in {posts, media}:
|
||||
if query.fromUser.len > 0:
|
||||
if query.kind in {posts, media}:
|
||||
param &= "filter:self_threads OR -filter:replies "
|
||||
elif query.kind == tweets and query.fromUser.len > 1:
|
||||
param &= "filter:self_threads OR -filter:replies "
|
||||
|
||||
if "nativeretweets" notin query.excludes:
|
||||
|
||||
34
src/sass/homepage.scss
Normal file
34
src/sass/homepage.scss
Normal file
@@ -0,0 +1,34 @@
|
||||
@import '_variables';
|
||||
@import '_mixins';
|
||||
|
||||
.homepage-container {
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.following-column {
|
||||
width: 280px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.profile-cards {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.homepage-container .timeline-container > .timeline > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 887px) {
|
||||
.homepage-container {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.following-column {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
@import 'inputs';
|
||||
@import 'timeline';
|
||||
@import 'search';
|
||||
@import 'homepage';
|
||||
|
||||
body {
|
||||
// colors
|
||||
|
||||
15
src/views/homepage.nim
Normal file
15
src/views/homepage.nim
Normal file
@@ -0,0 +1,15 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
import karax/[karaxdsl, vdom]
|
||||
|
||||
import profile
|
||||
import ".."/[types]
|
||||
|
||||
proc renderHomepage*(users: seq[User]; prefs: Prefs; path: string): VNode =
|
||||
buildHtml(tdiv(class="homepage-container")):
|
||||
tdiv(class="following-column"):
|
||||
tdiv(class="profile-cards"):
|
||||
for user in users:
|
||||
renderUserCard(user, prefs, path)
|
||||
|
||||
tdiv(class="timeline"):
|
||||
tdiv(id="timeline-container")
|
||||
@@ -50,6 +50,21 @@ proc renderTweetSearch*(results: Timeline; prefs: Prefs; path: string;
|
||||
|
||||
renderTimelineTweets(results, prefs, path, pinned)
|
||||
|
||||
proc renderHomepageTabs*(query: Query): VNode =
|
||||
buildHtml(ul(class="tab")):
|
||||
li(class=if query.kind == tweets: "tab-item active" else: "tab-item"):
|
||||
a(href="/?f=tweets"): text "Tweets"
|
||||
|
||||
li(class=if query.kind == replies: "tab-item active" else: "tab-item"):
|
||||
a(href="/?f=replies"): text "Tweets & Replies"
|
||||
|
||||
proc renderHomepageTimeline*(results: Timeline; prefs: Prefs; path: string): VNode =
|
||||
let query = results.query
|
||||
buildHtml(tdiv(class="timeline-container")):
|
||||
renderHomepageTabs(query)
|
||||
|
||||
renderTimelineTweets(results, prefs, path)
|
||||
|
||||
proc renderUserSearch*(results: Result[User]; prefs: Prefs; path: string): VNode =
|
||||
buildHtml(tdiv(class="timeline-container")):
|
||||
renderSearchTabs(results.query)
|
||||
|
||||
Reference in New Issue
Block a user