feat: added homepage feed showing followed accounts
This commit is contained in:
@@ -37,6 +37,10 @@ function fetchAndParse(url) {
|
|||||||
window.onload = function () {
|
window.onload = function () {
|
||||||
const url = window.location.pathname;
|
const url = window.location.pathname;
|
||||||
const isTweet = url.indexOf("/status/") !== -1;
|
const isTweet = url.indexOf("/status/") !== -1;
|
||||||
|
const isHomepage = url === "/" || url === "";
|
||||||
|
|
||||||
|
if (isHomepage) return;
|
||||||
|
|
||||||
const isIncompleteThread =
|
const isIncompleteThread =
|
||||||
isTweet && document.querySelector(".timeline-item.more-replies") != null;
|
isTweet && document.querySelector(".timeline-item.more-replies") != null;
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,9 @@ from os import getEnv
|
|||||||
|
|
||||||
import jester
|
import jester
|
||||||
|
|
||||||
import types, config, prefs, formatters, redis_cache, http_pool, auth
|
import types, config, prefs, formatters, redis_cache, http_pool, auth, query
|
||||||
import views/[general, about]
|
import views/[general, about, search, profile]
|
||||||
|
import karax/[karaxdsl, vdom]
|
||||||
import routes/[
|
import routes/[
|
||||||
preferences, timeline, status, media, search, rss, list, debug,
|
preferences, timeline, status, media, search, rss, list, debug,
|
||||||
unsupported, embed, resolver, router_utils, follow]
|
unsupported, embed, resolver, router_utils, follow]
|
||||||
@@ -98,7 +99,43 @@ settings:
|
|||||||
|
|
||||||
routes:
|
routes:
|
||||||
get "/":
|
get "/":
|
||||||
resp renderMain(renderSearch(), request, cfg, themePrefs())
|
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":
|
get "/about":
|
||||||
resp renderMain(renderAbout(), request, cfg, themePrefs())
|
resp renderMain(renderAbout(), request, cfg, themePrefs())
|
||||||
|
|||||||
@@ -59,8 +59,11 @@ proc genQueryParam*(query: Query): string =
|
|||||||
if i < query.fromUser.high:
|
if i < query.fromUser.high:
|
||||||
param &= "OR "
|
param &= "OR "
|
||||||
|
|
||||||
if query.fromUser.len > 0 and query.kind in {posts, media}:
|
if query.fromUser.len > 0:
|
||||||
param &= "filter:self_threads OR -filter:replies "
|
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:
|
if "nativeretweets" notin query.excludes:
|
||||||
param &= "include:nativeretweets "
|
param &= "include:nativeretweets "
|
||||||
|
|||||||
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 'inputs';
|
||||||
@import 'timeline';
|
@import 'timeline';
|
||||||
@import 'search';
|
@import 'search';
|
||||||
|
@import 'homepage';
|
||||||
|
|
||||||
body {
|
body {
|
||||||
// colors
|
// 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)
|
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 =
|
proc renderUserSearch*(results: Result[User]; prefs: Prefs; path: string): VNode =
|
||||||
buildHtml(tdiv(class="timeline-container")):
|
buildHtml(tdiv(class="timeline-container")):
|
||||||
renderSearchTabs(results.query)
|
renderSearchTabs(results.query)
|
||||||
|
|||||||
Reference in New Issue
Block a user