commit
510abb9b50
30 changed files with 252 additions and 119 deletions
|
@ -10,7 +10,7 @@ Inspired by the [invidio.us](https://github.com/omarroth/invidious) project.
|
||||||
- Prevents Twitter from tracking your IP or JavaScript fingerprint
|
- Prevents Twitter from tracking your IP or JavaScript fingerprint
|
||||||
- Unofficial API (no rate limits or developer account required)
|
- Unofficial API (no rate limits or developer account required)
|
||||||
- AGPLv3 licensed, no proprietary instances permitted
|
- AGPLv3 licensed, no proprietary instances permitted
|
||||||
- Dark theme
|
- Themes
|
||||||
- Lightweight (for [@nim_lang](https://twitter.com/nim_lang), 36KB vs 580KB from twitter.com)
|
- Lightweight (for [@nim_lang](https://twitter.com/nim_lang), 36KB vs 580KB from twitter.com)
|
||||||
- Native RSS feeds
|
- Native RSS feeds
|
||||||
- Mobile support (responsive design)
|
- Mobile support (responsive design)
|
||||||
|
@ -21,7 +21,6 @@ Inspired by the [invidio.us](https://github.com/omarroth/invidious) project.
|
||||||
- More caching (waiting for [moigagoo/norm#19](https://github.com/moigagoo/norm/pull/19))
|
- More caching (waiting for [moigagoo/norm#19](https://github.com/moigagoo/norm/pull/19))
|
||||||
- Simple account system with customizable feed
|
- Simple account system with customizable feed
|
||||||
- Json API endpoints
|
- Json API endpoints
|
||||||
- Themes
|
|
||||||
- Nitter logo
|
- Nitter logo
|
||||||
- Emoji support (WIP, uses native font for now)
|
- Emoji support (WIP, uses native font for now)
|
||||||
|
|
||||||
|
|
|
@ -9,3 +9,6 @@ hostname = "nitter.net"
|
||||||
[Cache]
|
[Cache]
|
||||||
directory = "./tmp"
|
directory = "./tmp"
|
||||||
profileMinutes = 10 # how long to cache profiles
|
profileMinutes = 10 # how long to cache profiles
|
||||||
|
|
||||||
|
[Config]
|
||||||
|
defaultTheme = "Dark"
|
||||||
|
|
|
@ -11,7 +11,7 @@ bin = @["nitter"]
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
|
||||||
requires "nim >= 0.19.9"
|
requires "nim >= 0.19.9"
|
||||||
requires "norm >= 1.0.17"
|
requires "norm#head"
|
||||||
requires "https://github.com/dom96/httpbeast#head"
|
requires "https://github.com/dom96/httpbeast#head"
|
||||||
requires "jester >= 0.4.3"
|
requires "jester >= 0.4.3"
|
||||||
requires "regex >= 0.11.2"
|
requires "regex >= 0.11.2"
|
||||||
|
|
3
public/css/themes/dark.css
Normal file
3
public/css/themes/dark.css
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
body {
|
||||||
|
/* uses default values */
|
||||||
|
}
|
37
public/css/themes/light.css
Normal file
37
public/css/themes/light.css
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
body {
|
||||||
|
--bg_color: #E6ECF0;
|
||||||
|
--fg_color: #0F0F0F;
|
||||||
|
--fg_faded: #657786;
|
||||||
|
--fg_dark: var(--fg_faded);
|
||||||
|
--fg_nav: var(--accent);
|
||||||
|
|
||||||
|
--bg_panel: #FFFFFF;
|
||||||
|
--bg_elements: #FDFDFD;
|
||||||
|
--bg_overlays: #FFFFFF;
|
||||||
|
--bg_hover: #F5F8FA;
|
||||||
|
|
||||||
|
--grey: var(--fg_faded);
|
||||||
|
--dark_grey: #D6D6D6;
|
||||||
|
--darker_grey: #CECECE;
|
||||||
|
--darkest_grey: #ECECEC;
|
||||||
|
--border_grey: #E6ECF0;
|
||||||
|
|
||||||
|
--accent: #1DA1F2;
|
||||||
|
--accent_light: #A0EDFF;
|
||||||
|
--accent_dark: var(--accent);
|
||||||
|
--accent_border: #1DA1F296;
|
||||||
|
|
||||||
|
--play_button: #D84D4D;
|
||||||
|
--play_button_hover: #FF6C60;
|
||||||
|
|
||||||
|
--more_replies_dots: #0199F7;
|
||||||
|
--error_red: #FF7266;
|
||||||
|
|
||||||
|
--verified_blue: var(--accent);
|
||||||
|
--icon_text: ##F8F8F2;
|
||||||
|
|
||||||
|
--tab: var(--accent);
|
||||||
|
--tab_selected: #000000;
|
||||||
|
|
||||||
|
--profile_stat: var(--fg_dark);
|
||||||
|
}
|
|
@ -21,5 +21,7 @@ proc getConfig*(path: string): Config =
|
||||||
hostname: cfg.get("Server", "hostname", "nitter.net"),
|
hostname: cfg.get("Server", "hostname", "nitter.net"),
|
||||||
|
|
||||||
cacheDir: cfg.get("Cache", "directory", "/tmp/nitter"),
|
cacheDir: cfg.get("Cache", "directory", "/tmp/nitter"),
|
||||||
profileCacheTime: cfg.get("Cache", "profileMinutes", 10)
|
profileCacheTime: cfg.get("Cache", "profileMinutes", 10),
|
||||||
|
|
||||||
|
defaultTheme: cfg.get("Config", "defaultTheme", "Dark")
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,6 +14,10 @@ static:
|
||||||
if missing.len > 0:
|
if missing.len > 0:
|
||||||
raiseAssert("{$1} missing from the Prefs type" % missing.join(", "))
|
raiseAssert("{$1} missing from the Prefs type" % missing.join(", "))
|
||||||
|
|
||||||
|
template safeAddColumn(field: typedesc): untyped =
|
||||||
|
try: field.addColumn
|
||||||
|
except DbError: discard
|
||||||
|
|
||||||
dbFromTypes("prefs.db", "", "", "", [Prefs])
|
dbFromTypes("prefs.db", "", "", "", [Prefs])
|
||||||
|
|
||||||
withDb:
|
withDb:
|
||||||
|
@ -21,10 +25,12 @@ withDb:
|
||||||
createTables()
|
createTables()
|
||||||
except DbError:
|
except DbError:
|
||||||
discard
|
discard
|
||||||
|
Prefs.theme.safeAddColumn
|
||||||
|
|
||||||
proc getDefaultPrefs(hostname: string): Prefs =
|
proc getDefaultPrefs(cfg: Config): Prefs =
|
||||||
result = genDefaultPrefs()
|
result = genDefaultPrefs()
|
||||||
result.replaceTwitter = hostname
|
result.replaceTwitter = cfg.hostname
|
||||||
|
result.theme = cfg.defaultTheme
|
||||||
|
|
||||||
proc cache*(prefs: var Prefs) =
|
proc cache*(prefs: var Prefs) =
|
||||||
withDb:
|
withDb:
|
||||||
|
@ -35,18 +41,18 @@ proc cache*(prefs: var Prefs) =
|
||||||
except AssertionError, KeyError:
|
except AssertionError, KeyError:
|
||||||
prefs.insert()
|
prefs.insert()
|
||||||
|
|
||||||
proc getPrefs*(id, hostname: string): Prefs =
|
proc getPrefs*(id: string; cfg: Config): Prefs =
|
||||||
if id.len == 0:
|
if id.len == 0:
|
||||||
return getDefaultPrefs(hostname)
|
return getDefaultPrefs(cfg)
|
||||||
|
|
||||||
withDb:
|
withDb:
|
||||||
try:
|
try:
|
||||||
result.getOne("id = ?", id)
|
result.getOne("id = ?", id)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
result = getDefaultPrefs(hostname)
|
result = getDefaultPrefs(cfg)
|
||||||
|
|
||||||
proc resetPrefs*(prefs: var Prefs; hostname: string) =
|
proc resetPrefs*(prefs: var Prefs; cfg: Config) =
|
||||||
var defPrefs = getDefaultPrefs(hostname)
|
var defPrefs = getDefaultPrefs(cfg)
|
||||||
defPrefs.id = prefs.id
|
defPrefs.id = prefs.id
|
||||||
cache(defPrefs)
|
cache(defPrefs)
|
||||||
prefs = defPrefs
|
prefs = defPrefs
|
||||||
|
|
|
@ -51,6 +51,9 @@ const prefList*: OrderedTable[string, seq[Pref]] = {
|
||||||
],
|
],
|
||||||
|
|
||||||
"Display": @[
|
"Display": @[
|
||||||
|
Pref(kind: select, name: "theme", label: "Theme",
|
||||||
|
defaultOption: "Dark"),
|
||||||
|
|
||||||
Pref(kind: checkbox, name: "hideTweetStats",
|
Pref(kind: checkbox, name: "hideTweetStats",
|
||||||
label: "Hide tweet stats (replies, retweets, likes)",
|
label: "Hide tweet stats (replies, retweets, likes)",
|
||||||
defaultState: false),
|
defaultState: false),
|
||||||
|
@ -94,10 +97,12 @@ macro genUpdatePrefs*(): untyped =
|
||||||
of input:
|
of input:
|
||||||
result.add quote do: prefs.`ident` = xmltree.escape(strip(`value`))
|
result.add quote do: prefs.`ident` = xmltree.escape(strip(`value`))
|
||||||
of select:
|
of select:
|
||||||
|
let name = pref.name
|
||||||
let options = pref.options
|
let options = pref.options
|
||||||
let default = pref.defaultOption
|
let default = pref.defaultOption
|
||||||
result.add quote do:
|
result.add quote do:
|
||||||
if `value` in `options`: prefs.`ident` = `value`
|
if `name` == "theme": prefs.`ident` = `value`
|
||||||
|
elif `value` in `options`: prefs.`ident` = `value`
|
||||||
else: prefs.`ident` = `default`
|
else: prefs.`ident` = `default`
|
||||||
|
|
||||||
result.add quote do:
|
result.add quote do:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import strutils, uri
|
import strutils, uri, os, algorithm
|
||||||
|
|
||||||
import jester
|
import jester
|
||||||
|
|
||||||
|
@ -8,13 +8,18 @@ import ../views/[general, preferences]
|
||||||
|
|
||||||
export preferences
|
export preferences
|
||||||
|
|
||||||
|
proc findThemes*(dir: string): seq[string] =
|
||||||
|
for kind, path in walkDir(dir / "css" / "themes"):
|
||||||
|
result.add path.splitFile.name.capitalizeAscii
|
||||||
|
sort(result)
|
||||||
|
|
||||||
proc createPrefRouter*(cfg: Config) =
|
proc createPrefRouter*(cfg: Config) =
|
||||||
router preferences:
|
router preferences:
|
||||||
template savePrefs(): untyped =
|
template savePrefs(): untyped =
|
||||||
setCookie("preferences", $prefs.id, daysForward(360), httpOnly=true, secure=cfg.useHttps)
|
setCookie("preferences", $prefs.id, daysForward(360), httpOnly=true, secure=cfg.useHttps)
|
||||||
|
|
||||||
get "/settings":
|
get "/settings":
|
||||||
let html = renderPreferences(cookiePrefs(), refPath())
|
let html = renderPreferences(cookiePrefs(), refPath(), findThemes(cfg.staticDir))
|
||||||
resp renderMain(html, request, cfg, "Preferences")
|
resp renderMain(html, request, cfg, "Preferences")
|
||||||
|
|
||||||
get "/settings/@i?":
|
get "/settings/@i?":
|
||||||
|
@ -28,7 +33,7 @@ proc createPrefRouter*(cfg: Config) =
|
||||||
|
|
||||||
post "/resetprefs":
|
post "/resetprefs":
|
||||||
var prefs = cookiePrefs()
|
var prefs = cookiePrefs()
|
||||||
resetPrefs(prefs, cfg.hostname)
|
resetPrefs(prefs, cfg)
|
||||||
savePrefs()
|
savePrefs()
|
||||||
redirect($(parseUri("/settings") ? filterParams(request.params)))
|
redirect($(parseUri("/settings") ? filterParams(request.params)))
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import ../utils, ../prefs
|
||||||
export utils, prefs
|
export utils, prefs
|
||||||
|
|
||||||
template cookiePrefs*(): untyped {.dirty.} =
|
template cookiePrefs*(): untyped {.dirty.} =
|
||||||
getPrefs(request.cookies.getOrDefault("preferences"), cfg.hostname)
|
getPrefs(request.cookies.getOrDefault("preferences"), cfg)
|
||||||
|
|
||||||
template getPath*(): untyped {.dirty.} =
|
template getPath*(): untyped {.dirty.} =
|
||||||
$(parseUri(request.path) ? filterParams(request.params))
|
$(parseUri(request.path) ? filterParams(request.params))
|
||||||
|
|
|
@ -7,15 +7,15 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.error-panel {
|
.error-panel {
|
||||||
@include center-panel($error_red);
|
@include center-panel(var(--error_red));
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-bar > form {
|
.search-bar > form {
|
||||||
@include center-panel($darkest-grey);
|
@include center-panel(var(--darkest_grey));
|
||||||
|
|
||||||
button {
|
button {
|
||||||
background: #303030;
|
background: var(--bg_elements);
|
||||||
color: $fg_color;
|
color: var(--fg_color);
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -27,8 +27,8 @@
|
||||||
input {
|
input {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: $bg_elements;
|
background: var(--bg_elements);
|
||||||
color: $fg_color;
|
color: var(--fg_color);
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
|
|
|
@ -19,11 +19,11 @@
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.overlay-circle {
|
.overlay-circle {
|
||||||
border-color: $accent;
|
border-color: var(--play_button_hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlay-triangle {
|
.overlay-triangle {
|
||||||
border-color: transparent transparent transparent $accent;
|
border-color: transparent transparent transparent var(--play_button_hover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,11 +51,11 @@
|
||||||
|
|
||||||
@mixin input-colors {
|
@mixin input-colors {
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: $accent;
|
border-color: var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
border-color: $accent_light;
|
border-color: var(--accent_light);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,13 @@
|
||||||
$bg_color: #0F0F0F;
|
$bg_color: #0F0F0F;
|
||||||
$fg_color: #F8F8F2;
|
$fg_color: #F8F8F2;
|
||||||
$fg_faded: #F8F8F2CF;
|
$fg_faded: #F8F8F2CF;
|
||||||
$fg_dark: #9d9da0;
|
$fg_dark: #FF6C60;
|
||||||
|
$fg_nav: #FF6C60;
|
||||||
|
|
||||||
$bg_panel: #161616;
|
$bg_panel: #161616;
|
||||||
$bg_elements: #121212;
|
$bg_elements: #121212;
|
||||||
$bg_overlays: #1F1F1F;
|
$bg_overlays: #1F1F1F;
|
||||||
|
$bg_hover: #1A1A1A;
|
||||||
|
|
||||||
$grey: #888889;
|
$grey: #888889;
|
||||||
$dark_grey: #404040;
|
$dark_grey: #404040;
|
||||||
|
@ -19,11 +21,17 @@ $accent_light: #FFACA0;
|
||||||
$accent_dark: #8A3731;
|
$accent_dark: #8A3731;
|
||||||
$accent_border: #FF6C6091;
|
$accent_border: #FF6C6091;
|
||||||
|
|
||||||
$play_button_red: #D8574D;
|
$play_button: #D8574D;
|
||||||
|
$play_button_hover: #FF6C60;
|
||||||
|
|
||||||
$more_replies_dots: #AD433B;
|
$more_replies_dots: #AD433B;
|
||||||
$error_red: #420A05;
|
$error_red: #420A05;
|
||||||
|
|
||||||
$verified_blue: #1DA1F2;
|
$verified_blue: #1DA1F2;
|
||||||
|
$icon_text: $fg_color;
|
||||||
|
|
||||||
|
$tab: $fg_color;
|
||||||
|
$tab_selected: $accent;
|
||||||
|
|
||||||
$shadow: rgba(0,0,0,.6);
|
$shadow: rgba(0,0,0,.6);
|
||||||
$shadow_dark: rgba(0,0,0,.2);
|
$shadow_dark: rgba(0,0,0,.2);
|
||||||
|
|
|
@ -9,8 +9,45 @@
|
||||||
@import 'search';
|
@import 'search';
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: $bg_color;
|
// colors
|
||||||
color: $fg_color;
|
--bg_color: #{$bg_color};
|
||||||
|
--fg_color: #{$fg_color};
|
||||||
|
--fg_faded: #{$fg_faded};
|
||||||
|
--fg_dark: #{$fg_dark};
|
||||||
|
--fg_nav: #{$fg_nav};
|
||||||
|
|
||||||
|
--bg_panel: #{$bg_panel};
|
||||||
|
--bg_elements: #{$bg_elements};
|
||||||
|
--bg_overlays: #{$bg_overlays};
|
||||||
|
--bg_hover: #{$bg_hover};
|
||||||
|
|
||||||
|
--grey: #{$grey};
|
||||||
|
--dark_grey: #{$dark_grey};
|
||||||
|
--darker_grey: #{$darker_grey};
|
||||||
|
--darkest_grey: #{$darkest_grey};
|
||||||
|
--border_grey: #{$border_grey};
|
||||||
|
|
||||||
|
--accent: #{$accent};
|
||||||
|
--accent_light: #{$accent_light};
|
||||||
|
--accent_dark: #{$accent_dark};
|
||||||
|
--accent_border: #{$accent_border};
|
||||||
|
|
||||||
|
--play_button: #{$play_button};
|
||||||
|
--play_button_hover: #{$play_button_hover};
|
||||||
|
|
||||||
|
--more_replies_dots: #{$more_replies_dots};
|
||||||
|
--error_red: #{$error_red};
|
||||||
|
|
||||||
|
--verified_blue: #{$verified_blue};
|
||||||
|
--icon_text: #{$icon_text};
|
||||||
|
|
||||||
|
--tab: #{$fg_color};
|
||||||
|
--tab_selected: #{$accent};
|
||||||
|
|
||||||
|
--profile_stat: #{$fg_color};
|
||||||
|
|
||||||
|
background-color: var(--bg_color);
|
||||||
|
color: var(--fg_color);
|
||||||
font-family: $font_0, $font_1, $font_2, $font_3;
|
font-family: $font_0, $font_1, $font_2, $font_3;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
|
@ -36,7 +73,7 @@ p {
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: $accent;
|
color: var(--accent);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
|
@ -54,7 +91,7 @@ legend {
|
||||||
padding: .6em 0 .3em 0;
|
padding: .6em 0 .3em 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
border-bottom: 1px solid $border_grey;
|
border-bottom: 1px solid var(--border_grey);
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +117,7 @@ ul {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
background-color: $bg_overlays;
|
background-color: var(--bg_overlays);
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
align-self: start;
|
align-self: start;
|
||||||
|
|
||||||
|
@ -91,8 +128,8 @@ ul {
|
||||||
}
|
}
|
||||||
|
|
||||||
.verified-icon {
|
.verified-icon {
|
||||||
color: $fg_color;
|
color: var(--icon_text);
|
||||||
background-color: $verified_blue;
|
background-color: var(--verified_blue);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
margin: 2px 0 3px 3px;
|
margin: 2px 0 3px 3px;
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
|
|
||||||
button {
|
button {
|
||||||
@include input-colors;
|
@include input-colors;
|
||||||
background-color: $bg_elements;
|
background-color: var(--bg_elements);
|
||||||
color: $fg_color;
|
color: var(--fg_color);
|
||||||
border: 1px solid $accent_border;
|
border: 1px solid var(--accent_border);
|
||||||
padding: 3px 6px;
|
padding: 3px 6px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -13,12 +13,13 @@ button {
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"],
|
input[type="text"],
|
||||||
input[type="date"] {
|
input[type="date"],
|
||||||
|
select {
|
||||||
@include input-colors;
|
@include input-colors;
|
||||||
background-color: $bg_elements;
|
background-color: var(--bg_elements);
|
||||||
padding: 1px 4px;
|
padding: 1px 4px;
|
||||||
color: $fg_color;
|
color: var(--fg_color);
|
||||||
border: 1px solid $accent_border;
|
border: 1px solid var(--accent_border);
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
@ -40,8 +41,8 @@ input::-webkit-calendar-picker-indicator {
|
||||||
input::-webkit-datetime-edit-day-field:focus,
|
input::-webkit-datetime-edit-day-field:focus,
|
||||||
input::-webkit-datetime-edit-month-field:focus,
|
input::-webkit-datetime-edit-month-field:focus,
|
||||||
input::-webkit-datetime-edit-year-field:focus {
|
input::-webkit-datetime-edit-year-field:focus {
|
||||||
background-color: $accent;
|
background-color: var(--accent);
|
||||||
color: $fg_color;
|
color: var(--fg_color);
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +65,7 @@ input::-webkit-datetime-edit-year-field:focus {
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-button button {
|
.icon-button button {
|
||||||
color: $accent;
|
color: var(--accent);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -73,7 +74,7 @@ input::-webkit-datetime-edit-year-field:focus {
|
||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $accent_light;
|
color: var(--accent_light);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,8 +84,8 @@ input::-webkit-datetime-edit-year-field:focus {
|
||||||
right: 0;
|
right: 0;
|
||||||
height: 17px;
|
height: 17px;
|
||||||
width: 17px;
|
width: 17px;
|
||||||
background-color: $bg_elements;
|
background-color: var(--bg_elements);
|
||||||
border: 1px solid $accent_border;
|
border: 1px solid var(--accent_border);
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
content: "";
|
content: "";
|
||||||
|
@ -114,11 +115,11 @@ input::-webkit-datetime-edit-year-field:focus {
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover input ~ .checkbox {
|
&:hover input ~ .checkbox {
|
||||||
border-color: $accent;
|
border-color: var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active input ~ .checkbox {
|
&:active input ~ .checkbox {
|
||||||
border-color: $accent_light;
|
border-color: var(--accent_light);
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox:after {
|
.checkbox:after {
|
||||||
|
@ -143,6 +144,16 @@ input::-webkit-datetime-edit-year-field:focus {
|
||||||
padding-right: 135px;
|
padding-right: 135px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
display: block;
|
||||||
|
-moz-appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
input[type="text"] {
|
input[type="text"] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
|
|
@ -4,12 +4,16 @@ nav {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
background-color: $bg_overlays;
|
background-color: var(--bg_overlays);
|
||||||
box-shadow: 0 0 4px $shadow;
|
box-shadow: 0 0 4px $shadow;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
|
|
||||||
|
a, .icon-button button {
|
||||||
|
color: var(--fg_nav);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.inner-nav {
|
.inner-nav {
|
||||||
|
@ -26,7 +30,7 @@ nav {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $accent_light;
|
color: var(--accent_light);
|
||||||
text-decoration: unset;
|
text-decoration: unset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +58,7 @@ nav {
|
||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $accent_light;
|
color: var(--accent_light);
|
||||||
text-decoration: unset;
|
text-decoration: unset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
.profile-card {
|
.profile-card {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
background: $bg_panel;
|
background: var(--bg_panel);
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
@ -20,14 +20,14 @@
|
||||||
|
|
||||||
.profile-card-username {
|
.profile-card-username {
|
||||||
@include breakable;
|
@include breakable;
|
||||||
color: $fg_color;
|
color: var(--fg_color);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-card-fullname {
|
.profile-card-fullname {
|
||||||
@include breakable;
|
@include breakable;
|
||||||
color: $fg_color;
|
color: var(--fg_color);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
|
@ -45,8 +45,8 @@
|
||||||
width: calc(100% - 8px);
|
width: calc(100% - 8px);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border: 4px solid $darker_grey;
|
border: 4px solid var(--darker_grey);
|
||||||
background: $bg_color;
|
background: var(--bg_color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-joindate, .profile-location, profile-website {
|
.profile-joindate, .profile-location, profile-website {
|
||||||
color: $fg_faded;
|
color: var(--fg_faded);
|
||||||
margin: 2px 0;
|
margin: 2px 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -94,10 +94,12 @@
|
||||||
|
|
||||||
.profile-stat-header {
|
.profile-stat-header {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
color: var(--profile_stat);
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-stat-num {
|
.profile-stat-num {
|
||||||
display: block;
|
display: block;
|
||||||
|
color: var(--profile_stat);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(max-width: 600px) {
|
@media(max-width: 600px) {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
.photo-rail {
|
.photo-rail {
|
||||||
&-card {
|
&-card {
|
||||||
float: left;
|
float: left;
|
||||||
background: $bg_panel;
|
background: var(--bg_panel);
|
||||||
border-radius: 0 0 4px 4px;
|
border-radius: 0 0 4px 4px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
display: none;
|
display: none;
|
||||||
width: calc(100% - 24px);
|
width: calc(100% - 24px);
|
||||||
float: unset;
|
float: unset;
|
||||||
color: $accent;
|
color: var(--accent);
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,9 @@
|
||||||
|
|
||||||
> label {
|
> label {
|
||||||
display: inline;
|
display: inline;
|
||||||
background-color: #121212;
|
background-color: var(--bg_elements);
|
||||||
color: #F8F8F2;
|
color: var(--fg_color);
|
||||||
border: 1px solid #FF6C6091;
|
border: 1px solid var(--accent_border);
|
||||||
padding: 1px 6px 2px 6px;
|
padding: 1px 6px 2px 6px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
|
@ -5,15 +5,15 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline {
|
.timeline {
|
||||||
background-color: $bg_panel;
|
background-color: var(--bg_panel);
|
||||||
|
|
||||||
> div:not(:first-child) {
|
> div:not(:first-child) {
|
||||||
border-top: 1px solid $border_grey;
|
border-top: 1px solid var(--border_grey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-header {
|
.timeline-header {
|
||||||
background-color: $bg_panel;
|
background-color: var(--bg_panel);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0 0 5px 0;
|
margin: 0 0 5px 0;
|
||||||
background-color: $bg_panel;
|
background-color: var(--bg_panel);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
|
|
||||||
a {
|
a {
|
||||||
border-bottom: .1rem solid transparent;
|
border-bottom: .1rem solid transparent;
|
||||||
color: inherit;
|
color: var(--tab);
|
||||||
display: block;
|
display: block;
|
||||||
padding: 8px 0;
|
padding: 8px 0;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
@ -53,14 +53,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
border-bottom-color: $accent;
|
border-bottom-color: var(--tab_selected);
|
||||||
color: $accent;
|
color: var(--tab_selected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active a {
|
&.active a {
|
||||||
border-bottom-color: $accent;
|
border-bottom-color: var(--tab_selected);
|
||||||
color: $accent;
|
color: var(--tab_selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.wide {
|
&.wide {
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-footer {
|
.timeline-footer {
|
||||||
background-color: $bg_panel;
|
background-color: var(--bg_panel);
|
||||||
padding: 6px 0;
|
padding: 6px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,48 +81,48 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
color: $accent;
|
color: var(--accent);
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-none {
|
.timeline-none {
|
||||||
color: $accent;
|
color: var(--accent);
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-end {
|
.timeline-end {
|
||||||
background-color: $bg_panel;
|
background-color: var(--bg_panel);
|
||||||
color: $accent;
|
color: var(--accent);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.show-more {
|
.show-more {
|
||||||
background-color: $bg_panel;
|
background-color: var(--bg_panel);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: .75em 0;
|
padding: .75em 0;
|
||||||
display: block !important;
|
display: block !important;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
background-color: $darkest_grey;
|
background-color: var(--darkest_grey);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 2em;
|
height: 2em;
|
||||||
padding: 0 2em;
|
padding: 0 2em;
|
||||||
line-height: 2em;
|
line-height: 2em;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $darker_grey;
|
background-color: var(--darker_grey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-ref {
|
.top-ref {
|
||||||
background-color: #0f0f0f;
|
background-color: var(--bg_color);
|
||||||
border-top: none !important;
|
border-top: none !important;
|
||||||
|
|
||||||
.icon-down {
|
.icon-down {
|
||||||
|
@ -132,7 +132,7 @@
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $accent_light;
|
color: var(--accent_light);
|
||||||
}
|
}
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
max-width: 80%;
|
max-width: 80%;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: $fg_color;
|
color: var(--fg_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.username {
|
.username {
|
||||||
|
@ -68,10 +68,14 @@
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tweet-date a, .username, .show-more a {
|
||||||
|
color: var(--fg_dark);
|
||||||
|
}
|
||||||
|
|
||||||
.tweet-published {
|
.tweet-published {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
color: $grey;
|
color: var(--grey);
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +93,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.replying-to {
|
.replying-to {
|
||||||
color: $fg_dark;
|
color: var(--fg_faded);
|
||||||
margin: -2px 0 4px;
|
margin: -2px 0 4px;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
@ -99,7 +103,7 @@
|
||||||
|
|
||||||
.retweet-header, .pinned, .tweet-stats {
|
.retweet-header, .pinned, .tweet-stats {
|
||||||
align-content: center;
|
align-content: center;
|
||||||
color: $grey;
|
color: var(--grey);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
@ -134,9 +138,9 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
border: solid 1px $dark_grey;
|
border: solid 1px var(--dark_grey);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background-color: $bg_color;
|
background-color: var(--bg_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tweet-link {
|
.tweet-link {
|
||||||
|
@ -147,6 +151,6 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: #1a1a1a;
|
background-color: var(--bg_hover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,15 +10,15 @@
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: $dark_grey;
|
border-color: var(--dark_grey);
|
||||||
background-color: $bg_elements;
|
background-color: var(--bg_elements);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
display: flex;
|
display: flex;
|
||||||
text-decoration: none !important;
|
text-decoration: none !important;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: $grey;
|
border-color: var(--grey);
|
||||||
}
|
}
|
||||||
|
|
||||||
.attachments {
|
.attachments {
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
|
|
||||||
.card-destination {
|
.card-destination {
|
||||||
@include ellipsis;
|
@include ellipsis;
|
||||||
color: $grey;
|
color: var(--grey);
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
background-color: $fg_color;
|
background-color: var(--fg_color);
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -107,7 +107,7 @@
|
||||||
.card-image {
|
.card-image {
|
||||||
position: unset;
|
position: unset;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: $dark_grey;
|
border-color: var(--dark_grey);
|
||||||
border-width: 0;
|
border-width: 0;
|
||||||
border-bottom-width: 1px;
|
border-bottom-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
background-color: $bg_color;
|
background-color: var(--bg_color);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
|
|
||||||
|
@ -81,13 +81,13 @@
|
||||||
|
|
||||||
.overlay-circle {
|
.overlay-circle {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: $dark_grey;
|
background-color: var(--dark_grey);
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
border-width: 5px;
|
border-width: 5px;
|
||||||
border-color: $play_button_red;
|
border-color: var(--play_button);
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
height: 0;
|
height: 0;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-width: 12px 0 12px 17px;
|
border-width: 12px 0 12px 17px;
|
||||||
border-color: transparent transparent transparent $play_button_red;
|
border-color: transparent transparent transparent var(--play_button);
|
||||||
margin-left: 14px;
|
margin-left: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 6px 0;
|
margin: 6px 0;
|
||||||
height: 26px;
|
height: 26px;
|
||||||
background: $bg_color;
|
background: var(--bg_color);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
.poll-choice-bar {
|
.poll-choice-bar {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: $dark_grey;
|
background: var(--dark_grey);
|
||||||
}
|
}
|
||||||
|
|
||||||
.poll-choice-value {
|
.poll-choice-value {
|
||||||
|
@ -33,10 +33,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.poll-info {
|
.poll-info {
|
||||||
color: $grey;
|
color: var(--grey);
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
.leader .poll-choice-bar {
|
.leader .poll-choice-bar {
|
||||||
background: $accent_dark;
|
background: var(--accent_dark);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,20 +2,20 @@
|
||||||
|
|
||||||
.quote {
|
.quote {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
border: solid 1px $dark_grey;
|
border: solid 1px var(--dark_grey);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background-color: $bg_elements;
|
background-color: var(--bg_elements);
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
position: relative;
|
position: relative;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: $grey;
|
border-color: var(--grey);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.unavailable:hover {
|
&.unavailable:hover {
|
||||||
border-color: $dark_grey;
|
border-color: var(--dark_grey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.quote-sensitive {
|
.quote-sensitive {
|
||||||
background: $darker_grey;
|
background: var(--darker_grey);
|
||||||
width: 102px;
|
width: 102px;
|
||||||
height: 102px;
|
height: 102px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
|
|
||||||
.quote-sensitive-icon {
|
.quote-sensitive-icon {
|
||||||
font-size: 40px;
|
font-size: 40px;
|
||||||
color: $grey;
|
color: var(--grey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(max-width: 600px) {
|
@media(max-width: 600px) {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
.main-thread {
|
.main-thread {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
background-color: $bg_panel;
|
background-color: var(--bg_panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-tweet, .replies {
|
.main-tweet, .replies {
|
||||||
|
@ -24,14 +24,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.reply {
|
.reply {
|
||||||
background-color: $bg_panel;
|
background-color: var(--bg_panel);
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thread-line {
|
.thread-line {
|
||||||
.timeline-item::before,
|
.timeline-item::before,
|
||||||
&.timeline-item::before {
|
&.timeline-item::before {
|
||||||
background: $accent_dark;
|
background: var(--accent_dark);
|
||||||
content: '';
|
content: '';
|
||||||
position: relative;
|
position: relative;
|
||||||
min-width: 3px;
|
min-width: 3px;
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
.more-replies::before {
|
.more-replies::before {
|
||||||
content: '...';
|
content: '...';
|
||||||
background: unset;
|
background: unset;
|
||||||
color: $more_replies_dots;
|
color: var(--more_replies_dots);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
line-height: 0.25em;
|
line-height: 0.25em;
|
||||||
|
|
|
@ -177,6 +177,7 @@ type
|
||||||
hostname*: string
|
hostname*: string
|
||||||
cacheDir*: string
|
cacheDir*: string
|
||||||
profileCacheTime*: int
|
profileCacheTime*: int
|
||||||
|
defaultTheme*: string
|
||||||
|
|
||||||
proc contains*(thread: Chain; tweet: Tweet): bool =
|
proc contains*(thread: Chain; tweet: Tweet): bool =
|
||||||
thread.content.anyIt(it.id == tweet.id)
|
thread.content.anyIt(it.id == tweet.id)
|
||||||
|
|
|
@ -29,11 +29,13 @@ proc renderNavbar*(title, rss: string; req: Request): VNode =
|
||||||
|
|
||||||
proc renderMain*(body: VNode; req: Request; cfg: Config; titleText=""; desc="";
|
proc renderMain*(body: VNode; req: Request; cfg: Config; titleText=""; desc="";
|
||||||
rss=""; `type`="article"; video=""; images: seq[string] = @[]): string =
|
rss=""; `type`="article"; video=""; images: seq[string] = @[]): string =
|
||||||
let prefs = getPrefs(req.cookies.getOrDefault("preferences"), cfg.hostname)
|
let prefs = getPrefs(req.cookies.getOrDefault("preferences"), cfg)
|
||||||
|
let theme = "/css/themes/" & toLowerAscii(prefs.theme) & ".css"
|
||||||
let node = buildHtml(html(lang="en")):
|
let node = buildHtml(html(lang="en")):
|
||||||
head:
|
head:
|
||||||
link(rel="stylesheet", `type`="text/css", href="/css/style.css")
|
link(rel="stylesheet", `type`="text/css", href="/css/style.css")
|
||||||
link(rel="stylesheet", `type`="text/css", href="/css/fontello.css")
|
link(rel="stylesheet", `type`="text/css", href="/css/fontello.css")
|
||||||
|
link(rel="stylesheet", `type`="text/css", href=theme)
|
||||||
|
|
||||||
link(rel="apple-touch-icon", sizes="180x180", href="/apple-touch-icon.png")
|
link(rel="apple-touch-icon", sizes="180x180", href="/apple-touch-icon.png")
|
||||||
link(rel="icon", type="image/png", sizes="32x32", href="/favicon-32x32.png")
|
link(rel="icon", type="image/png", sizes="32x32", href="/favicon-32x32.png")
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import tables, macros, strutils
|
import tables, macros, strutils, os
|
||||||
import karax/[karaxdsl, vdom, vstyles]
|
import karax/[karaxdsl, vdom, vstyles]
|
||||||
|
|
||||||
import renderutils
|
import renderutils
|
||||||
|
@ -22,12 +22,16 @@ macro renderPrefs*(): untyped =
|
||||||
|
|
||||||
case pref.kind
|
case pref.kind
|
||||||
of checkbox: discard
|
of checkbox: discard
|
||||||
of select: stmt[0].add newLit(pref.options)
|
|
||||||
of input: stmt[0].add newLit(pref.placeholder)
|
of input: stmt[0].add newLit(pref.placeholder)
|
||||||
|
of select:
|
||||||
|
if pref.name == "theme":
|
||||||
|
stmt[0].add ident("themes")
|
||||||
|
else:
|
||||||
|
stmt[0].add newLit(pref.options)
|
||||||
|
|
||||||
result[2].add stmt
|
result[2].add stmt
|
||||||
|
|
||||||
proc renderPreferences*(prefs: Prefs; path: string): VNode =
|
proc renderPreferences*(prefs: Prefs; path: string; themes: seq[string]): VNode =
|
||||||
buildHtml(tdiv(class="overlay-panel")):
|
buildHtml(tdiv(class="overlay-panel")):
|
||||||
fieldset(class="preferences"):
|
fieldset(class="preferences"):
|
||||||
form(`method`="post", action="/saveprefs"):
|
form(`method`="post", action="/saveprefs"):
|
||||||
|
|
|
@ -71,7 +71,7 @@ proc genInput*(pref, label, state, placeholder: string; class=""; autofocus=fals
|
||||||
verbatim &"<input name={pref} type=\"text\" placeholder=\"{p}\" value=\"{s}\" {a}/>"
|
verbatim &"<input name={pref} type=\"text\" placeholder=\"{p}\" value=\"{s}\" {a}/>"
|
||||||
|
|
||||||
proc genSelect*(pref, label, state: string; options: seq[string]): VNode =
|
proc genSelect*(pref, label, state: string; options: seq[string]): VNode =
|
||||||
buildHtml(tdiv(class="pref-group")):
|
buildHtml(tdiv(class="pref-group pref-input")):
|
||||||
label(`for`=pref): text label
|
label(`for`=pref): text label
|
||||||
select(name=pref):
|
select(name=pref):
|
||||||
for opt in options:
|
for opt in options:
|
||||||
|
|
Loading…
Reference in a new issue