Making front end work w/ pictrs v2. Fixes #57

This commit is contained in:
Dessalines 2020-10-14 14:36:37 -05:00
parent 7cb650dbd3
commit 40e1aca891
8 changed files with 95 additions and 92 deletions

View file

@ -297,6 +297,10 @@ br.big {
margin-top: -60px;
}
.img-icon {
width: 2rem; height: 2rem;
}
.tribute-container ul {
margin: 0;
margin-top: 2px;

View file

@ -1,4 +1,5 @@
import { Component } from 'inferno';
import { PictrsImage } from './pictrs-image';
interface BannerIconHeaderProps {
banner?: string;
@ -13,15 +14,12 @@ export class BannerIconHeader extends Component<BannerIconHeaderProps, any> {
render() {
return (
<div class="position-relative mb-2">
{this.props.banner && (
<img src={this.props.banner} class="banner img-fluid" />
)}
{this.props.banner && <PictrsImage src={this.props.banner} />}
{this.props.icon && (
<img
<PictrsImage
src={this.props.icon}
className={`ml-2 mb-0 ${
this.props.banner ? 'avatar-pushup' : ''
} rounded-circle avatar-overlay`}
iconOverlay
pushup={!!this.props.banner}
/>
)}
</div>

View file

@ -1,7 +1,8 @@
import { Component } from 'inferno';
import { Link } from 'inferno-router';
import { Community } from 'lemmy-js-client';
import { hostname, pictrsAvatarThumbnail, showAvatars } from '../utils';
import { hostname, showAvatars } from '../utils';
import { PictrsImage } from './pictrs-image';
interface CommunityOther {
name: string;
@ -47,11 +48,7 @@ export class CommunityLink extends Component<CommunityLinkProps, any> {
to={link}
>
{!this.props.hideAvatar && community.icon && showAvatars() && (
<img
style="width: 2rem; height: 2rem;"
src={pictrsAvatarThumbnail(community.icon)}
class="rounded-circle mr-2"
/>
<PictrsImage src={community.icon} icon />
)}
<span>{displayName}</span>
</Link>

View file

@ -20,7 +20,6 @@ import {
} from 'lemmy-js-client';
import {
wsJsonToRes,
pictrsAvatarThumbnail,
showAvatars,
fetchLimit,
toast,
@ -32,6 +31,7 @@ import {
wsSubscribe,
} from '../utils';
import { i18n } from '../i18next';
import { PictrsImage } from './pictrs-image';
interface NavbarProps {
site: GetSiteResponse;
@ -190,12 +190,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
to="/"
>
{this.props.site.site.icon && showAvatars() && (
<img
src={pictrsAvatarThumbnail(this.props.site.site.icon)}
height="32"
width="32"
class="rounded-circle mr-2"
/>
<PictrsImage src={this.props.site.site.icon} icon />
)}
{this.props.site.site.name}
</Link>
@ -345,12 +340,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
>
<span>
{user.avatar && showAvatars() && (
<img
src={pictrsAvatarThumbnail(user.avatar)}
height="32"
width="32"
class="rounded-circle mr-2"
/>
<PictrsImage src={user.avatar} icon />
)}
{user.preferred_username
? user.preferred_username

View file

@ -0,0 +1,66 @@
import { Component } from 'inferno';
const iconThumbnailSize = 96;
const thumbnailSize = 256;
interface PictrsImageProps {
src: string;
icon?: boolean;
thumbnail?: boolean;
nsfw?: boolean;
iconOverlay?: boolean;
pushup?: boolean;
}
export class PictrsImage extends Component<PictrsImageProps, any> {
constructor(props: any, context: any) {
super(props, context);
}
render() {
return (
<picture>
<source srcSet={this.src('webp')} type="image/webp" />
<source srcSet={this.src('jpg')} type="image/jpeg" />
<img
src={this.src('jpg')}
className={`img-fluid
${this.props.thumbnail ? 'thumbnail rounded ' : 'img-expanded '}
${this.props.thumbnail && this.props.nsfw && 'img-blur '}
${this.props.icon && 'rounded-circle img-icon mr-2 '}
${this.props.iconOverlay && 'ml-2 mb-0 rounded-circle avatar-overlay '}
${this.props.pushup && 'avatar-pushup '}
`}
/>
</picture>
);
}
src(format: string): string {
// sample url:
// http://localhost:8535/pictrs/image/file.png?thumbnail=256&format=jpg
let split = this.props.src.split('/pictrs/image/');
// If theres not multiple, then its not a pictrs image
if (split.length == 1) {
return this.props.src;
}
let host = split[0];
let path = split[1];
let params = { format };
if (this.props.thumbnail) {
params['thumbnail'] = thumbnailSize;
} else if (this.props.icon) {
params['thumbnail'] = iconThumbnailSize;
}
let paramsStr = `?${new URLSearchParams(params).toString()}`;
let out = `${host}/pictrs/image/${path}${paramsStr}`;
return out;
}
}

View file

@ -24,6 +24,7 @@ import { PostForm } from './post-form';
import { IFramelyCard } from './iframely-card';
import { UserListing } from './user-listing';
import { CommunityLink } from './community-link';
import { PictrsImage } from './pictrs-image';
import {
md,
mdToHtml,
@ -32,7 +33,6 @@ import {
isImage,
isVideo,
getUnixTime,
pictrsImage,
setupTippy,
hostname,
previewLines,
@ -164,27 +164,26 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
imgThumb(src: string) {
let post = this.props.post;
return (
<img
className={`img-fluid thumbnail rounded ${
post.nsfw || post.community_nsfw ? 'img-blur' : ''
}`}
<PictrsImage
src={src}
thumbnail
nsfw={post.nsfw || post.community_nsfw}
/>
);
}
getImage(thumbnail: boolean = false) {
getImageSrc(): string {
let post = this.props.post;
if (isImage(post.url)) {
if (post.url.includes('pictrs')) {
return pictrsImage(post.url, thumbnail);
return post.url;
} else if (post.thumbnail_url) {
return pictrsImage(post.thumbnail_url, thumbnail);
return post.thumbnail_url;
} else {
return post.url;
}
} else if (post.thumbnail_url) {
return pictrsImage(post.thumbnail_url, thumbnail);
return post.thumbnail_url;
} else {
return null;
}
@ -200,7 +199,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
data-tippy-content={i18n.t('expand_here')}
onClick={linkEvent(this, this.handleImageExpandClick)}
>
{this.imgThumb(this.getImage(true))}
{this.imgThumb(this.getImageSrc())}
<svg class="icon mini-overlay">
<use xlinkHref="#icon-image"></use>
</svg>
@ -215,7 +214,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
rel="noopener"
title={post.url}
>
{this.imgThumb(this.getImage(true))}
{this.imgThumb(this.getImageSrc())}
<svg class="icon mini-overlay">
<use xlinkHref="#icon-external-link"></use>
</svg>
@ -442,7 +441,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
class="pointer"
onClick={linkEvent(this, this.handleImageExpandClick)}
>
<img class="img-fluid img-expanded" src={this.getImage()} />
<PictrsImage src={this.getImageSrc()} />
</span>
</div>
</span>

View file

@ -1,13 +1,9 @@
import { Component } from 'inferno';
import { Link } from 'inferno-router';
import { UserView } from 'lemmy-js-client';
import {
pictrsAvatarThumbnail,
showAvatars,
hostname,
isCakeDay,
} from '../utils';
import { showAvatars, hostname, isCakeDay } from '../utils';
import { CakeDay } from './cake-day';
import { PictrsImage } from './pictrs-image';
export interface UserOther {
name: string;
@ -59,11 +55,7 @@ export class UserListing extends Component<UserListingProps, any> {
to={link}
>
{!this.props.hideAvatar && user.avatar && showAvatars() && (
<img
style="width: 2rem; height: 2rem;"
src={pictrsAvatarThumbnail(user.avatar)}
class="rounded-circle mr-2"
/>
<PictrsImage src={user.avatar} icon />
)}
<span>{displayName}</span>
</Link>

View file

@ -491,15 +491,6 @@ export function objectFlip(obj: any) {
return ret;
}
export function pictrsAvatarThumbnail(src: string): string {
// sample url: http://localhost:8535/pictrs/image/thumbnail256/gs7xuu.jpg
let split = src.split('/pictrs/image');
let out = `${split[0]}/pictrs/image/${
canUseWebP() ? 'webp/' : ''
}thumbnail96${split[1]}`;
return out;
}
export function showAvatars(): boolean {
return (
(UserService.Instance.user && UserService.Instance.user.show_avatars) ||
@ -520,23 +511,6 @@ export function isCakeDay(published: string): boolean {
);
}
// Converts to image thumbnail
export function pictrsImage(hash: string, thumbnail: boolean = false): string {
let root = `/pictrs/image`;
// Necessary for other servers / domains
if (hash.includes('pictrs')) {
let split = hash.split('/pictrs/image/');
root = `${split[0]}/pictrs/image`;
hash = split[1];
}
let out = `${root}/${canUseWebP() ? 'webp/' : ''}${
thumbnail ? 'thumbnail256/' : ''
}${hash}`;
return out;
}
export function isCommentType(
item: Comment | PrivateMessage | Post
): item is Comment {
@ -1090,23 +1064,6 @@ export function hostname(url: string): string {
return cUrl.port ? `${cUrl.hostname}:${cUrl.port}` : `${cUrl.hostname}`;
}
function canUseWebP() {
// TODO pictshare might have a webp conversion bug, try disabling this
return false;
// var elem = document.createElement('canvas');
// if (!!(elem.getContext && elem.getContext('2d'))) {
// var testString = !(window.mozInnerScreenX == null) ? 'png' : 'webp';
// // was able or not to get WebP representation
// return (
// elem.toDataURL('image/webp').startsWith('data:image/' + testString)
// );
// }
// // very old browser like IE 8, canvas not supported
// return false;
}
export function validTitle(title?: string): boolean {
// Initial title is null, minimum length is taken care of by textarea's minLength={3}
if (title === null || title.length < 3) return true;