diff --git a/nitter.example.conf b/nitter.example.conf index 95802e8..2e3d6df 100644 --- a/nitter.example.conf +++ b/nitter.example.conf @@ -27,6 +27,7 @@ enableDebug = false # enable request logs and debug endpoints (/.sessions) logLevel = "info" # log level (debug, info, warn, error, fatal) proxy = "" # http/https url, SOCKS proxies are not supported proxyAuth = "" +defaultFollowedAccounts = "eff,fsf" # default accounts to show when user follows none # Change default preferences here, see src/prefs_impl.nim for a complete list [Preferences] diff --git a/src/config.nim b/src/config.nim index 7325a65..f48ad8a 100644 --- a/src/config.nim +++ b/src/config.nim @@ -1,6 +1,6 @@ # SPDX-License-Identifier: AGPL-3.0-only import parsecfg except Config -import types, strutils +import types, strutils, sequtils proc get*[T](config: parseCfg.Config; section, key: string; default: T): T = let val = config.getSectionValue(section, key) @@ -9,6 +9,7 @@ proc get*[T](config: parseCfg.Config; section, key: string; default: T): T = when T is int: parseInt(val) elif T is bool: parseBool(val) elif T is string: val + elif T is seq[string]: val.split(',').mapIt(it.strip()) proc getConfig*(path: string): (Config, parseCfg.Config) = var cfg = loadConfig(path) @@ -41,7 +42,8 @@ proc getConfig*(path: string): (Config, parseCfg.Config) = enableDebug: cfg.get("Config", "enableDebug", false), logLevel: cfg.get("Config", "logLevel", ""), proxy: cfg.get("Config", "proxy", ""), - proxyAuth: cfg.get("Config", "proxyAuth", "") + proxyAuth: cfg.get("Config", "proxyAuth", ""), + defaultFollowedAccounts: cfg.get("Config", "defaultFollowedAccounts", @["eff", "fsf"]) ) return (conf, cfg) diff --git a/src/nitter.nim b/src/nitter.nim index f1d176f..e102600 100644 --- a/src/nitter.nim +++ b/src/nitter.nim @@ -101,22 +101,28 @@ routes: get "/": let prefs = cookiePrefs() - if prefs.following.len > 0: + if prefs.following.len > 0 or cfg.defaultFollowedAccounts.len > 0: let cursor = getCursor() + accounts = if prefs.following.len > 0: prefs.following else: cfg.defaultFollowedAccounts + isDefault = prefs.following.len == 0 + currentPath = if @"f".len > 0: "/?f=" & @"f" else: "/" var homepageQuery = initQuery(params(request)) if @"f".len == 0: homepageQuery.kind = tweets - homepageQuery.fromUser = prefs.following + homepageQuery.fromUser = accounts let timeline = await getGraphTweetSearch(homepageQuery, cursor) - html = renderHomepageTimeline(timeline, prefs, getPath()) + html = if isDefault: + renderDefaultTimeline(timeline, prefs, getPath()) + else: + renderHomepageTimeline(timeline, prefs, getPath()) var users: seq[User] - for username in prefs.following: + for username in accounts: try: let user = await getCachedUser(username) users.add(user) @@ -127,7 +133,6 @@ routes: 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"): diff --git a/src/sass/timeline.scss b/src/sass/timeline.scss index 85c4be8..6b1992b 100644 --- a/src/sass/timeline.scss +++ b/src/sass/timeline.scss @@ -26,6 +26,25 @@ button { float: unset; } + + &.timeline-default { + background-color: var(--bg_panel); + border-bottom: 1px solid var(--bg_elements); + margin-bottom: 5px; + + .timeline-default-message { + color: var(--fg_color); + font-size: 16px; + font-weight: normal; + margin: 0; + padding: 5px; + + strong { + font-weight: bold; + color: var(--accent); + } + } + } } .timeline-banner img { diff --git a/src/types.nim b/src/types.nim index fbd5f89..cb5ff7c 100644 --- a/src/types.nim +++ b/src/types.nim @@ -290,6 +290,7 @@ type logLevel*: string proxy*: string proxyAuth*: string + defaultFollowedAccounts*: seq[string] rssCacheTime*: int listCacheTime*: int diff --git a/src/views/search.nim b/src/views/search.nim index 4fb6d32..e88ae24 100644 --- a/src/views/search.nim +++ b/src/views/search.nim @@ -65,6 +65,19 @@ proc renderHomepageTimeline*(results: Timeline; prefs: Prefs; path: string): VNo renderTimelineTweets(results, prefs, path) +proc renderDefaultTimeline*(results: Timeline; prefs: Prefs; path: string): VNode = + let query = results.query + buildHtml(tdiv(class="timeline-container")): + tdiv(class="timeline-header timeline-default"): + h2(class="timeline-default-message"): + text "Follow people to populate your " + strong: text "own" + text " feed" + + renderHomepageTabs(query) + + renderTimelineTweets(results, prefs, path) + proc renderUserSearch*(results: Result[User]; prefs: Prefs; path: string): VNode = buildHtml(tdiv(class="timeline-container")): renderSearchTabs(results.query)