A better mobile view, upgrading darkly theme.
This commit is contained in:
parent
6fa9dc599c
commit
c5443b6e82
5 changed files with 841 additions and 697 deletions
104
ui/assets/css/themes/_variables.darkly.scss
vendored
Normal file
104
ui/assets/css/themes/_variables.darkly.scss
vendored
Normal file
|
@ -0,0 +1,104 @@
|
|||
|
||||
$white: #fff;
|
||||
$gray-100: #f8f9fa;
|
||||
$gray-200: #ebebeb;
|
||||
$gray-300: #dee2e6;
|
||||
$gray-400: #ced4da;
|
||||
$gray-500: #adb5bd;
|
||||
$gray-600: #888;
|
||||
$gray-700: #444;
|
||||
$gray-800: #303030;
|
||||
$gray-900: #222;
|
||||
$black: #000;
|
||||
$blue: #375a7f;
|
||||
$indigo: #6610f2;
|
||||
$purple: #6f42c1;
|
||||
$pink: #e83e8c;
|
||||
$red: #e74c3c;
|
||||
$orange: #fd7e14;
|
||||
$yellow: #f39c12;
|
||||
$green: #00bc8c;
|
||||
$teal: #20c997;
|
||||
$cyan: #3498db;
|
||||
$primary: $blue;
|
||||
$secondary: $gray-700;
|
||||
$success: $green;
|
||||
$info: $cyan;
|
||||
$warning: $yellow;
|
||||
$danger: $red;
|
||||
$dark: $gray-300;
|
||||
$yiq-contrasted-threshold: 175;
|
||||
$body-bg: $gray-900;
|
||||
$body-color: $gray-300;
|
||||
$link-color: $success;
|
||||
$font-family-sans-serif: "Lato", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
$font-size-base: 0.9375rem;
|
||||
$h1-font-size: 3rem;
|
||||
$h2-font-size: 2.5rem;
|
||||
$h3-font-size: 2rem;
|
||||
$text-muted: $gray-600;
|
||||
$table-accent-bg: $gray-800;
|
||||
$table-border-color: $gray-700;
|
||||
$input-border-color: $body-bg;
|
||||
$input-group-addon-color: $gray-500;
|
||||
$input-group-addon-bg: $gray-700;
|
||||
$custom-file-color: $gray-500;
|
||||
$custom-file-border-color: $body-bg;
|
||||
$dropdown-bg: $gray-900;
|
||||
$dropdown-border-color: $gray-700;
|
||||
$dropdown-divider-bg: $gray-700;
|
||||
$dropdown-link-color: $white;
|
||||
$dropdown-link-hover-color: $white;
|
||||
$dropdown-link-hover-bg: $primary;
|
||||
$nav-link-padding-x: 2rem;
|
||||
$nav-link-disabled-color: $gray-500;
|
||||
$nav-tabs-border-color: $gray-700;
|
||||
$nav-tabs-link-hover-border-color: $nav-tabs-border-color $nav-tabs-border-color transparent;
|
||||
$nav-tabs-link-active-color: $white;
|
||||
$nav-tabs-link-active-border-color: $nav-tabs-border-color $nav-tabs-border-color transparent;
|
||||
$navbar-padding-y: 1rem;
|
||||
$navbar-dark-color: rgba($white,.6);
|
||||
$navbar-dark-hover-color: $white;
|
||||
$navbar-light-color: rgba($white,.6);
|
||||
$navbar-light-hover-color: $white;
|
||||
$navbar-light-active-color: $white;
|
||||
$navbar-light-toggler-border-color: rgba($gray-900, .1);
|
||||
$pagination-color: $white;
|
||||
$pagination-bg: $success;
|
||||
$pagination-border-width: 0;
|
||||
$pagination-border-color: transparent;
|
||||
$pagination-hover-color: $white;
|
||||
$pagination-hover-bg: lighten($success, 10%);
|
||||
$pagination-hover-border-color: transparent;
|
||||
$pagination-active-bg: $pagination-hover-bg;
|
||||
$pagination-active-border-color: transparent;
|
||||
$pagination-disabled-color: $white;
|
||||
$pagination-disabled-bg: darken($success, 15%);
|
||||
$pagination-disabled-border-color: transparent;
|
||||
$jumbotron-bg: $gray-800;
|
||||
$card-cap-bg: $gray-700;
|
||||
$card-bg: $gray-800;
|
||||
$popover-bg: $gray-800;
|
||||
$popover-header-bg: $gray-700;
|
||||
$toast-background-color: $gray-700;
|
||||
$toast-header-background-color: $gray-800;
|
||||
$modal-content-bg: $gray-800;
|
||||
$modal-content-border-color: $gray-700;
|
||||
$modal-header-border-color: $gray-700;
|
||||
$progress-bg: $gray-700;
|
||||
$list-group-bg: $gray-800;
|
||||
$list-group-border-color: $gray-700;
|
||||
$list-group-hover-bg: $gray-700;
|
||||
$breadcrumb-bg: $gray-700;
|
||||
$close-color: $white;
|
||||
$close-text-shadow: none;
|
||||
$pre-color: inherit;
|
||||
$mark-bg: #333;
|
||||
$custom-select-bg: $secondary;
|
||||
$custom-select-color: $white;
|
||||
$input-bg: $secondary;
|
||||
$input-color: $white;
|
||||
$input-disabled-bg: darken($secondary, 10%);;
|
||||
$light: $gray-800;
|
||||
$navbar-light-brand-color: $navbar-dark-active-color;
|
||||
$navbar-light-brand-hover-color: $navbar-dark-active-color;
|
36
ui/assets/css/themes/darkly.min.css
vendored
36
ui/assets/css/themes/darkly.min.css
vendored
File diff suppressed because one or more lines are too long
4
ui/src/components/navbar.tsx
vendored
4
ui/src/components/navbar.tsx
vendored
|
@ -184,7 +184,7 @@ export class Navbar extends Component<any, NavbarState> {
|
|||
{!this.state.siteLoading ? (
|
||||
<Link
|
||||
title={this.state.siteRes.version}
|
||||
class="d-flex align-items-center navbar-brand mr-1"
|
||||
class="d-flex align-items-center navbar-brand mr-md-3"
|
||||
to="/"
|
||||
>
|
||||
{this.state.siteRes.site.icon && showAvatars() && (
|
||||
|
@ -235,7 +235,7 @@ export class Navbar extends Component<any, NavbarState> {
|
|||
!this.state.expanded && 'collapse'
|
||||
} navbar-collapse`}
|
||||
>
|
||||
<ul class="ml-3 navbar-nav my-2 mr-auto">
|
||||
<ul class="navbar-nav my-2 mr-auto">
|
||||
<li class="nav-item">
|
||||
<Link
|
||||
class="nav-link"
|
||||
|
|
392
ui/src/components/post-listing.tsx
vendored
392
ui/src/components/post-listing.tsx
vendored
|
@ -163,7 +163,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
return (
|
||||
<img
|
||||
className={`img-fluid thumbnail rounded ${
|
||||
(post.nsfw || post.community_nsfw) && 'img-blur'
|
||||
post.nsfw || post.community_nsfw ? 'img-blur' : ''
|
||||
}`}
|
||||
src={src}
|
||||
/>
|
||||
|
@ -190,8 +190,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
|
||||
if (isImage(post.url)) {
|
||||
return (
|
||||
<span
|
||||
class="text-body pointer"
|
||||
<div
|
||||
class="text-body pointer d-inline-block position-relative"
|
||||
data-tippy-content={i18n.t('expand_here')}
|
||||
onClick={linkEvent(this, this.handleImageExpandClick)}
|
||||
>
|
||||
|
@ -199,12 +199,12 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
<svg class="icon mini-overlay">
|
||||
<use xlinkHref="#icon-image"></use>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
} else if (post.thumbnail_url) {
|
||||
return (
|
||||
<a
|
||||
className="text-body"
|
||||
class="text-body d-inline-block position-relative"
|
||||
href={post.url}
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
|
@ -265,10 +265,93 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
}
|
||||
}
|
||||
|
||||
listing() {
|
||||
createdLine() {
|
||||
let post = this.props.post;
|
||||
return (
|
||||
<div class="row">
|
||||
<ul class="list-inline mb-1 text-muted small">
|
||||
<li className="list-inline-item">
|
||||
<UserListing
|
||||
user={{
|
||||
name: post.creator_name,
|
||||
preferred_username: post.creator_preferred_username,
|
||||
avatar: post.creator_avatar,
|
||||
id: post.creator_id,
|
||||
local: post.creator_local,
|
||||
actor_id: post.creator_actor_id,
|
||||
published: post.creator_published,
|
||||
}}
|
||||
/>
|
||||
|
||||
{this.isMod && (
|
||||
<span className="mx-1 badge badge-light">{i18n.t('mod')}</span>
|
||||
)}
|
||||
{this.isAdmin && (
|
||||
<span className="mx-1 badge badge-light">{i18n.t('admin')}</span>
|
||||
)}
|
||||
{(post.banned_from_community || post.banned) && (
|
||||
<span className="mx-1 badge badge-danger">{i18n.t('banned')}</span>
|
||||
)}
|
||||
{this.props.showCommunity && (
|
||||
<span>
|
||||
<span class="mx-1"> {i18n.t('to')} </span>
|
||||
<CommunityLink
|
||||
community={{
|
||||
name: post.community_name,
|
||||
id: post.community_id,
|
||||
local: post.community_local,
|
||||
actor_id: post.community_actor_id,
|
||||
icon: post.community_icon,
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</li>
|
||||
<li className="list-inline-item">•</li>
|
||||
{post.url && !(hostname(post.url) == window.location.hostname) && (
|
||||
<>
|
||||
<li className="list-inline-item">
|
||||
<a
|
||||
className="text-muted font-italic"
|
||||
href={post.url}
|
||||
target="_blank"
|
||||
title={post.url}
|
||||
rel="noopener"
|
||||
>
|
||||
{hostname(post.url)}
|
||||
</a>
|
||||
</li>
|
||||
<li className="list-inline-item">•</li>
|
||||
</>
|
||||
)}
|
||||
<li className="list-inline-item">
|
||||
<span>
|
||||
<MomentTime data={post} />
|
||||
</span>
|
||||
</li>
|
||||
{post.body && (
|
||||
<>
|
||||
<li className="list-inline-item">•</li>
|
||||
<li className="list-inline-item">
|
||||
{/* Using a link with tippy doesn't work on touch devices unfortunately */}
|
||||
<Link
|
||||
className="text-muted"
|
||||
data-tippy-content={md.render(previewLines(post.body))}
|
||||
data-tippy-allowHtml={true}
|
||||
to={`/post/${post.id}`}
|
||||
>
|
||||
<svg class="mr-1 icon icon-inline">
|
||||
<use xlinkHref="#icon-book-open"></use>
|
||||
</svg>
|
||||
</Link>
|
||||
</li>
|
||||
</>
|
||||
)}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
voteBar() {
|
||||
return (
|
||||
<div className={`vote-bar col-1 pr-0 small text-center`}>
|
||||
<button
|
||||
className={`btn-animate btn btn-link p-0 ${
|
||||
|
@ -301,18 +384,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
</button>
|
||||
)}
|
||||
</div>
|
||||
{!this.state.imageExpanded && (
|
||||
<div class="col-3 col-sm-2 pr-0">
|
||||
<div class="position-relative">{this.thumbnail()}</div>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
class={`${this.state.imageExpanded ? 'col-12' : 'col-8 col-sm-9'}`}
|
||||
>
|
||||
<div class="row">
|
||||
<div className="col-12">
|
||||
<div className="post-title">
|
||||
<h5 className="mb-1 d-inline-block">
|
||||
);
|
||||
}
|
||||
|
||||
postTitleLine() {
|
||||
let post = this.props.post;
|
||||
return (
|
||||
<div className="post-title overflow-hidden">
|
||||
<h5>
|
||||
{this.props.showBody && post.url ? (
|
||||
<a
|
||||
className={!post.stickied ? 'text-body' : 'text-primary'}
|
||||
|
@ -332,23 +411,6 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
{post.name}
|
||||
</Link>
|
||||
)}
|
||||
</h5>
|
||||
{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}
|
||||
rel="noopener"
|
||||
>
|
||||
{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 ? (
|
||||
|
@ -374,10 +436,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
<div>
|
||||
<span
|
||||
class="pointer"
|
||||
onClick={linkEvent(
|
||||
this,
|
||||
this.handleImageExpandClick
|
||||
)}
|
||||
onClick={linkEvent(this, this.handleImageExpandClick)}
|
||||
>
|
||||
<img
|
||||
class="img-fluid img-expanded"
|
||||
|
@ -429,82 +488,15 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
{i18n.t('nsfw')}
|
||||
</small>
|
||||
)}
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div className="details col-12">
|
||||
<ul class="list-inline mb-1 text-muted small">
|
||||
<li className="list-inline-item">
|
||||
<span>{i18n.t('by')} </span>
|
||||
<UserListing
|
||||
user={{
|
||||
name: post.creator_name,
|
||||
preferred_username: post.creator_preferred_username,
|
||||
avatar: post.creator_avatar,
|
||||
id: post.creator_id,
|
||||
local: post.creator_local,
|
||||
actor_id: post.creator_actor_id,
|
||||
published: post.creator_published,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
{this.isMod && (
|
||||
<span className="mx-1 badge badge-light">
|
||||
{i18n.t('mod')}
|
||||
</span>
|
||||
)}
|
||||
{this.isAdmin && (
|
||||
<span className="mx-1 badge badge-light">
|
||||
{i18n.t('admin')}
|
||||
</span>
|
||||
)}
|
||||
{(post.banned_from_community || post.banned) && (
|
||||
<span className="mx-1 badge badge-danger">
|
||||
{i18n.t('banned')}
|
||||
</span>
|
||||
)}
|
||||
{this.props.showCommunity && (
|
||||
<span>
|
||||
<span> {i18n.t('to')} </span>
|
||||
<CommunityLink
|
||||
community={{
|
||||
name: post.community_name,
|
||||
id: post.community_id,
|
||||
local: post.community_local,
|
||||
actor_id: post.community_actor_id,
|
||||
icon: post.community_icon,
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</li>
|
||||
<li className="list-inline-item">•</li>
|
||||
<li className="list-inline-item">
|
||||
<span>
|
||||
<MomentTime data={post} />
|
||||
</span>
|
||||
</li>
|
||||
{post.body && (
|
||||
<>
|
||||
<li className="list-inline-item">•</li>
|
||||
<li className="list-inline-item">
|
||||
{/* Using a link with tippy doesn't work on touch devices unfortunately */}
|
||||
<Link
|
||||
className="text-muted"
|
||||
data-tippy-content={md.render(previewLines(post.body))}
|
||||
data-tippy-allowHtml={true}
|
||||
to={`/post/${post.id}`}
|
||||
>
|
||||
<svg class="mr-1 icon icon-inline">
|
||||
<use xlinkHref="#icon-book-open"></use>
|
||||
</svg>
|
||||
</Link>
|
||||
</li>
|
||||
</>
|
||||
)}
|
||||
</ul>
|
||||
<ul class="list-inline mb-1 text-muted small">
|
||||
commentsLine(showVotes: boolean = false) {
|
||||
let post = this.props.post;
|
||||
return (
|
||||
<ul class="d-flex align-items-center list-inline mb-1 text-muted small">
|
||||
<li className="list-inline-item">
|
||||
<Link
|
||||
className="text-muted"
|
||||
|
@ -521,7 +513,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
})}
|
||||
</Link>
|
||||
</li>
|
||||
{this.state.upvotes !== this.state.score && (
|
||||
{(showVotes || this.state.upvotes !== this.state.score) && (
|
||||
<>
|
||||
<li className="list-inline-item">•</li>
|
||||
<span
|
||||
|
@ -529,26 +521,41 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
data-tippy-content={this.pointsTippy}
|
||||
>
|
||||
<li className="list-inline-item">
|
||||
<span className="text-muted">
|
||||
<a
|
||||
className={`btn-animate btn btn-link p-0 ${
|
||||
this.state.my_vote == 1 ? 'text-info' : 'text-muted'
|
||||
}`}
|
||||
onClick={linkEvent(this, this.handlePostLike)}
|
||||
>
|
||||
<svg class="small icon icon-inline mr-1">
|
||||
<use xlinkHref="#icon-arrow-up"></use>
|
||||
</svg>
|
||||
{this.state.upvotes}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li className="list-inline-item">
|
||||
<span className="text-muted">
|
||||
<a
|
||||
className={`btn-animate btn btn-link p-0 ${
|
||||
this.state.my_vote == -1 ? 'text-danger' : 'text-muted'
|
||||
}`}
|
||||
onClick={linkEvent(this, this.handlePostDisLike)}
|
||||
>
|
||||
<svg class="small icon icon-inline mr-1">
|
||||
<use xlinkHref="#icon-arrow-down"></use>
|
||||
</svg>
|
||||
{this.state.downvotes}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</ul>
|
||||
{this.props.post.duplicates && (
|
||||
);
|
||||
}
|
||||
|
||||
duplicatesLine() {
|
||||
return (
|
||||
this.props.post.duplicates && (
|
||||
<ul class="list-inline mb-1 small text-muted">
|
||||
<>
|
||||
<li className="list-inline-item mr-2">
|
||||
|
@ -556,14 +563,18 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
</li>
|
||||
{this.props.post.duplicates.map(post => (
|
||||
<li className="list-inline-item mr-2">
|
||||
<Link to={`/post/${post.id}`}>
|
||||
{post.community_name}
|
||||
</Link>
|
||||
<Link to={`/post/${post.id}`}>{post.community_name}</Link>
|
||||
</li>
|
||||
))}
|
||||
</>
|
||||
</ul>
|
||||
)}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
postActions() {
|
||||
let post = this.props.post;
|
||||
return (
|
||||
<ul class="list-inline mb-1 text-muted font-weight-bold">
|
||||
{UserService.Instance.user && (
|
||||
<>
|
||||
|
@ -578,9 +589,7 @@ 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>
|
||||
|
@ -617,9 +626,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
class="btn btn-link btn-animate text-muted"
|
||||
onClick={linkEvent(this, this.handleDeleteClick)}
|
||||
data-tippy-content={
|
||||
!post.deleted
|
||||
? i18n.t('delete')
|
||||
: i18n.t('restore')
|
||||
!post.deleted ? i18n.t('delete') : i18n.t('restore')
|
||||
}
|
||||
>
|
||||
<svg
|
||||
|
@ -672,9 +679,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
class="btn btn-link btn-animate text-muted"
|
||||
onClick={linkEvent(this, this.handleModLock)}
|
||||
data-tippy-content={
|
||||
post.locked
|
||||
? i18n.t('unlock')
|
||||
: i18n.t('lock')
|
||||
post.locked ? i18n.t('unlock') : i18n.t('lock')
|
||||
}
|
||||
>
|
||||
<svg
|
||||
|
@ -691,9 +696,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
class="btn btn-link btn-animate text-muted"
|
||||
onClick={linkEvent(this, this.handleModSticky)}
|
||||
data-tippy-content={
|
||||
post.stickied
|
||||
? i18n.t('unsticky')
|
||||
: i18n.t('sticky')
|
||||
post.stickied ? i18n.t('unsticky') : i18n.t('sticky')
|
||||
}
|
||||
>
|
||||
<svg
|
||||
|
@ -713,20 +716,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
{!post.removed ? (
|
||||
<span
|
||||
class="pointer"
|
||||
onClick={linkEvent(
|
||||
this,
|
||||
this.handleModRemoveShow
|
||||
)}
|
||||
onClick={linkEvent(this, this.handleModRemoveShow)}
|
||||
>
|
||||
{i18n.t('remove')}
|
||||
</span>
|
||||
) : (
|
||||
<span
|
||||
class="pointer"
|
||||
onClick={linkEvent(
|
||||
this,
|
||||
this.handleModRemoveSubmit
|
||||
)}
|
||||
onClick={linkEvent(this, this.handleModRemoveSubmit)}
|
||||
>
|
||||
{i18n.t('restore')}
|
||||
</span>
|
||||
|
@ -778,8 +775,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
</>
|
||||
)}
|
||||
{/* Community creators and admins can transfer community to another mod */}
|
||||
{(this.amCommunityCreator || this.canAdmin) &&
|
||||
this.isMod && (
|
||||
{(this.amCommunityCreator || this.canAdmin) && this.isMod && (
|
||||
<li className="list-inline-item">
|
||||
{!this.state.showConfirmTransferCommunity ? (
|
||||
<span
|
||||
|
@ -809,8 +805,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
class="pointer d-inline-block"
|
||||
onClick={linkEvent(
|
||||
this,
|
||||
this
|
||||
.handleCancelShowConfirmTransferCommunity
|
||||
this.handleCancelShowConfirmTransferCommunity
|
||||
)}
|
||||
>
|
||||
{i18n.t('no')}
|
||||
|
@ -827,20 +822,14 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
{!post.banned ? (
|
||||
<span
|
||||
class="pointer"
|
||||
onClick={linkEvent(
|
||||
this,
|
||||
this.handleModBanShow
|
||||
)}
|
||||
onClick={linkEvent(this, this.handleModBanShow)}
|
||||
>
|
||||
{i18n.t('ban_from_site')}
|
||||
</span>
|
||||
) : (
|
||||
<span
|
||||
class="pointer"
|
||||
onClick={linkEvent(
|
||||
this,
|
||||
this.handleModBanSubmit
|
||||
)}
|
||||
onClick={linkEvent(this, this.handleModBanSubmit)}
|
||||
>
|
||||
{i18n.t('unban_from_site')}
|
||||
</span>
|
||||
|
@ -881,10 +870,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
</span>
|
||||
<span
|
||||
class="pointer d-inline-block mr-1"
|
||||
onClick={linkEvent(
|
||||
this,
|
||||
this.handleTransferSite
|
||||
)}
|
||||
onClick={linkEvent(this, this.handleTransferSite)}
|
||||
>
|
||||
{i18n.t('yes')}
|
||||
</span>
|
||||
|
@ -906,6 +892,13 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
</>
|
||||
)}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
removeAndBanDialogs() {
|
||||
let post = this.props.post;
|
||||
return (
|
||||
<>
|
||||
{this.state.showRemoveDialog && (
|
||||
<form
|
||||
class="form-inline"
|
||||
|
@ -950,10 +943,89 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
</div>
|
||||
</form>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
mobileThumbnail() {
|
||||
return this.props.post.thumbnail_url || isImage(this.props.post.url) ? (
|
||||
<div class="row">
|
||||
<div class="col-8">{this.postTitleLine()}</div>
|
||||
<div class="col-4">
|
||||
{/* Post body prev or thumbnail */}
|
||||
{!this.state.imageExpanded && this.thumbnail()}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
this.postTitleLine()
|
||||
);
|
||||
}
|
||||
|
||||
showMobilePreview() {
|
||||
return (
|
||||
this.props.post.body &&
|
||||
!this.props.showBody && (
|
||||
<div
|
||||
className="md-div mb-1"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: md.render(previewLines(this.props.post.body)),
|
||||
}}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
listing() {
|
||||
return (
|
||||
<>
|
||||
{/* The mobile view*/}
|
||||
<div class="d-block d-sm-none">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
{this.createdLine()}
|
||||
|
||||
{/* If it has a thumbnail, do a right aligned thumbnail */}
|
||||
{this.mobileThumbnail()}
|
||||
|
||||
{/* Show a preview of the post body */}
|
||||
{this.showMobilePreview()}
|
||||
|
||||
{this.commentsLine(true)}
|
||||
{this.duplicatesLine()}
|
||||
{this.postActions()}
|
||||
{this.removeAndBanDialogs()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* The larger view*/}
|
||||
<div class="d-none d-sm-block">
|
||||
<div class="row">
|
||||
{this.voteBar()}
|
||||
{!this.state.imageExpanded && (
|
||||
<div class="col-sm-2 pr-0">
|
||||
<div class="">{this.thumbnail()}</div>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
class={`${
|
||||
this.state.imageExpanded ? 'col-12' : 'col-12 col-sm-9'
|
||||
}`}
|
||||
>
|
||||
<div class="row">
|
||||
<div className="col-12">
|
||||
{this.postTitleLine()}
|
||||
{this.createdLine()}
|
||||
{this.commentsLine()}
|
||||
{this.duplicatesLine()}
|
||||
{this.postActions()}
|
||||
{this.removeAndBanDialogs()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
6
ui/src/utils.ts
vendored
6
ui/src/utils.ts
vendored
|
@ -982,10 +982,12 @@ function randomHsl() {
|
|||
|
||||
export function previewLines(text: string, lines: number = 3): string {
|
||||
// Use lines * 2 because markdown requires 2 lines
|
||||
return text
|
||||
return (
|
||||
text
|
||||
.split('\n')
|
||||
.slice(0, lines * 2)
|
||||
.join('\n');
|
||||
.join('\n') + '...'
|
||||
);
|
||||
}
|
||||
|
||||
export function hostname(url: string): string {
|
||||
|
|
Loading…
Reference in a new issue