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"):
|
||||
section(class="navbar-section"):
|
||||
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"):
|
||||
tdiv(class="input-group input-inline"):
|
||||
input(class="search-input input-sm",
|
||||
|
|
|
|||
|
|
@ -8,17 +8,15 @@
|
|||
|
||||
<title>The Nim programming language forum</title>
|
||||
|
||||
<base href="/karax/">
|
||||
|
||||
<link rel="stylesheet" href="nimforum.css">
|
||||
<link rel="stylesheet" href="/karax/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="icon" href="images/favicon.png">
|
||||
<link rel="icon" href="/karax/images/favicon.png">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="ROOT" />
|
||||
|
||||
<script type="text/javascript" src="nimcache/forum.js"></script>
|
||||
<script type="text/javascript" src="/karax/nimcache/forum.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ proc class*(classes: varargs[tuple[name: string, present: bool]],
|
|||
if class.present: result.add(class.name & " ")
|
||||
|
||||
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
|
||||
assert appName in $window.location.pathname
|
||||
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 threadlist, category
|
||||
import threadlist, category, post
|
||||
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
|
||||
thread*: Thread
|
||||
|
|
@ -38,7 +23,7 @@ when defined(js):
|
|||
list: Option[PostList]
|
||||
loading: bool
|
||||
status: HttpCode
|
||||
replyBoxShown: bool
|
||||
replyingTo: Option[Post]
|
||||
replyBox: ReplyBox
|
||||
|
||||
proc newState(): State =
|
||||
|
|
@ -46,7 +31,7 @@ when defined(js):
|
|||
list: none[PostList](),
|
||||
loading: false,
|
||||
status: Http200,
|
||||
replyBoxShown: true,
|
||||
replyingTo: none[Post](),
|
||||
replyBox: newReplyBox()
|
||||
)
|
||||
|
||||
|
|
@ -74,7 +59,12 @@ when defined(js):
|
|||
proc renderPostUrl(post: Post, thread: Thread): string =
|
||||
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 =
|
||||
let postCopy = post # TODO: Another workaround here, closure capture :(
|
||||
result = buildHtml():
|
||||
tdiv(class="post"):
|
||||
tdiv(class="post-icon"):
|
||||
|
|
@ -102,7 +92,8 @@ when defined(js):
|
|||
button(class="btn"):
|
||||
italic(class="far fa-flag")
|
||||
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")
|
||||
text " Reply"
|
||||
|
||||
|
|
@ -183,11 +174,9 @@ when defined(js):
|
|||
genPost(post, list.thread, isLoggedIn)
|
||||
prevPost = some(post)
|
||||
|
||||
if state.replyBoxShown and prevPost.isSome:
|
||||
genTimePassed(prevPost.get(), none[Post]())
|
||||
|
||||
if list.moreCount > 0:
|
||||
genLoadMore(list.posts.len)
|
||||
elif prevPost.isSome:
|
||||
genTimePassed(prevPost.get(), none[Post]())
|
||||
|
||||
if state.replyBoxShown:
|
||||
render(state.replyBox, list.thread)
|
||||
render(state.replyBox, list.thread, state.replyingTo)
|
||||
|
|
@ -1,28 +1,53 @@
|
|||
when defined(js):
|
||||
import strformat
|
||||
import strformat, options
|
||||
|
||||
from dom import getElementById, scrollIntoView, setTimeout
|
||||
|
||||
include karax/prelude
|
||||
import karax / [vstyles, kajax, kdom]
|
||||
|
||||
import karaxutils, threadlist
|
||||
import karaxutils, threadlist, post
|
||||
|
||||
type
|
||||
ReplyBox* = ref object
|
||||
shown: bool
|
||||
preview: bool
|
||||
|
||||
proc newReplyBox*(): 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():
|
||||
tdiv(class="information no-border"):
|
||||
tdiv(class="information no-border", id="reply-box"):
|
||||
tdiv(class="information-icon"):
|
||||
italic(class="fas fa-reply")
|
||||
tdiv(class="information-main", style=style(StyleAttr.width, "100%")):
|
||||
tdiv(class="information-title"):
|
||||
# text fmt("Replying to \"{thread.topic}\"")
|
||||
# tdiv(class="information-content"):
|
||||
tdiv(class="panel", id="reply-box"):
|
||||
if post.isNone:
|
||||
text fmt("Replying to \"{thread.topic}\"")
|
||||
else:
|
||||
text "Replying to "
|
||||
renderUserMention(post.get().author)
|
||||
tdiv(class="information-content"):
|
||||
tdiv(class="panel"):
|
||||
tdiv(class="panel-nav"):
|
||||
ul(class="tab tab-block"):
|
||||
li(class=class({"active": not state.preview}, "tab-item")):
|
||||
|
|
|
|||
|
|
@ -70,6 +70,12 @@ when defined(js):
|
|||
if user.isOnline:
|
||||
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 =
|
||||
result = buildHtml(td):
|
||||
for user in users:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue