forked from nutomic/lemmy
Use image thumbnails from pictshare. Fixes #555
This commit is contained in:
parent
e784cc8b72
commit
2092cf3f4e
4 changed files with 72 additions and 60 deletions
10
ui/assets/css/main.css
vendored
10
ui/assets/css/main.css
vendored
|
@ -188,16 +188,6 @@ hr {
|
||||||
border: unset;
|
border: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.img-expand-overlay {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
padding: 2px;
|
|
||||||
background: rgba(0,0,0,.4);
|
|
||||||
border-bottom-left-radius: 0.25rem !important;
|
|
||||||
border-top-right-radius: 0.25rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-overlay:hover {
|
.link-overlay:hover {
|
||||||
transition: .1s;
|
transition: .1s;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|
4
ui/package.json
vendored
4
ui/package.json
vendored
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"name": "lemmy",
|
"name": "lemmy",
|
||||||
"description": "A simple UI for lemmy",
|
"description": "The official Lemmy UI",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Dessalines",
|
"author": "Dessalines",
|
||||||
"license": "GPL-2.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "node fuse prod",
|
"build": "node fuse prod",
|
||||||
|
|
108
ui/src/components/post-listing.tsx
vendored
108
ui/src/components/post-listing.tsx
vendored
|
@ -51,6 +51,7 @@ interface PostListingState {
|
||||||
downvotes: number;
|
downvotes: number;
|
||||||
url: string;
|
url: string;
|
||||||
iframely: FramelyData;
|
iframely: FramelyData;
|
||||||
|
thumbnail: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PostListingProps {
|
interface PostListingProps {
|
||||||
|
@ -80,6 +81,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
downvotes: this.props.post.downvotes,
|
downvotes: this.props.post.downvotes,
|
||||||
url: this.props.post.url,
|
url: this.props.post.url,
|
||||||
iframely: null,
|
iframely: null,
|
||||||
|
thumbnail: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
|
@ -92,6 +94,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
this.handleEditCancel = this.handleEditCancel.bind(this);
|
this.handleEditCancel = this.handleEditCancel.bind(this);
|
||||||
|
|
||||||
if (this.state.url) {
|
if (this.state.url) {
|
||||||
|
this.setThumbnail();
|
||||||
this.fetchIframely();
|
this.fetchIframely();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,9 +108,11 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
if (nextProps.post.url !== this.state.url) {
|
if (nextProps.post.url !== this.state.url) {
|
||||||
this.state.url = nextProps.post.url;
|
this.state.url = nextProps.post.url;
|
||||||
if (this.state.url) {
|
if (this.state.url) {
|
||||||
|
this.setThumbnail();
|
||||||
this.fetchIframely();
|
this.fetchIframely();
|
||||||
} else {
|
} else {
|
||||||
this.state.iframely = null;
|
this.state.iframely = null;
|
||||||
|
this.state.thumbnail = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,6 +137,18 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
imgThumbnail() {
|
||||||
|
let post = this.props.post;
|
||||||
|
return (
|
||||||
|
<object
|
||||||
|
className={`img-fluid thumbnail rounded ${(post.nsfw ||
|
||||||
|
post.community_nsfw) &&
|
||||||
|
'img-blur'}`}
|
||||||
|
data={imageThumbnailer(this.state.thumbnail)}
|
||||||
|
></object>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
listing() {
|
listing() {
|
||||||
let post = this.props.post;
|
let post = this.props.post;
|
||||||
return (
|
return (
|
||||||
|
@ -161,37 +178,32 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{this.hasImage() && !this.state.imageExpanded && (
|
{this.state.thumbnail && !this.state.imageExpanded && (
|
||||||
<div class="mx-2 mt-1 float-left position-relative">
|
<div class="mx-2 mt-1 float-left position-relative">
|
||||||
<a
|
{isImage(this.state.url) ? (
|
||||||
className="text-body"
|
<span
|
||||||
href={this.state.url}
|
class="text-body pointer"
|
||||||
target="_blank"
|
title={i18n.t('expand_here')}
|
||||||
title={this.state.url}
|
onClick={linkEvent(this, this.handleImageExpandClick)}
|
||||||
>
|
|
||||||
<object
|
|
||||||
className={`img-fluid thumbnail rounded ${(post.nsfw ||
|
|
||||||
post.community_nsfw) &&
|
|
||||||
'img-blur'}`}
|
|
||||||
data={imageThumbnailer(this.getImage())}
|
|
||||||
>
|
>
|
||||||
<svg class="icon rounded placeholder">
|
{this.imgThumbnail()}
|
||||||
|
<svg class="icon rounded link-overlay hover-link">
|
||||||
|
<use xlinkHref="#icon-image"></use>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<a
|
||||||
|
className="text-body"
|
||||||
|
href={this.state.url}
|
||||||
|
target="_blank"
|
||||||
|
title={this.state.url}
|
||||||
|
>
|
||||||
|
{this.imgThumbnail()}
|
||||||
|
<svg class="icon rounded link-overlay hover-link">
|
||||||
<use xlinkHref="#icon-external-link"></use>
|
<use xlinkHref="#icon-external-link"></use>
|
||||||
</svg>
|
</svg>
|
||||||
</object>
|
</a>
|
||||||
<svg class="icon rounded link-overlay hover-link">
|
)}
|
||||||
<use xlinkHref="#icon-external-link"></use>
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
<span
|
|
||||||
title={i18n.t('expand_here')}
|
|
||||||
class="pointer"
|
|
||||||
onClick={linkEvent(this, this.handleImageExpandClick)}
|
|
||||||
>
|
|
||||||
<svg class="icon img-expand-overlay">
|
|
||||||
<use xlinkHref="#icon-image"></use>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{this.state.url && isVideo(this.state.url) && (
|
{this.state.url && isVideo(this.state.url) && (
|
||||||
|
@ -247,7 +259,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
</a>
|
</a>
|
||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
{this.hasImage() && (
|
{this.state.thumbnail && (
|
||||||
<>
|
<>
|
||||||
{!this.state.imageExpanded ? (
|
{!this.state.imageExpanded ? (
|
||||||
<span
|
<span
|
||||||
|
@ -272,7 +284,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
>
|
>
|
||||||
<object
|
<object
|
||||||
class="img-fluid img-expanded"
|
class="img-fluid img-expanded"
|
||||||
data={this.getImage()}
|
data={this.state.thumbnail}
|
||||||
>
|
>
|
||||||
<svg class="icon rounded placeholder">
|
<svg class="icon rounded placeholder">
|
||||||
<use xlinkHref="#icon-external-link"></use>
|
<use xlinkHref="#icon-external-link"></use>
|
||||||
|
@ -795,29 +807,39 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
.then(res => {
|
.then(res => {
|
||||||
this.state.iframely = res;
|
this.state.iframely = res;
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
|
|
||||||
|
// Store and fetch the image in pictshare
|
||||||
|
if (
|
||||||
|
this.state.iframely.thumbnail_url &&
|
||||||
|
isImage(this.state.iframely.thumbnail_url)
|
||||||
|
) {
|
||||||
|
fetch(
|
||||||
|
`/pictshare/api/geturl.php?url=${this.state.iframely.thumbnail_url}`
|
||||||
|
)
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(res => {
|
||||||
|
let url = `${window.location.origin}/pictshare/${res.url}`;
|
||||||
|
if (res.filetype == 'mp4') {
|
||||||
|
url += '/raw';
|
||||||
|
}
|
||||||
|
this.state.thumbnail = url;
|
||||||
|
this.setState(this.state);
|
||||||
|
});
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error(`Iframely service not set up properly. ${error}`);
|
console.error(`Iframely service not set up properly. ${error}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
hasImage(): boolean {
|
setThumbnail() {
|
||||||
return (
|
|
||||||
(this.state.url && isImage(this.state.url)) ||
|
|
||||||
(this.state.iframely && this.state.iframely.thumbnail_url !== undefined)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getImage(): string {
|
|
||||||
let simpleImg = isImage(this.state.url);
|
let simpleImg = isImage(this.state.url);
|
||||||
if (simpleImg) {
|
if (simpleImg) {
|
||||||
return this.state.url;
|
this.state.thumbnail = this.state.url;
|
||||||
} else if (this.state.iframely) {
|
} else {
|
||||||
let iframelyThumbnail = this.state.iframely.thumbnail_url;
|
this.state.thumbnail = null;
|
||||||
if (iframelyThumbnail) {
|
|
||||||
return iframelyThumbnail;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
this.setState(this.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePostLike(i: PostListing) {
|
handlePostLike(i: PostListing) {
|
||||||
|
|
10
ui/src/utils.ts
vendored
10
ui/src/utils.ts
vendored
|
@ -220,9 +220,9 @@ export function routeSearchTypeToEnum(type: string): SearchType {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getPageTitle(url: string) {
|
export async function getPageTitle(url: string) {
|
||||||
let res = await fetch(`https://textance.herokuapp.com/title/${url}`);
|
let res = await fetch(`/iframely/oembed?url=${url}`).then(res => res.json());
|
||||||
let data = await res.text();
|
let title = await res.title;
|
||||||
return data;
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function debounce(
|
export function debounce(
|
||||||
|
@ -386,7 +386,7 @@ export function objectFlip(obj: any) {
|
||||||
export function pictshareAvatarThumbnail(src: string): string {
|
export function pictshareAvatarThumbnail(src: string): string {
|
||||||
// sample url: http://localhost:8535/pictshare/gs7xuu.jpg
|
// sample url: http://localhost:8535/pictshare/gs7xuu.jpg
|
||||||
let split = src.split('pictshare');
|
let split = src.split('pictshare');
|
||||||
let out = `${split[0]}pictshare/96x96${split[1]}`;
|
let out = `${split[0]}pictshare/96${split[1]}`;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,7 +401,7 @@ export function showAvatars(): boolean {
|
||||||
export function imageThumbnailer(url: string): string {
|
export function imageThumbnailer(url: string): string {
|
||||||
let split = url.split('pictshare');
|
let split = url.split('pictshare');
|
||||||
if (split.length > 1) {
|
if (split.length > 1) {
|
||||||
let out = `${split[0]}pictshare/192x192${split[1]}`;
|
let out = `${split[0]}pictshare/192${split[1]}`;
|
||||||
return out;
|
return out;
|
||||||
} else {
|
} else {
|
||||||
return url;
|
return url;
|
||||||
|
|
Loading…
Reference in a new issue