Show who you're replying to and scroll to reply box.
This commit is contained in:
parent
fe49dd1e85
commit
96e78a5b84
7 changed files with 75 additions and 38 deletions
|
|
@ -81,7 +81,7 @@ when defined(js):
|
||||||
tdiv(class="navbar container grid-xl"):
|
tdiv(class="navbar container grid-xl"):
|
||||||
section(class="navbar-section"):
|
section(class="navbar-section"):
|
||||||
a(href=makeUri("/")):
|
a(href=makeUri("/")):
|
||||||
img(src="images/crown.png", id="img-logo") # TODO: Customisation.
|
img(src="/karax/images/crown.png", id="img-logo") # TODO: Customisation.
|
||||||
section(class="navbar-section"):
|
section(class="navbar-section"):
|
||||||
tdiv(class="input-group input-inline"):
|
tdiv(class="input-group input-inline"):
|
||||||
input(class="search-input input-sm",
|
input(class="search-input input-sm",
|
||||||
|
|
|
||||||
|
|
@ -8,17 +8,15 @@
|
||||||
|
|
||||||
<title>The Nim programming language forum</title>
|
<title>The Nim programming language forum</title>
|
||||||
|
|
||||||
<base href="/karax/">
|
<link rel="stylesheet" href="/karax/nimforum.css">
|
||||||
|
|
||||||
<link rel="stylesheet" href="nimforum.css">
|
|
||||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.12/css/all.css" integrity="sha384-G0fIWCsCzJIMAVNQPfjH08cyYaUtMwjJwqiRKxxE/rx96Uroj1BtIQ6MLJuheaO9" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.12/css/all.css" integrity="sha384-G0fIWCsCzJIMAVNQPfjH08cyYaUtMwjJwqiRKxxE/rx96Uroj1BtIQ6MLJuheaO9" crossorigin="anonymous">
|
||||||
<link rel="icon" href="images/favicon.png">
|
<link rel="icon" href="/karax/images/favicon.png">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div id="ROOT" />
|
<div id="ROOT" />
|
||||||
|
|
||||||
<script type="text/javascript" src="nimcache/forum.js"></script>
|
<script type="text/javascript" src="/karax/nimcache/forum.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,8 @@ proc class*(classes: varargs[tuple[name: string, present: bool]],
|
||||||
if class.present: result.add(class.name & " ")
|
if class.present: result.add(class.name & " ")
|
||||||
|
|
||||||
proc makeUri*(relative: string, appName=appName, includeHash=false): string =
|
proc makeUri*(relative: string, appName=appName, includeHash=false): string =
|
||||||
## Concatenates ``relative`` to the current URL in a way that is sane.
|
## Concatenates ``relative`` to the current URL in a way that is
|
||||||
|
## (possibly) sane.
|
||||||
var relative = relative
|
var relative = relative
|
||||||
assert appName in $window.location.pathname
|
assert appName in $window.location.pathname
|
||||||
if relative[0] == '/': relative = relative[1..^1]
|
if relative[0] == '/': relative = relative[1..^1]
|
||||||
|
|
|
||||||
18
redesign/post.nim
Normal file
18
redesign/post.nim
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import threadlist
|
||||||
|
|
||||||
|
type
|
||||||
|
PostInfo* = object
|
||||||
|
creation*: int64
|
||||||
|
content*: string
|
||||||
|
|
||||||
|
Post* = object
|
||||||
|
id*: int
|
||||||
|
author*: User
|
||||||
|
likes*: seq[User] ## Users that liked this post.
|
||||||
|
seen*: bool ## Determines whether the current user saw this post.
|
||||||
|
## I considered using a simple timestamp for each thread,
|
||||||
|
## but that wouldn't work when a user navigates to the last
|
||||||
|
## post in a thread for example.
|
||||||
|
history*: seq[PostInfo] ## If the post was edited this will contain the
|
||||||
|
## older versions of the post.
|
||||||
|
info*: PostInfo
|
||||||
|
|
@ -1,23 +1,8 @@
|
||||||
|
|
||||||
import options, json, times, httpcore, strformat, sugar, math
|
import options, json, times, httpcore, strformat, sugar, math
|
||||||
|
|
||||||
import threadlist, category
|
import threadlist, category, post
|
||||||
type
|
type
|
||||||
PostInfo* = object
|
|
||||||
creation*: int64
|
|
||||||
content*: string
|
|
||||||
|
|
||||||
Post* = object
|
|
||||||
id*: int
|
|
||||||
author*: User
|
|
||||||
likes*: seq[User] ## Users that liked this post.
|
|
||||||
seen*: bool ## Determines whether the current user saw this post.
|
|
||||||
## I considered using a simple timestamp for each thread,
|
|
||||||
## but that wouldn't work when a user navigates to the last
|
|
||||||
## post in a thread for example.
|
|
||||||
history*: seq[PostInfo] ## If the post was edited this will contain the
|
|
||||||
## older versions of the post.
|
|
||||||
info*: PostInfo
|
|
||||||
|
|
||||||
PostList* = ref object
|
PostList* = ref object
|
||||||
thread*: Thread
|
thread*: Thread
|
||||||
|
|
@ -38,7 +23,7 @@ when defined(js):
|
||||||
list: Option[PostList]
|
list: Option[PostList]
|
||||||
loading: bool
|
loading: bool
|
||||||
status: HttpCode
|
status: HttpCode
|
||||||
replyBoxShown: bool
|
replyingTo: Option[Post]
|
||||||
replyBox: ReplyBox
|
replyBox: ReplyBox
|
||||||
|
|
||||||
proc newState(): State =
|
proc newState(): State =
|
||||||
|
|
@ -46,7 +31,7 @@ when defined(js):
|
||||||
list: none[PostList](),
|
list: none[PostList](),
|
||||||
loading: false,
|
loading: false,
|
||||||
status: Http200,
|
status: Http200,
|
||||||
replyBoxShown: true,
|
replyingTo: none[Post](),
|
||||||
replyBox: newReplyBox()
|
replyBox: newReplyBox()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -74,7 +59,12 @@ when defined(js):
|
||||||
proc renderPostUrl(post: Post, thread: Thread): string =
|
proc renderPostUrl(post: Post, thread: Thread): string =
|
||||||
makeUri(fmt"/t/{thread.id}/p/{post.id}")
|
makeUri(fmt"/t/{thread.id}/p/{post.id}")
|
||||||
|
|
||||||
|
proc onReplyClick(e: Event, n: VNode, p: Option[Post]) =
|
||||||
|
state.replyingTo = p
|
||||||
|
state.replyBox.show()
|
||||||
|
|
||||||
proc genPost(post: Post, thread: Thread, isLoggedIn: bool): VNode =
|
proc genPost(post: Post, thread: Thread, isLoggedIn: bool): VNode =
|
||||||
|
let postCopy = post # TODO: Another workaround here, closure capture :(
|
||||||
result = buildHtml():
|
result = buildHtml():
|
||||||
tdiv(class="post"):
|
tdiv(class="post"):
|
||||||
tdiv(class="post-icon"):
|
tdiv(class="post-icon"):
|
||||||
|
|
@ -102,7 +92,8 @@ when defined(js):
|
||||||
button(class="btn"):
|
button(class="btn"):
|
||||||
italic(class="far fa-flag")
|
italic(class="far fa-flag")
|
||||||
tdiv(class="reply-button"):
|
tdiv(class="reply-button"):
|
||||||
button(class="btn"):
|
button(class="btn", onClick=(e: Event, n: VNode) =>
|
||||||
|
onReplyClick(e, n, some(postCopy))):
|
||||||
italic(class="fas fa-reply")
|
italic(class="fas fa-reply")
|
||||||
text " Reply"
|
text " Reply"
|
||||||
|
|
||||||
|
|
@ -183,11 +174,9 @@ when defined(js):
|
||||||
genPost(post, list.thread, isLoggedIn)
|
genPost(post, list.thread, isLoggedIn)
|
||||||
prevPost = some(post)
|
prevPost = some(post)
|
||||||
|
|
||||||
if state.replyBoxShown and prevPost.isSome:
|
|
||||||
genTimePassed(prevPost.get(), none[Post]())
|
|
||||||
|
|
||||||
if list.moreCount > 0:
|
if list.moreCount > 0:
|
||||||
genLoadMore(list.posts.len)
|
genLoadMore(list.posts.len)
|
||||||
|
elif prevPost.isSome:
|
||||||
|
genTimePassed(prevPost.get(), none[Post]())
|
||||||
|
|
||||||
if state.replyBoxShown:
|
render(state.replyBox, list.thread, state.replyingTo)
|
||||||
render(state.replyBox, list.thread)
|
|
||||||
|
|
@ -1,28 +1,53 @@
|
||||||
when defined(js):
|
when defined(js):
|
||||||
import strformat
|
import strformat, options
|
||||||
|
|
||||||
|
from dom import getElementById, scrollIntoView, setTimeout
|
||||||
|
|
||||||
include karax/prelude
|
include karax/prelude
|
||||||
import karax / [vstyles, kajax, kdom]
|
import karax / [vstyles, kajax, kdom]
|
||||||
|
|
||||||
import karaxutils, threadlist
|
import karaxutils, threadlist, post
|
||||||
|
|
||||||
type
|
type
|
||||||
ReplyBox* = ref object
|
ReplyBox* = ref object
|
||||||
|
shown: bool
|
||||||
preview: bool
|
preview: bool
|
||||||
|
|
||||||
proc newReplyBox*(): ReplyBox =
|
proc newReplyBox*(): ReplyBox =
|
||||||
ReplyBox()
|
ReplyBox()
|
||||||
|
|
||||||
proc render*(state: ReplyBox, thread: Thread): VNode =
|
proc performScroll() =
|
||||||
|
let replyBox = dom.document.getElementById("reply-box")
|
||||||
|
replyBox.scrollIntoView(false)
|
||||||
|
|
||||||
|
proc show*(state: ReplyBox) =
|
||||||
|
# Scroll to the reply box.
|
||||||
|
if not state.shown:
|
||||||
|
# TODO: It would be nice for Karax to give us an event when it renders
|
||||||
|
# things. That way we can remove this crappy hack.
|
||||||
|
discard dom.window.setTimeout(performScroll, 50)
|
||||||
|
else:
|
||||||
|
performScroll()
|
||||||
|
|
||||||
|
state.shown = true
|
||||||
|
|
||||||
|
proc render*(state: ReplyBox, thread: Thread, post: Option[Post]): VNode =
|
||||||
|
if not state.shown:
|
||||||
|
return buildHtml(tdiv(id="reply-box"))
|
||||||
|
|
||||||
result = buildHtml():
|
result = buildHtml():
|
||||||
tdiv(class="information no-border"):
|
tdiv(class="information no-border", id="reply-box"):
|
||||||
tdiv(class="information-icon"):
|
tdiv(class="information-icon"):
|
||||||
italic(class="fas fa-reply")
|
italic(class="fas fa-reply")
|
||||||
tdiv(class="information-main", style=style(StyleAttr.width, "100%")):
|
tdiv(class="information-main", style=style(StyleAttr.width, "100%")):
|
||||||
tdiv(class="information-title"):
|
tdiv(class="information-title"):
|
||||||
# text fmt("Replying to \"{thread.topic}\"")
|
if post.isNone:
|
||||||
# tdiv(class="information-content"):
|
text fmt("Replying to \"{thread.topic}\"")
|
||||||
tdiv(class="panel", id="reply-box"):
|
else:
|
||||||
|
text "Replying to "
|
||||||
|
renderUserMention(post.get().author)
|
||||||
|
tdiv(class="information-content"):
|
||||||
|
tdiv(class="panel"):
|
||||||
tdiv(class="panel-nav"):
|
tdiv(class="panel-nav"):
|
||||||
ul(class="tab tab-block"):
|
ul(class="tab tab-block"):
|
||||||
li(class=class({"active": not state.preview}, "tab-item")):
|
li(class=class({"active": not state.preview}, "tab-item")):
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,12 @@ when defined(js):
|
||||||
if user.isOnline:
|
if user.isOnline:
|
||||||
italic(class="avatar-presense online")
|
italic(class="avatar-presense online")
|
||||||
|
|
||||||
|
proc renderUserMention*(user: User): VNode =
|
||||||
|
result = buildHtml():
|
||||||
|
# TODO: Add URL to profile.
|
||||||
|
span(class="user-mention"):
|
||||||
|
text "@" & user.name
|
||||||
|
|
||||||
proc genUserAvatars(users: seq[User]): VNode =
|
proc genUserAvatars(users: seq[User]): VNode =
|
||||||
result = buildHtml(td):
|
result = buildHtml(td):
|
||||||
for user in users:
|
for user in users:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue