summaryrefslogtreecommitdiff
path: root/desk/web/thread.hoon
diff options
context:
space:
mode:
Diffstat (limited to 'desk/web/thread.hoon')
-rw-r--r--desk/web/thread.hoon478
1 files changed, 478 insertions, 0 deletions
diff --git a/desk/web/thread.hoon b/desk/web/thread.hoon
new file mode 100644
index 0000000..e88185d
--- /dev/null
+++ b/desk/web/thread.hoon
@@ -0,0 +1,478 @@
+/- boke, tp=trill-post, cons=contact
+/+ sr=sortug, plib=trill-utils, sigil=sigil-sigil, lib=boke, kaji, constants
+/= post-content /web/components/post-text
+|_ [fn=full-node:tp children=(list post:tp) page=@ud contacts=whoms:cons =bowl:gall]
+++ thread-css ^~ %- trip
+'''
+body>main{
+ width: 100%!important;
+}
+@media (max-width: 800px){
+ body>main{
+ padding: 0!important;
+ }
+}
+#board-thread{
+ max-width: 1280px;
+ margin: auto;
+
+/* base styles */
+ & header{
+ & img{
+ width: 20px;
+ margin-left: 1rem;
+ }
+ }
+
+ & p{
+ font-size: 1.1rem;
+ }
+ & .reply{
+ display: grid;
+ border: 1px solid silver;
+
+ & .author{
+ margin-right: 1rem;
+
+ & .avatar{
+ max-height: 100px;
+ max-width: 88px;
+ }
+ & .name{
+ font-weight: 500;
+ color: var(--hong);
+ text-align: center;
+ word-break: break-word;
+ }
+ }
+
+ & .metadata {
+ & p{
+ margin: -5px 0 0 0;
+ font-size: 14px;
+ }
+ & .buttons{
+ display: flex;
+ img{
+ height: 20px;
+ width: 20px;
+ margin: 5px 5px;
+ cursor: pointer;
+ }
+ }
+
+ }
+
+ & .content{
+ text-align: left:
+ word-wrap: break-word;
+
+ & p{
+ padding: 0.5rem;
+ font-weight: 400;
+ overflow: hidden;
+ word-break: break-word;
+ white-space: normal;
+ margin: 1rem 0;
+ }
+ & blockquote{
+ margin: 1rem 2rem 1rem 1rem;
+ padding: 0.4rem;
+ border: 1px solid grey;
+ border-radius: 2%;
+ }
+ }
+ }
+ & footer{
+ width: 100%;
+ .tags{
+ padding: 0;
+ font-size: 0.9rem;
+ flex-wrap: wrap;
+
+ a{
+ margin-left: 0.1rem;
+ }
+ }
+ }
+
+
+ /* desktop */
+
+ @media (min-width: 1000px){
+ #posts{
+ display: flex;
+ }
+ #replies{
+ width: 83.33%;
+ }
+ }
+ @media(min-width: 800px){
+
+ & #sidebar{
+ position: sticky;
+ top: 4rem;
+ right: 0;
+ align-self: flex-start;
+ }
+
+ & #posts{
+
+ & .reply{
+ padding: 1rem;
+ margin: 1rem;
+ grid-template-columns: 10% 90%;
+ grid-template-rows: 40px auto;
+
+ & .author{
+ grid-column-start: 1;
+ grid-column-end: 2;
+ grid-row-start: 1;
+ grid-row-end: 3;
+ }
+
+ & .metadata{
+ display: flex;
+ justify-content: space-between;
+ border-bottom: 1px solid grey; /* TODO darkmode */
+ grid-column-start: 2;
+ grid-column-end: 3;
+ grid-row-start: 1;
+ grid-row-end: 2;
+ }
+
+ & .content{
+ grid-column-start: 2;
+ grid-column-end: 3;
+ grid-row-start: 2;
+ grid-row-end: 3;
+
+ & img{
+ margin: 0 auto;
+ }
+ }
+ }
+ }
+ }
+ /* mobile */
+ @media(max-width: 800px){
+
+
+ & #posts{
+ display: block;
+ width: 100%;
+
+ & .reply{
+ padding-top: 10px;
+ grid-template-columns: 100px auto;
+ grid-template-rows: 80px auto;
+
+ & .author{
+ grid-column-start; 1;
+ grid-column-end: 2;
+ grid-row-start: 1;
+ grid-row-end: 2;
+
+ & .avatar{
+ height: 60px;
+ width: 60px;
+ display: block;
+ margin: 0 auto;
+ }
+ }
+ & .metadata{
+ grid-column-start: 2;
+ grid-column-end: 3;
+ grid-row-start: 1;
+ grid-row-end: 2;
+ padding: 0;
+ border-bottom: 1px solid grey;
+
+ & .buttons{
+ width: 100%;
+ justify-content: space-between;
+ margin-top: 0.5rem;
+ }
+ }
+ & .content{
+ grid-column-start: 1;
+ grid-column-end: 3;
+ grid-row-start: 2;
+ grid-row-end: 3;
+
+ }
+ }
+ }
+ }
+
+
+
+
+ & #sidebar{
+ padding-top: 2rem 0.5rem 0.5rem 0.5rem;
+
+ & div{
+ margin: 1rem 0;
+ }
+
+ & #search-box{
+ margin-top: 0.25rem;
+
+ & input{
+ width: 100%!important;
+ border: 1px solid var(--text-color);
+ }
+ }
+ }
+}
+
+.reply-box{
+ & .replying-to{
+ display: flex;
+
+ & .name{
+ margin-left: 1rem;
+ }
+ }
+ & textarea{
+ resize: none;
+ display: block;
+ outline: none;
+ width: 100%;
+ }
+ & input[type=submit]{
+ margin-top: 0.5rem;
+ float:right;
+ }
+}
+'''
+++ thread-js ^~ %- trip
+'''
+const buttons = document.querySelectorAll(".buttons");
+console.log(buttons, "buttons")
+buttons.forEach(el => {
+ const parent = el.closest(".reply");
+ const cb = el.querySelector(".copy-button")
+ cb.addEventListener("click", () => {
+ const path = `https://spandrell.ch/board/p/${parent.id}`
+ navigator.clipboard.writeText(path).then(res => {
+ console.log(res, "write to clipboard")
+ }).catch(er => {
+ console.log(er, "couldn't write to clipboard")
+ })
+ })
+ const db = el.querySelector(".down-button")
+ db.addEventListener("click", () => {
+ parent.querySelector("footer").scrollIntoView();
+ })
+});
+
+'''
+++ $ ^- manx
+=/ index (mul (dec page) board-page-size:constants)
+=/ childlist (slice:sr children board-page-size:constants index)
+;div#board-thread
+ ;style:"{thread-css}"
+ ;header.fxc
+ ;h1:"{(trip title.p.fn)}"
+ ;+ %+ hide-if:kaji ?|((is-admin:lib src.bowl) .=(author.p.fn src.bowl))
+ edit-button
+ ==
+ ;div#posts
+ ;div#replies
+ ;* %+ mapi:sr childlist thread-child
+ ==
+ ;+ sidebar
+ ==
+ ;script:"{thread-js}"
+==
+++ edit-button
+=/ pid-string (enc:kaji [author.p.fn id.p.fn])
+;a/"/board/edit/{pid-string}"
+ ;img@"https://s3.spandrell.ch/assets/board/ui/edit.svg";
+==
+
+++ thread-child
+|= [post-index=@ud =post:tp] ^- manx
+=/ base-index (mul (dec page) board-page-size:constants)
+=/ pind (add base-index +(post-index))
+=/ usr (user author.post)
+=/ pid-string (enc:kaji [author.post id.post])
+=/ jammed-parents %- enc:kaji [op=[author.p.fn id.p.fn] parent=[author.post id.post]]
+;div.reply(id pid-string)
+ ;div.author
+ ;+ avatar.usr
+ ;+ name.usr
+ ==
+ ;div.metadata
+ ;+ (date post pind)
+ ;+ (buttons post)
+ ==
+ ;div.content
+ ;* (post-content contents.post)
+ ;+ (footer post)
+ ==
+ ;+ (reply-box name.usr jammed-parents)
+==
+++ user
+|= u=@p ^- [avatar=manx name=manx]
+=/ ming (get-name:lib u)
+=/ sig sigil(size 80)
+=/ sigl ?: ?=(%ship -.ming) (sig u)
+=/ random (random-avatar:lib (jam u))
+;img.avatar@"{random}";
+=/ nam ;div.name:"{ming}"
+=/ prof (~(get by contacts) [%.y u])
+?~ prof [sigl nam]
+=/ avatar
+ =/ avatar-data (~(get by info.u.prof) %avatar)
+ ?~ avatar-data sigl
+ ?. ?=(%look -.u.avatar-data) sigl
+ ;img.avatar@"{(trip +.u.avatar-data)}";
+=/ name
+ =/ name-data (~(get by info.u.prof) %nickname)
+ ?~ name-data nam
+ ?. ?=(%text -.u.name-data) nam
+ ;div.name:"{(trip +.u.name-data)}"
+
+[avatar name]
+++ date
+|= [=post:tp post-index=@ud]
+=/ date-string (datetime-to-tape:string:sr id.post "-")
+=/ posted ;span.posted-date:"{date-string}"
+=/ last-edit=time key:head:(pop:corm:tp contents.post)
+=/ =marl ?: .=(last-edit id.post) posted^~
+:~ posted
+ ;span.updated-date:"{(datetime-to-tape:string:sr last-edit "-")}"
+==
+;div.date
+ ;p
+ ;* marl
+ ==
+ ;p
+ ;span:"Post #{(scow:parsing:sr %ud post-index)}"
+ ;span.engagement:""
+ ==
+==
+++ buttons
+|= =post:tp
+:: =/ votes %+ roll ~(tap by reacts.engagement.post) |= [[s=@p [r=@t *]] acc=@]
+:: ?: ?|(=(r "thumbsup") =(r "👍"))
+;div.buttons
+ ;+ %+ hide-if:kaji ?|((is-admin:lib src.bowl) .=(author.post src.bowl))
+ ;img@"https://s3.spandrell.ch/assets/board/ui/edit.svg";
+ ;img.copy-button@"https://s3.spandrell.ch/assets/board/ui/copy.svg";
+ ;img
+ =src "https://s3.spandrell.ch/assets/board/ui/upvote.svg"
+ ;
+ ==
+ ;img@"https://s3.spandrell.ch/assets/board/ui/downvote.svg"
+ ;
+ ==
+ ;img.down-button@"https://s3.spandrell.ch/assets/board/ui/down.svg";
+ ;img@"https://s3.spandrell.ch/assets/board/ui/reply.svg"
+ =kaji "toggle"
+ =targ ".reply-box"
+ =modal "1"
+ ;
+ ==
+ ;img.collapse-button
+ =src "https://s3.spandrell.ch/assets/board/ui/collapse.svg"
+ =kaji "toggle"
+ =targ ".content/.avatar/.uncollapse-button/.collapse-button"
+ ;
+ ==
+ ;img.uncollapse-button
+ =src "https://s3.spandrell.ch/assets/board/ui/uncollapse.svg"
+ =kaji "toggle"
+ =targ ".content/.avatar/.uncollapse-button/.collapse-button"
+ =hidden ""
+ ;
+ ==
+==
+++ reply-box
+|= [author=manx jammed-parents=tape] ^- manx
+:: %- serve-modal:kaji :_ ~
+;div.reply-box
+ =hidden ""
+ ;div.replying-to
+ ;div:"Replying to"
+ ;+ author
+ ==
+ ;form
+ =kaji "poke"
+ =action "add-post"
+ ;textarea
+ =name "text"
+ =rows "10"
+ ;
+ ==
+ ;input(type "hidden", name "parents", value jammed-parents);
+ ;input(type "submit", value "Send");
+ :: ==
+ ==
+==
+++ footer
+|= =post:tp
+=/ count ~(wyt in tags.post)
+=/ tags ?. (gth count 0) ;span:""
+=/ tag-links
+%+ mapi:sr ~(tap in tags.post)
+ |= [i=@ t=@t] ^- manx
+ ?. .=(i (dec count))
+ ;a/"/tags/{(trip t)}":"{(trip t)}, "
+ ;a/"/tags/{(trip t)}":"{(trip t)} "
+;div.tags.flex
+ ; Tags:
+ ;* tag-links
+==
+;footer
+ ;+ tags
+==
+::
+++ sidebar
+=/ from +((mul (dec page) board-page-size:constants))
+=/ to
+ =/ added (add from board-page-size:constants)
+ ?: (gth added (lent children)) (lent children) added
+=/ froms (number:string:sr from)
+=/ tos (number:string:sr to)
+=/ post-count (number:string:sr (lent children))
+=/ max-page +((div (lent children) board-page-size:constants))
+=/ page-count %- number:string:sr max-page
+=/ prev-page %- number:string:sr ?: .=(page 1) 1 (dec page)
+=/ curr-page (number:string:sr page)
+=/ next-page %- number:string:sr ?: .=(page max-page) page +(page)
+;div#sidebar
+ ;button:"Back to Board"
+ ;div#search-box
+ ;form.flex
+ ;input(name "thread-search", placeholder "Search on Thread");
+ ;button
+ ;img@"https://s3.spandrell.ch/assets/board/ui/search.svg";
+ ==
+ ==
+ ==
+ ;div#stats
+ ;p:"{post-count} Posts - {page-count} Pages"
+ ;p:"Showing posts {froms} to {tos}"
+ ==
+ ;div#page-nav
+ ;a.button/"1":"1"
+ ;a.button/"{prev-page}"
+ ;img@"https://s3.spandrell.ch/assets/board/ui/left.svg";
+ ==
+ ;a.button:"{curr-page}"
+ ;a.button/"{next-page}"
+ ;img@"https://s3.spandrell.ch/assets/board/ui/right.svg";
+ ==
+ ;a.button/"{page-count}":"{page-count}"
+ ==
+ ;button
+ =kaji "toggle"
+ =targ ".reply-box"
+ =modal "1"
+ ; Reply
+ ==
+==
+--