diff options
author | Felix Ableitner <me@nutomic.com> | 2020-06-09 14:01:26 +0200 |
---|---|---|
committer | Felix Ableitner <me@nutomic.com> | 2020-06-09 14:01:26 +0200 |
commit | 0f1a8ec928a36d73490a41a778244578f39dd626 (patch) | |
tree | e55ec80acbb258197ce899cefe6e1b24e09ad2fb /ui/src | |
parent | 5c6601cb2a819d20b0f0d17f3575aff006a47fd2 (diff) | |
parent | a13e9fe3959e07f901ba0647dfd7f749865a900d (diff) |
Merge branch 'master' into federation
Diffstat (limited to 'ui/src')
-rw-r--r-- | ui/src/components/comment-node.tsx | 22 | ||||
-rw-r--r-- | ui/src/components/login.tsx | 2 | ||||
-rw-r--r-- | ui/src/components/main.tsx | 2 | ||||
-rw-r--r-- | ui/src/components/post-form.tsx | 10 | ||||
-rw-r--r-- | ui/src/components/post-listing.tsx | 2 | ||||
-rw-r--r-- | ui/src/components/post.tsx | 12 | ||||
-rw-r--r-- | ui/src/components/private-message-form.tsx | 55 | ||||
-rw-r--r-- | ui/src/components/sidebar.tsx | 2 | ||||
-rw-r--r-- | ui/src/components/sponsors.tsx | 29 | ||||
-rw-r--r-- | ui/src/components/user.tsx | 4 | ||||
-rw-r--r-- | ui/src/i18next.ts | 18 | ||||
-rw-r--r-- | ui/src/utils.ts | 72 | ||||
-rw-r--r-- | ui/src/version.ts | 2 |
13 files changed, 169 insertions, 63 deletions
diff --git a/ui/src/components/comment-node.tsx b/ui/src/components/comment-node.tsx index 9bc9c7bb..ca828a45 100644 --- a/ui/src/components/comment-node.tsx +++ b/ui/src/components/comment-node.tsx @@ -709,19 +709,15 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> { get linkBtn() { let node = this.props.node; return ( - <button className="btn btn-link btn-animate"> - <Link - class="text-muted" - to={`/post/${node.comment.post_id}/comment/${node.comment.id}`} - title={ - this.props.showContext ? i18n.t('show_context') : i18n.t('link') - } - > - <svg class="icon icon-inline"> - <use xlinkHref="#icon-link"></use> - </svg> - </Link> - </button> + <Link + class="btn btn-link btn-animate text-muted" + to={`/post/${node.comment.post_id}/comment/${node.comment.id}`} + title={this.props.showContext ? i18n.t('show_context') : i18n.t('link')} + > + <svg class="icon icon-inline"> + <use xlinkHref="#icon-link"></use> + </svg> + </Link> ); } diff --git a/ui/src/components/login.tsx b/ui/src/components/login.tsx index 581c4995..84014f68 100644 --- a/ui/src/components/login.tsx +++ b/ui/src/components/login.tsx @@ -187,6 +187,7 @@ export class Login extends Component<any, State> { type="password" id="register-password" value={this.state.registerForm.password} + autoComplete="new-password" onInput={linkEvent(this, this.handleRegisterPasswordChange)} class="form-control" required @@ -206,6 +207,7 @@ export class Login extends Component<any, State> { type="password" id="register-verify-password" value={this.state.registerForm.password_verify} + autoComplete="new-password" onInput={linkEvent(this, this.handleRegisterPasswordVerifyChange)} class="form-control" required diff --git a/ui/src/components/main.tsx b/ui/src/components/main.tsx index 9e0c3a59..c168feb0 100644 --- a/ui/src/components/main.tsx +++ b/ui/src/components/main.tsx @@ -288,9 +288,11 @@ export class Main extends Component<any, MainState> { </ul> )} <ul class="my-2 list-inline"> + {/* <li className="list-inline-item badge badge-secondary"> {i18n.t('number_online', { count: this.state.siteRes.online })} </li> + */} <li className="list-inline-item badge badge-secondary"> {i18n.t('number_of_users', { count: this.state.siteRes.site.number_of_users, diff --git a/ui/src/components/post-form.tsx b/ui/src/components/post-form.tsx index f04910be..22224c34 100644 --- a/ui/src/components/post-form.tsx +++ b/ui/src/components/post-form.tsx @@ -331,6 +331,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> { value={this.state.postForm.community_id} onInput={linkEvent(this, this.handlePostCommunityChange)} > + <option>{i18n.t('select_a_community')}</option> {this.state.communities.map(community => ( <option value={community.id}> {community.local @@ -362,7 +363,11 @@ export class PostForm extends Component<PostFormProps, PostFormState> { )} <div class="form-group row"> <div class="col-sm-10"> - <button type="submit" class="btn btn-secondary mr-2"> + <button + disabled={!this.state.postForm.community_id} + type="submit" + class="btn btn-secondary mr-2" + > {this.state.loading ? ( <svg class="icon icon-spinner spin"> <use xlinkHref="#icon-spinner"></use> @@ -568,7 +573,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> { ).id; this.state.postForm.community_id = foundCommunityId; } else { - this.state.postForm.community_id = data.communities[0].id; + // By default, the null valued 'Select a Community' } this.setState(this.state); @@ -578,6 +583,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> { let selector = new Selectr(selectId, { nativeDropdown: false }); selector.on('selectr.select', option => { this.state.postForm.community_id = Number(option.value); + this.setState(this.state); }); } } else if (res.op == UserOperation.CreatePost) { diff --git a/ui/src/components/post-listing.tsx b/ui/src/components/post-listing.tsx index 6ebf5400..def42e3c 100644 --- a/ui/src/components/post-listing.tsx +++ b/ui/src/components/post-listing.tsx @@ -165,6 +165,8 @@ export class PostListing extends Component<PostListingProps, PostListingState> { if (isImage(post.url)) { if (post.url.includes('pictshare')) { return pictshareImage(post.url, thumbnail); + } else if (post.thumbnail_url) { + return pictshareImage(post.thumbnail_url, thumbnail); } else { return post.url; } diff --git a/ui/src/components/post.tsx b/ui/src/components/post.tsx index cf9e7486..297d0465 100644 --- a/ui/src/components/post.tsx +++ b/ui/src/components/post.tsx @@ -40,7 +40,6 @@ import { setupTippy, } from '../utils'; import { PostListing } from './post-listing'; -import { PostListings } from './post-listings'; import { Sidebar } from './sidebar'; import { CommentForm } from './comment-form'; import { CommentNodes } from './comment-nodes'; @@ -183,14 +182,6 @@ export class Post extends Component<any, PostState> { moderators={this.state.moderators} admins={this.state.admins} /> - {this.state.crossPosts.length > 0 && ( - <> - <div class="my-1 text-muted small font-weight-bold"> - {i18n.t('cross_posts')} - </div> - <PostListings showCommunity posts={this.state.crossPosts} /> - </> - )} <div className="mb-2" /> <CommentForm postId={this.state.post.id} @@ -466,6 +457,9 @@ export class Post extends Component<any, PostState> { this.state.crossPosts = data.posts.filter( p => p.id != Number(this.props.match.params.id) ); + if (this.state.crossPosts.length) { + this.state.post.duplicates = this.state.crossPosts; + } this.setState(this.state); } else if (res.op == UserOperation.TransferSite) { let data = res.data as GetSiteResponse; diff --git a/ui/src/components/private-message-form.tsx b/ui/src/components/private-message-form.tsx index 586b867e..64e22d61 100644 --- a/ui/src/components/private-message-form.tsx +++ b/ui/src/components/private-message-form.tsx @@ -163,38 +163,12 @@ export class PrivateMessageForm extends Component< )} /> )} - - <ul class="float-right list-inline mb-1 text-muted font-weight-bold"> - <li class="list-inline-item"> - <span - onClick={linkEvent(this, this.handleShowDisclaimer)} - class="pointer" - data-tippy-content={i18n.t('disclaimer')} - > - <svg class={`icon icon-inline`}> - <use xlinkHref="#icon-alert-triangle"></use> - </svg> - </span> - </li> - <li class="list-inline-item"> - <a - href={markdownHelpUrl} - target="_blank" - class="text-muted" - title={i18n.t('formatting_help')} - > - <svg class="icon icon-inline"> - <use xlinkHref="#icon-help-circle"></use> - </svg> - </a> - </li> - </ul> </div> </div> {this.state.showDisclaimer && ( <div class="form-group row"> - <div class="col-sm-10"> + <div class="offset-sm-2 col-sm-10"> <div class="alert alert-danger" role="alert"> <T i18nKey="private_message_disclaimer"> # @@ -211,7 +185,7 @@ export class PrivateMessageForm extends Component< </div> )} <div class="form-group row"> - <div class="col-sm-10"> + <div class="offset-sm-2 col-sm-10"> <button type="submit" class="btn btn-secondary mr-2"> {this.state.loading ? ( <svg class="icon icon-spinner spin"> @@ -242,6 +216,31 @@ export class PrivateMessageForm extends Component< {i18n.t('cancel')} </button> )} + <ul class="d-inline-block float-right list-inline mb-1 text-muted font-weight-bold"> + <li class="list-inline-item"> + <span + onClick={linkEvent(this, this.handleShowDisclaimer)} + class="pointer" + data-tippy-content={i18n.t('disclaimer')} + > + <svg class={`icon icon-inline`}> + <use xlinkHref="#icon-alert-triangle"></use> + </svg> + </span> + </li> + <li class="list-inline-item"> + <a + href={markdownHelpUrl} + target="_blank" + class="text-muted" + title={i18n.t('formatting_help')} + > + <svg class="icon icon-inline"> + <use xlinkHref="#icon-help-circle"></use> + </svg> + </a> + </li> + </ul> </div> </div> </form> diff --git a/ui/src/components/sidebar.tsx b/ui/src/components/sidebar.tsx index dc2376d7..17ac64b9 100644 --- a/ui/src/components/sidebar.tsx +++ b/ui/src/components/sidebar.tsx @@ -173,9 +173,11 @@ export class Sidebar extends Component<SidebarProps, SidebarState> { </form> )} <ul class="my-1 list-inline"> + {/* <li className="list-inline-item badge badge-secondary"> {i18n.t('number_online', { count: this.props.online })} </li> + */} <li className="list-inline-item badge badge-secondary"> {i18n.t('number_of_subscribers', { count: community.number_of_subscribers, diff --git a/ui/src/components/sponsors.tsx b/ui/src/components/sponsors.tsx index cdd7bdad..35ec7635 100644 --- a/ui/src/components/sponsors.tsx +++ b/ui/src/components/sponsors.tsx @@ -4,14 +4,25 @@ import { i18n } from '../i18next'; import { T } from 'inferno-i18next'; import { repoUrl } from '../utils'; +interface SilverUser { + name: string; + link: string; +} + let general = [ - 'alexx henry', - 'Nathan J. Goode', + 'Ernest Wiśniewski', + 'HN', + 'Forrest Weghorst', 'Andre Vallestero', 'NotTooHighToHack', ]; let highlighted = ['Oskenso Kashi', 'Alex Benishek']; -// let silver = []; +let silver: Array<SilverUser> = [ + { + name: 'Redjoker', + link: 'https://iww.org', + }, +]; // let gold = []; // let latinum = []; @@ -70,6 +81,18 @@ export class Sponsors extends Component<any, any> { return ( <div class="container"> <h5>{i18n.t('sponsors')}</h5> + <p>{i18n.t('silver_sponsors')}</p> + <div class="row card-columns"> + {silver.map(s => ( + <div class="card col-12 col-md-2"> + <div> + <a href={s.link} target="_blank"> + 💎 {s.name} + </a> + </div> + </div> + ))} + </div> <p>{i18n.t('general_sponsors')}</p> <div class="row card-columns"> {highlighted.map(s => ( diff --git a/ui/src/components/user.tsx b/ui/src/components/user.tsx index 51b9582f..78807153 100644 --- a/ui/src/components/user.tsx +++ b/ui/src/components/user.tsx @@ -614,6 +614,7 @@ export class User extends Component<any, UserState> { id="user-password" class="form-control" value={this.state.userSettingsForm.new_password} + autoComplete="new-password" onInput={linkEvent( this, this.handleUserSettingsNewPasswordChange @@ -634,6 +635,7 @@ export class User extends Component<any, UserState> { id="user-verify-password" class="form-control" value={this.state.userSettingsForm.new_password_verify} + autoComplete="new-password" onInput={linkEvent( this, this.handleUserSettingsNewPasswordVerifyChange @@ -654,6 +656,7 @@ export class User extends Component<any, UserState> { id="user-old-password" class="form-control" value={this.state.userSettingsForm.old_password} + autoComplete="new-password" onInput={linkEvent( this, this.handleUserSettingsOldPasswordChange @@ -750,6 +753,7 @@ export class User extends Component<any, UserState> { <input type="password" value={this.state.deleteAccountForm.password} + autoComplete="new-password" onInput={linkEvent( this, this.handleDeleteAccountPasswordChange diff --git a/ui/src/i18next.ts b/ui/src/i18next.ts index 85d06f91..5fa8f4e8 100644 --- a/ui/src/i18next.ts +++ b/ui/src/i18next.ts @@ -1,6 +1,8 @@ import i18next from 'i18next'; import { getLanguage } from './utils'; import { en } from './translations/en'; +import { el } from './translations/el'; +import { eu } from './translations/eu'; import { eo } from './translations/eo'; import { es } from './translations/es'; import { de } from './translations/de'; @@ -13,14 +15,25 @@ import { it } from './translations/it'; import { fi } from './translations/fi'; import { ca } from './translations/ca'; import { fa } from './translations/fa'; +import { hi } from './translations/hi'; +import { pl } from './translations/pl'; import { pt_BR } from './translations/pt_BR'; import { ja } from './translations/ja'; +import { ka } from './translations/ka'; +import { gl } from './translations/gl'; +import { tr } from './translations/tr'; +import { hu } from './translations/hu'; +import { uk } from './translations/uk'; // https://github.com/nimbusec-oss/inferno-i18next/blob/master/tests/T.test.js#L66 const resources = { en, + el, + eu, eo, es, + ka, + hi, de, zh, fr, @@ -31,8 +44,13 @@ const resources = { fi, ca, fa, + pl, pt_BR, ja, + gl, + tr, + hu, + uk, }; function format(value: any, format: any, lng: any): any { diff --git a/ui/src/utils.ts b/ui/src/utils.ts index 54322c8b..5ce84b39 100644 --- a/ui/src/utils.ts +++ b/ui/src/utils.ts @@ -1,4 +1,6 @@ import 'moment/locale/es'; +import 'moment/locale/el'; +import 'moment/locale/eu'; import 'moment/locale/eo'; import 'moment/locale/de'; import 'moment/locale/zh-cn'; @@ -10,9 +12,15 @@ import 'moment/locale/it'; import 'moment/locale/fi'; import 'moment/locale/ca'; import 'moment/locale/fa'; +import 'moment/locale/pl'; import 'moment/locale/pt-br'; import 'moment/locale/ja'; import 'moment/locale/ka'; +import 'moment/locale/hi'; +import 'moment/locale/gl'; +import 'moment/locale/tr'; +import 'moment/locale/hu'; +import 'moment/locale/uk'; import { UserOperation, @@ -58,17 +66,25 @@ export const mentionDropdownFetchLimit = 10; export const languages = [ { code: 'ca', name: 'Català' }, { code: 'en', name: 'English' }, + { code: 'el', name: 'Ελληνικά' }, + { code: 'eu', name: 'Euskara' }, { code: 'eo', name: 'Esperanto' }, { code: 'es', name: 'Español' }, { code: 'de', name: 'Deutsch' }, + { code: 'gl', name: 'Galego' }, + { code: 'hu', name: 'Magyar Nyelv' }, { code: 'ka', name: 'ქართული ენა' }, + { code: 'hi', name: 'मानक हिन्दी' }, { code: 'fa', name: 'فارسی' }, { code: 'ja', name: '日本語' }, + { code: 'pl', name: 'Polski' }, { code: 'pt_BR', name: 'Português Brasileiro' }, { code: 'zh', name: '中文' }, { code: 'fi', name: 'Suomi' }, { code: 'fr', name: 'Français' }, { code: 'sv', name: 'Svenska' }, + { code: 'tr', name: 'Türkçe' }, + { code: 'uk', name: 'українська мова' }, { code: 'ru', name: 'Русский' }, { code: 'nl', name: 'Nederlands' }, { code: 'it', name: 'Italiano' }, @@ -208,7 +224,7 @@ export function isMod(modIds: Array<number>, creator_id: number): boolean { } const imageRegex = new RegExp( - /(http)?s?:?(\/\/[^"']*\.(?:jpg|jpeg|gif|png|svg))/ + /(http)?s?:?(\/\/[^"']*\.(?:jpg|jpeg|gif|png|svg|webp))/ ); const videoRegex = new RegExp(`(http)?s?:?(\/\/[^"']*\.(?:mp4))`); @@ -360,12 +376,28 @@ export function getMomentLanguage(): string { lang = 'ca'; } else if (lang.startsWith('fa')) { lang = 'fa'; + } else if (lang.startsWith('pl')) { + lang = 'pl'; } else if (lang.startsWith('pt')) { lang = 'pt-br'; } else if (lang.startsWith('ja')) { lang = 'ja'; } else if (lang.startsWith('ka')) { lang = 'ka'; + } else if (lang.startsWith('hi')) { + lang = 'hi'; + } else if (lang.startsWith('el')) { + lang = 'el'; + } else if (lang.startsWith('eu')) { + lang = 'eu'; + } else if (lang.startsWith('gl')) { + lang = 'gl'; + } else if (lang.startsWith('tr')) { + lang = 'tr'; + } else if (lang.startsWith('hu')) { + lang = 'hu'; + } else if (lang.startsWith('uk')) { + lang = 'uk'; } else { lang = 'en'; } @@ -382,17 +414,22 @@ export function setTheme(theme: string = 'darkly') { } // Load the theme dynamically - if (!document.getElementById(theme)) { + let cssLoc = `/static/assets/css/themes/${theme}.min.css`; + loadCss(theme, cssLoc); + document.getElementById(theme).removeAttribute('disabled'); +} + +export function loadCss(id: string, loc: string) { + if (!document.getElementById(id)) { var head = document.getElementsByTagName('head')[0]; var link = document.createElement('link'); - link.id = theme; + link.id = id; link.rel = 'stylesheet'; link.type = 'text/css'; - link.href = `/static/assets/css/themes/${theme}.min.css`; + link.href = loc; link.media = 'all'; head.appendChild(link); } - document.getElementById(theme).removeAttribute('disabled'); } export function objectFlip(obj: any) { @@ -406,7 +443,7 @@ export function objectFlip(obj: any) { export function pictshareAvatarThumbnail(src: string): string { // sample url: http://localhost:8535/pictshare/gs7xuu.jpg let split = src.split('pictshare'); - let out = `${split[0]}pictshare/96${split[1]}`; + let out = `${split[0]}pictshare/${canUseWebP() ? 'webp/' : ''}96${split[1]}`; return out; } @@ -431,7 +468,9 @@ export function pictshareImage( hash = split[1]; } - let out = `${root}/${thumbnail ? '192/' : ''}${hash}`; + let out = `${root}/${canUseWebP() ? 'webp/' : ''}${ + thumbnail ? '192/' : '' + }${hash}`; return out; } @@ -462,6 +501,7 @@ export function messageToastify( text: `${body}<br />${creator}`, avatar: avatar, backgroundColor: backgroundColor, + className: 'text-body', close: true, gravity: 'top', position: 'right', @@ -864,3 +904,21 @@ export function hostname(url: string): string { ? `${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; +} diff --git a/ui/src/version.ts b/ui/src/version.ts index eb0ecff3..9abc8bce 100644 --- a/ui/src/version.ts +++ b/ui/src/version.ts @@ -1 +1 @@ -export const version: string = 'v0.6.51'; +export const version: string = 'v0.6.71'; |