diff --git a/package.json b/package.json index fd7cf4ad..2298d9e1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lemmy-ui", - "version": "0.18.0-beta.6", + "version": "0.18.0-rc.1", "description": "An isomorphic UI for lemmy", "repository": "https://github.com/LemmyNet/lemmy-ui", "license": "AGPL-3.0", diff --git a/src/assets/css/main.css b/src/assets/css/main.css index 3ff70e47..82f8433e 100644 --- a/src/assets/css/main.css +++ b/src/assets/css/main.css @@ -80,30 +80,6 @@ overflow-x: auto; } -.md-div table { - border-collapse: collapse; - width: 100%; - margin-bottom: 1rem; - border: 1px solid var(--dark); -} - -.md-div table th, -.md-div table td { - padding: 0.3rem; - vertical-align: top; - border-top: 1px solid var(--dark); - border: 1px solid var(--dark); -} - -.md-div table thead th { - vertical-align: bottom; - border-bottom: 2px solid var(--dark); -} - -.md-div table tbody + tbody { - border-top: 2px solid var(--dark); -} - .vote-bar { margin-top: -6.5px; } @@ -218,6 +194,11 @@ blockquote { overflow-y: auto; } +.comments { + list-style: none; + padding: 0; +} + .thumbnail { object-fit: cover; min-height: 60px; diff --git a/src/server/index.tsx b/src/server/index.tsx index 98063558..783845fb 100644 --- a/src/server/index.tsx +++ b/src/server/index.tsx @@ -160,7 +160,7 @@ server.get("/*", async (req, res) => { site = try_site.data; initializeSite(site); - if (path != "/setup" && !site.site_view.local_site.site_setup) { + if (path !== "/setup" && !site.site_view.local_site.site_setup) { return res.redirect("/setup"); } @@ -434,7 +434,7 @@ async function createSsrHtml(root: string, isoData: IsoDataOptionalSite) { - + { if (isBrowser()) { // On the first load, check the unreads this.requestNotificationPermission(); - await this.fetchUnreads(); + this.fetchUnreads(); this.requestNotificationPermission(); document.addEventListener("mouseup", this.handleOutsideMenuClick); @@ -406,35 +408,36 @@ export class Navbar extends Component { return amAdmin() || moderatesS; } - async fetchUnreads() { - const auth = myAuth(); - if (auth) { - this.setState({ unreadInboxCountRes: { state: "loading" } }); - this.setState({ - unreadInboxCountRes: await HttpService.client.getUnreadCount({ - auth, - }), - }); - - if (this.moderatesSomething) { - this.setState({ unreadReportCountRes: { state: "loading" } }); - this.setState({ - unreadReportCountRes: await HttpService.client.getReportCount({ - auth, - }), - }); - } - - if (amAdmin()) { - this.setState({ unreadApplicationCountRes: { state: "loading" } }); - this.setState({ - unreadApplicationCountRes: - await HttpService.client.getUnreadRegistrationApplicationCount({ + fetchUnreads() { + poll(async () => { + if (window.document.visibilityState !== "hidden") { + const auth = myAuth(); + if (auth) { + this.setState({ + unreadInboxCountRes: await HttpService.client.getUnreadCount({ auth, }), - }); + }); + + if (this.moderatesSomething) { + this.setState({ + unreadReportCountRes: await HttpService.client.getReportCount({ + auth, + }), + }); + } + + if (amAdmin()) { + this.setState({ + unreadApplicationCountRes: + await HttpService.client.getUnreadRegistrationApplicationCount({ + auth, + }), + }); + } + } } - } + }, updateUnreadCountsInterval); } get unreadInboxCount(): number { diff --git a/src/shared/components/comment/comment-node.tsx b/src/shared/components/comment/comment-node.tsx index 8559f38b..0380a726 100644 --- a/src/shared/components/comment/comment-node.tsx +++ b/src/shared/components/comment/comment-node.tsx @@ -270,9 +270,6 @@ export class CommentNode extends Component { this.props.moderators ); - const borderColor = this.props.node.depth - ? colorList[(this.props.node.depth - 1) % colorList.length] - : colorList[0]; const moreRepliesBorderColor = this.props.node.depth ? colorList[this.props.node.depth % colorList.length] : colorList[0]; @@ -284,26 +281,17 @@ export class CommentNode extends Component { node.comment_view.counts.child_count > 0; return ( -
+
  • @@ -959,9 +947,9 @@ export class CommentNode extends Component {
    {showMoreChildren && (
    + {this.state.collapsed &&
    } +
  • ); } @@ -1211,6 +1201,7 @@ export class CommentNode extends Component { linkBtn(small = false) { const cv = this.commentView; + const classnames = classNames("btn btn-link btn-animate text-muted", { "btn-sm": small, }); diff --git a/src/shared/components/comment/comment-nodes.tsx b/src/shared/components/comment/comment-nodes.tsx index 3f9b48ef..8c0a236e 100644 --- a/src/shared/components/comment/comment-nodes.tsx +++ b/src/shared/components/comment/comment-nodes.tsx @@ -1,3 +1,4 @@ +import classNames from "classnames"; import { Component } from "inferno"; import { AddAdmin, @@ -25,6 +26,7 @@ import { TransferCommunity, } from "lemmy-js-client"; import { CommentNodeI, CommentViewType } from "../../interfaces"; +import { colorList } from "../../utils"; import { CommentNode } from "./comment-node"; interface CommentNodesProps { @@ -44,6 +46,8 @@ interface CommentNodesProps { allLanguages: Language[]; siteLanguages: number[]; hideImages?: boolean; + isChild?: boolean; + depth?: number; finished: Map; onSaveComment(form: SaveComment): void; onCommentReplyRead(form: MarkCommentReplyAsRead): void; @@ -74,49 +78,61 @@ export class CommentNodes extends Component { render() { const maxComments = this.props.maxCommentsShown ?? this.props.nodes.length; + const borderColor = this.props.depth + ? colorList[this.props.depth % colorList.length] + : colorList[0]; + return ( -
    - {this.props.nodes.slice(0, maxComments).map(node => ( - - ))} -
    + this.props.nodes.length > 0 && ( +
      + {this.props.nodes.slice(0, maxComments).map(node => ( + + ))} +
    + ) ); } } diff --git a/src/shared/components/home/home.tsx b/src/shared/components/home/home.tsx index cc9dd518..3daaa4fd 100644 --- a/src/shared/components/home/home.tsx +++ b/src/shared/components/home/home.tsx @@ -266,9 +266,10 @@ export class Home extends Component { } async componentDidMount() { - if (!this.state.isIsomorphic) { + if (!this.state.isIsomorphic || !this.isoData.routeData.length) { await Promise.all([this.fetchTrendingCommunities(), this.fetchData()]); } + setupTippy(); } @@ -480,7 +481,7 @@ export class Home extends Component { } trendingCommunities(isMobile = false) { - switch (this.state.trendingCommunitiesRes.state) { + switch (this.state.trendingCommunitiesRes?.state) { case "loading": return (
    @@ -597,7 +598,7 @@ export class Home extends Component { const siteRes = this.state.siteRes; if (dataType === DataType.Post) { - switch (this.state.postsRes.state) { + switch (this.state.postsRes?.state) { case "loading": return (
    diff --git a/src/shared/components/home/login.tsx b/src/shared/components/home/login.tsx index 94915542..381c13bb 100644 --- a/src/shared/components/home/login.tsx +++ b/src/shared/components/home/login.tsx @@ -186,7 +186,9 @@ export class Login extends Component { UserService.Instance.myUserInfo = site.data.my_user; } - i.props.history.replace("/"); + i.props.history.action === "PUSH" + ? i.props.history.back() + : i.props.history.replace("/"); break; } diff --git a/src/shared/components/post/post-listing.tsx b/src/shared/components/post/post-listing.tsx index d5fc785c..60e188a3 100644 --- a/src/shared/components/post/post-listing.tsx +++ b/src/shared/components/post/post-listing.tsx @@ -1382,9 +1382,12 @@ export class PostListing extends Component { } showMobilePreview() { - const body = this.postView.post.body; + const { body, id } = this.postView.post; + return !this.showBody && body ? ( -
    {body}
    + +
    {body}
    + ) : ( <> ); diff --git a/src/shared/components/post/post-listings.tsx b/src/shared/components/post/post-listings.tsx index 098a015d..00370f03 100644 --- a/src/shared/components/post/post-listings.tsx +++ b/src/shared/components/post/post-listings.tsx @@ -68,7 +68,7 @@ export class PostListings extends Component { return (
    {this.posts.length > 0 ? ( - this.posts.map(post_view => ( + this.posts.map((post_view, idx) => ( <> { onAddAdmin={this.props.onAddAdmin} onTransferCommunity={this.props.onTransferCommunity} /> -
    + {idx + 1 !== this.posts.length && ( +
    + )} )) ) : ( diff --git a/src/shared/utils.ts b/src/shared/utils.ts index 83cc6f1a..cf59086b 100644 --- a/src/shared/utils.ts +++ b/src/shared/utils.ts @@ -76,6 +76,7 @@ export const commentTreeMaxDepth = 8; export const markdownFieldCharacterLimit = 50000; export const maxUploadImages = 20; export const concurrentImageUpload = 4; +export const updateUnreadCountsInterval = 30000; export const relTags = "noopener nofollow"; @@ -739,7 +740,7 @@ function setupMarkdown() { defs: emojiDefs, }) .disable("image"); - var defaultRenderer = md.renderer.rules.image; + const defaultRenderer = md.renderer.rules.image; md.renderer.rules.image = function ( tokens: Token[], idx: number, @@ -758,6 +759,9 @@ function setupMarkdown() { const alt_text = item.content; return `${alt_text}`; }; + md.renderer.rules.table_open = function () { + return ''; + }; } export function getEmojiMart( @@ -1128,7 +1132,7 @@ export const colorList: string[] = [ ]; function hsl(num: number) { - return `hsla(${num}, 35%, 50%, 1)`; + return `hsla(${num}, 35%, 50%, 0.5)`; } export function hostname(url: string): string { @@ -1497,3 +1501,18 @@ export function newVote(voteType: VoteType, myVote?: number): number { export type RouteDataResponse> = { [K in keyof T]: RequestState>; }; + +function sleep(millis: number): Promise { + return new Promise(resolve => setTimeout(resolve, millis)); +} + +/** + * Polls / repeatedly runs a promise, every X milliseconds + */ +export async function poll(promiseFn: any, millis: number) { + if (window.document.visibilityState !== "hidden") { + await promiseFn(); + } + await sleep(millis); + return poll(promiseFn, millis); +}