diff options
Diffstat (limited to 'ui')
-rw-r--r-- | ui/.gitignore | 3 | ||||
-rw-r--r-- | ui/package.json | 2 | ||||
-rw-r--r-- | ui/src/components/comment-form.tsx | 5 | ||||
-rw-r--r-- | ui/src/components/comment-node.tsx | 26 | ||||
-rw-r--r-- | ui/src/components/navbar.tsx | 2 | ||||
-rw-r--r-- | ui/src/components/post-form.tsx | 10 | ||||
-rw-r--r-- | ui/src/components/post-listing.tsx | 75 | ||||
-rw-r--r-- | ui/src/components/post.tsx | 20 | ||||
-rw-r--r-- | ui/src/components/private-message-form.tsx | 5 | ||||
-rw-r--r-- | ui/src/components/private-message.tsx | 15 | ||||
-rw-r--r-- | ui/src/components/sidebar.tsx | 11 | ||||
-rw-r--r-- | ui/src/interfaces.ts | 26 | ||||
-rw-r--r-- | ui/src/utils.ts | 14 | ||||
-rw-r--r-- | ui/yarn.lock | 15 |
14 files changed, 136 insertions, 93 deletions
diff --git a/ui/.gitignore b/ui/.gitignore index cc0ab540..bdd11a35 100644 --- a/ui/.gitignore +++ b/ui/.gitignore @@ -6,14 +6,11 @@ _site .git build .build -.git -.history .idea .jshintrc .nyc_output .sass-cache .vscode -build coverage jsconfig.json Gemfile.lock diff --git a/ui/package.json b/ui/package.json index 21458f0d..d2eb1de9 100644 --- a/ui/package.json +++ b/ui/package.json @@ -18,7 +18,7 @@ "@types/autosize": "^3.0.6", "@types/js-cookie": "^2.2.6", "@types/jwt-decode": "^2.2.1", - "@types/markdown-it": "^10.0.0", + "@types/markdown-it": "^0.0.9", "@types/markdown-it-container": "^2.0.2", "@types/node": "^13.11.1", "autosize": "^4.0.2", diff --git a/ui/src/components/comment-form.tsx b/ui/src/components/comment-form.tsx index 5239eb2c..b3c1a9a1 100644 --- a/ui/src/components/comment-form.tsx +++ b/ui/src/components/comment-form.tsx @@ -162,8 +162,9 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> { </button> {this.state.commentForm.content && ( <button - className={`btn btn-sm mr-2 btn-secondary ${this.state - .previewMode && 'active'}`} + className={`btn btn-sm mr-2 btn-secondary ${ + this.state.previewMode && 'active' + }`} onClick={linkEvent(this, this.handlePreviewToggle)} > {i18n.t('preview')} diff --git a/ui/src/components/comment-node.tsx b/ui/src/components/comment-node.tsx index ba4301e1..69a78f50 100644 --- a/ui/src/components/comment-node.tsx +++ b/ui/src/components/comment-node.tsx @@ -142,9 +142,11 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> { } > <div - class={`${!this.props.noIndent && + class={`${ + !this.props.noIndent && this.props.node.comment.parent_id && - 'ml-2'}`} + 'ml-2' + }`} > <div class="d-flex flex-wrap align-items-center mb-1 mt-1 text-muted small"> <span class="mr-2"> @@ -249,8 +251,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> { this.loadingIcon ) : ( <svg - class={`icon icon-inline ${node.comment.read && - 'text-success'}`} + class={`icon icon-inline ${ + node.comment.read && 'text-success' + }`} > <use xlinkHref="#icon-check"></use> </svg> @@ -302,8 +305,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> { this.loadingIcon ) : ( <svg - class={`icon icon-inline ${node.comment.saved && - 'text-warning'}`} + class={`icon icon-inline ${ + node.comment.saved && 'text-warning' + }`} > <use xlinkHref="#icon-star"></use> </svg> @@ -350,8 +354,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> { data-tippy-content={i18n.t('view_source')} > <svg - class={`icon icon-inline ${this.state - .viewSource && 'text-success'}`} + class={`icon icon-inline ${ + this.state.viewSource && 'text-success' + }`} > <use xlinkHref="#icon-file-text"></use> </svg> @@ -380,8 +385,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> { } > <svg - class={`icon icon-inline ${node.comment - .deleted && 'text-danger'}`} + class={`icon icon-inline ${ + node.comment.deleted && 'text-danger' + }`} > <use xlinkHref="#icon-trash"></use> </svg> diff --git a/ui/src/components/navbar.tsx b/ui/src/components/navbar.tsx index e0d8aff5..f1936be1 100644 --- a/ui/src/components/navbar.tsx +++ b/ui/src/components/navbar.tsx @@ -381,7 +381,7 @@ export class Navbar extends Component<any, NavbarState> { requestNotificationPermission() { if (UserService.Instance.user) { - document.addEventListener('DOMContentLoaded', function() { + document.addEventListener('DOMContentLoaded', function () { if (!Notification) { toast(i18n.t('notifications_error'), 'danger'); return; diff --git a/ui/src/components/post-form.tsx b/ui/src/components/post-form.tsx index 912d8e58..4dbc8b23 100644 --- a/ui/src/components/post-form.tsx +++ b/ui/src/components/post-form.tsx @@ -194,8 +194,9 @@ export class PostForm extends Component<PostFormProps, PostFormState> { <form> <label htmlFor="file-upload" - className={`${UserService.Instance.user && - 'pointer'} d-inline-block float-right text-muted font-weight-bold`} + className={`${ + UserService.Instance.user && 'pointer' + } d-inline-block float-right text-muted font-weight-bold`} data-tippy-content={i18n.t('upload_image')} > <svg class="icon icon-inline"> @@ -288,8 +289,9 @@ export class PostForm extends Component<PostFormProps, PostFormState> { )} {this.state.postForm.body && ( <button - className={`mt-1 mr-2 btn btn-sm btn-secondary ${this.state - .previewMode && 'active'}`} + className={`mt-1 mr-2 btn btn-sm btn-secondary ${ + this.state.previewMode && 'active' + }`} onClick={linkEvent(this, this.handlePreviewToggle)} > {i18n.t('preview')} diff --git a/ui/src/components/post-listing.tsx b/ui/src/components/post-listing.tsx index d0efa043..49749201 100644 --- a/ui/src/components/post-listing.tsx +++ b/ui/src/components/post-listing.tsx @@ -30,6 +30,7 @@ import { getUnixTime, pictshareImage, setupTippy, + hostname, previewLines, } from '../utils'; import { i18n } from '../i18next'; @@ -150,9 +151,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> { let post = this.props.post; return ( <img - className={`img-fluid thumbnail rounded ${(post.nsfw || - post.community_nsfw) && - 'img-blur'}`} + className={`img-fluid thumbnail rounded ${ + (post.nsfw || post.community_nsfw) && 'img-blur' + }`} src={src} /> ); @@ -312,22 +313,21 @@ export class PostListing extends Component<PostListingProps, PostListingState> { </Link> )} </h5> - {post.url && - !(new URL(post.url).hostname == window.location.hostname) && ( - <small class="d-inline-block"> - <a - className="ml-2 text-muted font-italic" - href={post.url} - target="_blank" - title={post.url} - > - {new URL(post.url).hostname} - <svg class="ml-1 icon icon-inline"> - <use xlinkHref="#icon-external-link"></use> - </svg> - </a> - </small> - )} + {post.url && !(hostname(post.url) == window.location.hostname) && ( + <small class="d-inline-block"> + <a + className="ml-2 text-muted font-italic" + href={post.url} + target="_blank" + title={post.url} + > + {hostname(post.url)} + <svg class="ml-1 icon icon-inline"> + <use xlinkHref="#icon-external-link"></use> + </svg> + </a> + </small> + )} {(isImage(post.url) || this.props.post.thumbnail_url) && ( <> {!this.state.imageExpanded ? ( @@ -440,9 +440,15 @@ export class PostListing extends Component<PostListingProps, PostListingState> { {this.props.showCommunity && ( <span> <span> {i18n.t('to')} </span> - <Link to={`/c/${post.community_name}`}> - {post.community_name} - </Link> + {post.local ? ( + <Link to={`/c/${post.community_name}`}> + {post.community_name} + </Link> + ) : ( + <a href={post.community_actor_id} target="_blank"> + {hostname(post.ap_id)}/{post.community_name} + </a> + )} </span> )} </li> @@ -542,8 +548,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> { } > <svg - class={`icon icon-inline ${post.saved && - 'text-warning'}`} + class={`icon icon-inline ${ + post.saved && 'text-warning' + }`} > <use xlinkHref="#icon-star"></use> </svg> @@ -586,8 +593,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> { } > <svg - class={`icon icon-inline ${post.deleted && - 'text-danger'}`} + class={`icon icon-inline ${ + post.deleted && 'text-danger' + }`} > <use xlinkHref="#icon-trash"></use> </svg> @@ -618,8 +626,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> { data-tippy-content={i18n.t('view_source')} > <svg - class={`icon icon-inline ${this.state - .viewSource && 'text-success'}`} + class={`icon icon-inline ${ + this.state.viewSource && 'text-success' + }`} > <use xlinkHref="#icon-file-text"></use> </svg> @@ -639,8 +648,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> { } > <svg - class={`icon icon-inline ${post.locked && - 'text-danger'}`} + class={`icon icon-inline ${ + post.locked && 'text-danger' + }`} > <use xlinkHref="#icon-lock"></use> </svg> @@ -657,8 +667,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> { } > <svg - class={`icon icon-inline ${post.stickied && - 'text-success'}`} + class={`icon icon-inline ${ + post.stickied && 'text-success' + }`} > <use xlinkHref="#icon-pin"></use> </svg> diff --git a/ui/src/components/post.tsx b/ui/src/components/post.tsx index de0f0e32..cf9e7486 100644 --- a/ui/src/components/post.tsx +++ b/ui/src/components/post.tsx @@ -213,8 +213,9 @@ export class Post extends Component<any, PostState> { return ( <div class="btn-group btn-group-toggle mb-2"> <label - className={`btn btn-sm btn-secondary pointer ${this.state - .commentSort === CommentSortType.Hot && 'active'}`} + className={`btn btn-sm btn-secondary pointer ${ + this.state.commentSort === CommentSortType.Hot && 'active' + }`} > {i18n.t('hot')} <input @@ -225,8 +226,9 @@ export class Post extends Component<any, PostState> { /> </label> <label - className={`btn btn-sm btn-secondary pointer ${this.state - .commentSort === CommentSortType.Top && 'active'}`} + className={`btn btn-sm btn-secondary pointer ${ + this.state.commentSort === CommentSortType.Top && 'active' + }`} > {i18n.t('top')} <input @@ -237,8 +239,9 @@ export class Post extends Component<any, PostState> { /> </label> <label - className={`btn btn-sm btn-secondary pointer ${this.state - .commentSort === CommentSortType.New && 'active'}`} + className={`btn btn-sm btn-secondary pointer ${ + this.state.commentSort === CommentSortType.New && 'active' + }`} > {i18n.t('new')} <input @@ -249,8 +252,9 @@ export class Post extends Component<any, PostState> { /> </label> <label - className={`btn btn-sm btn-secondary pointer ${this.state - .commentSort === CommentSortType.Old && 'active'}`} + className={`btn btn-sm btn-secondary pointer ${ + this.state.commentSort === CommentSortType.Old && 'active' + }`} > {i18n.t('old')} <input diff --git a/ui/src/components/private-message-form.tsx b/ui/src/components/private-message-form.tsx index 6b607654..14abacf6 100644 --- a/ui/src/components/private-message-form.tsx +++ b/ui/src/components/private-message-form.tsx @@ -222,8 +222,9 @@ export class PrivateMessageForm extends Component< </button> {this.state.privateMessageForm.content && ( <button - className={`btn btn-secondary mr-2 ${this.state.previewMode && - 'active'}`} + className={`btn btn-secondary mr-2 ${ + this.state.previewMode && 'active' + }`} onClick={linkEvent(this, this.handlePreviewToggle)} > {i18n.t('preview')} diff --git a/ui/src/components/private-message.tsx b/ui/src/components/private-message.tsx index 337b1650..3acd6e19 100644 --- a/ui/src/components/private-message.tsx +++ b/ui/src/components/private-message.tsx @@ -144,8 +144,9 @@ export class PrivateMessage extends Component< } > <svg - class={`icon icon-inline ${message.read && - 'text-success'}`} + class={`icon icon-inline ${ + message.read && 'text-success' + }`} > <use xlinkHref="#icon-check"></use> </svg> @@ -188,8 +189,9 @@ export class PrivateMessage extends Component< } > <svg - class={`icon icon-inline ${message.deleted && - 'text-danger'}`} + class={`icon icon-inline ${ + message.deleted && 'text-danger' + }`} > <use xlinkHref="#icon-trash"></use> </svg> @@ -204,8 +206,9 @@ export class PrivateMessage extends Component< data-tippy-content={i18n.t('view_source')} > <svg - class={`icon icon-inline ${this.state.viewSource && - 'text-success'}`} + class={`icon icon-inline ${ + this.state.viewSource && 'text-success' + }`} > <use xlinkHref="#icon-file-text"></use> </svg> diff --git a/ui/src/components/sidebar.tsx b/ui/src/components/sidebar.tsx index d66266f6..4b317aaa 100644 --- a/ui/src/components/sidebar.tsx +++ b/ui/src/components/sidebar.tsx @@ -111,8 +111,9 @@ export class Sidebar extends Component<SidebarProps, SidebarState> { } > <svg - class={`icon icon-inline ${community.deleted && - 'text-danger'}`} + class={`icon icon-inline ${ + community.deleted && 'text-danger' + }`} > <use xlinkHref="#icon-trash"></use> </svg> @@ -215,9 +216,9 @@ export class Sidebar extends Component<SidebarProps, SidebarState> { ))} </ul> <Link - class={`btn btn-sm btn-secondary btn-block mb-3 ${(community.deleted || - community.removed) && - 'no-click'}`} + class={`btn btn-sm btn-secondary btn-block mb-3 ${ + (community.deleted || community.removed) && 'no-click' + }`} to={`/create_post?community=${community.name}`} > {i18n.t('create_a_post')} diff --git a/ui/src/interfaces.ts b/ui/src/interfaces.ts index b77ccac6..12430836 100644 --- a/ui/src/interfaces.ts +++ b/ui/src/interfaces.ts @@ -100,10 +100,13 @@ export interface User { export interface UserView { id: number; + actor_id: string; name: string; avatar?: string; email?: string; matrix_user_id?: string; + bio?: string; + local: boolean; published: string; number_of_posts: number; post_score: number; @@ -117,15 +120,21 @@ export interface UserView { export interface CommunityUser { id: number; user_id: number; + user_actor_id: string; + user_local: boolean; user_name: string; avatar?: string; community_id: number; + community_actor_id: string; + community_local: boolean; community_name: string; published: string; } export interface Community { id: number; + actor_id: string; + local: boolean; name: string; title: string; description?: string; @@ -136,6 +145,9 @@ export interface Community { nsfw: boolean; published: string; updated?: string; + creator_actor_id: string; + creator_local: boolean; + last_refreshed_at: string; creator_name: string; creator_avatar?: string; category_name: string; @@ -161,13 +173,19 @@ export interface Post { embed_description?: string; embed_html?: string; thumbnail_url?: string; + ap_id: string; + local: boolean; nsfw: boolean; banned: boolean; banned_from_community: boolean; published: string; updated?: string; + creator_actor_id: string; + creator_local: boolean; creator_name: string; creator_avatar?: string; + community_actor_id: string; + community_local: boolean; community_name: string; community_removed: boolean; community_deleted: boolean; @@ -188,6 +206,8 @@ export interface Post { export interface Comment { id: number; + ap_id: string; + local: boolean; creator_id: number; post_id: number; parent_id?: number; @@ -198,9 +218,13 @@ export interface Comment { published: string; updated?: string; community_id: number; + community_actor_id: string; + community_local: boolean; community_name: string; banned: boolean; banned_from_community: boolean; + creator_actor_id: string; + creator_local: boolean; creator_name: string; creator_avatar?: string; score: number; @@ -213,6 +237,8 @@ export interface Comment { saved?: boolean; user_mention_id?: number; // For mention type recipient_id?: number; + recipient_actor_id?: string; + recipient_local?: boolean; depth?: number; } diff --git a/ui/src/utils.ts b/ui/src/utils.ts index 21a7fef8..480b41c7 100644 --- a/ui/src/utils.ts +++ b/ui/src/utils.ts @@ -118,11 +118,11 @@ export const md = new markdown_it({ typographer: true, }) .use(markdown_it_container, 'spoiler', { - validate: function(params: any) { + validate: function (params: any) { return params.trim().match(/^spoiler\s+(.*)$/); }, - render: function(tokens: any, idx: any) { + render: function (tokens: any, idx: any) { var m = tokens[idx].info.trim().match(/^spoiler\s+(.*)$/); if (tokens[idx].nesting === 1) { @@ -138,7 +138,7 @@ export const md = new markdown_it({ defs: objectFlip(emojiShortName), }); -md.renderer.rules.emoji = function(token, idx) { +md.renderer.rules.emoji = function (token, idx) { return twemoji.parse(token[idx].content); }; @@ -284,7 +284,7 @@ export function debounce( let timeout: any; // Calling debounce returns a new anonymous function - return function() { + return function () { // reference the context and args for the setTimeout function var context = this, args = arguments; @@ -300,7 +300,7 @@ export function debounce( clearTimeout(timeout); // Set the new timeout - timeout = setTimeout(function() { + timeout = setTimeout(function () { // Inside the timeout function, clear the timeout variable // which will let the next execution run when in 'immediate' mode timeout = null; @@ -841,3 +841,7 @@ export function previewLines(text: string, lines: number = 3): string { .slice(0, lines * 2) .join('\n'); } + +export function hostname(url: string): string { + return new URL(url).hostname; +} diff --git a/ui/yarn.lock b/ui/yarn.lock index 35ad32a0..4e94559e 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -234,26 +234,13 @@ dependencies: "@types/markdown-it" "*" -"@types/markdown-it@*": +"@types/markdown-it@*", "@types/markdown-it@^0.0.9": version "0.0.9" resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-0.0.9.tgz#a5d552f95216c478e0a27a5acc1b28dcffd989ce" integrity sha512-IFSepyZXbF4dgSvsk8EsgaQ/8Msv1I5eTL0BZ0X3iGO9jw6tCVtPG8HchIPm3wrkmGdqZOD42kE0zplVi1gYDA== dependencies: "@types/linkify-it" "*" -"@types/markdown-it@^10.0.0": - version "10.0.0" - resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-10.0.0.tgz#a2b5f9fb444bb27c1e0c4a0116fea09b3c6ebc1e" - integrity sha512-7UPBg1W0rfsqQ1JwNFfhxibKO0t7Q0scNt96XcFIFLGE/vhZamzZayaFS2LKha/26Pz7b/2GgiaxQZ1GUwW0dA== - dependencies: - "@types/linkify-it" "*" - "@types/mdurl" "*" - -"@types/mdurl@*": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9" - integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA== - "@types/node@^13.11.1": version "13.11.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.1.tgz#49a2a83df9d26daacead30d0ccc8762b128d53c7" |