mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-23 12:51:18 +00:00
Add image loading indicator.
This commit is contained in:
parent
4672e9b783
commit
3444c70313
4 changed files with 46 additions and 9 deletions
22
ui/src/components/comment-form.tsx
vendored
22
ui/src/components/comment-form.tsx
vendored
|
@ -1,7 +1,7 @@
|
||||||
import { Component, linkEvent } from 'inferno';
|
import { Component, linkEvent } from 'inferno';
|
||||||
import { CommentNode as CommentNodeI, CommentForm as CommentFormI, SearchForm, SearchType, SortType, UserOperation, SearchResponse } from '../interfaces';
|
import { CommentNode as CommentNodeI, CommentForm as CommentFormI, SearchForm, SearchType, SortType, UserOperation, SearchResponse } from '../interfaces';
|
||||||
import { Subscription } from "rxjs";
|
import { Subscription } from "rxjs";
|
||||||
import { capitalizeFirstLetter, mentionDropdownFetchLimit, msgOp, mdToHtml, randomStr, imageUploadUrl, markdownHelpUrl } from '../utils';
|
import { capitalizeFirstLetter, mentionDropdownFetchLimit, msgOp, mdToHtml, randomStr, markdownHelpUrl } from '../utils';
|
||||||
import { WebSocketService, UserService } from '../services';
|
import { WebSocketService, UserService } from '../services';
|
||||||
import * as autosize from 'autosize';
|
import * as autosize from 'autosize';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
|
@ -21,6 +21,7 @@ interface CommentFormState {
|
||||||
commentForm: CommentFormI;
|
commentForm: CommentFormI;
|
||||||
buttonTitle: string;
|
buttonTitle: string;
|
||||||
previewMode: boolean;
|
previewMode: boolean;
|
||||||
|
imageLoading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
||||||
|
@ -38,6 +39,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
||||||
},
|
},
|
||||||
buttonTitle: !this.props.node ? capitalizeFirstLetter(i18n.t('post')) : this.props.edit ? capitalizeFirstLetter(i18n.t('edit')) : capitalizeFirstLetter(i18n.t('reply')),
|
buttonTitle: !this.props.node ? capitalizeFirstLetter(i18n.t('post')) : this.props.edit ? capitalizeFirstLetter(i18n.t('edit')) : capitalizeFirstLetter(i18n.t('reply')),
|
||||||
previewMode: false,
|
previewMode: false,
|
||||||
|
imageLoading: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
|
@ -134,12 +136,15 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
||||||
{this.state.commentForm.content &&
|
{this.state.commentForm.content &&
|
||||||
<button className={`btn btn-sm mr-2 btn-secondary ${this.state.previewMode && 'active'}`} onClick={linkEvent(this, this.handlePreviewToggle)}><T i18nKey="preview">#</T></button>
|
<button className={`btn btn-sm mr-2 btn-secondary ${this.state.previewMode && 'active'}`} onClick={linkEvent(this, this.handlePreviewToggle)}><T i18nKey="preview">#</T></button>
|
||||||
}
|
}
|
||||||
{this.props.node && <button type="button" class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.handleReplyCancel)}><T i18nKey="cancel">#</T></button>}
|
{this.props.node && <button type="button" class="btn btn-sm btn-secondary mr-2" onClick={linkEvent(this, this.handleReplyCancel)}><T i18nKey="cancel">#</T></button>}
|
||||||
<a href={markdownHelpUrl} target="_blank" class="d-inline-block float-right text-muted small font-weight-bold"><T i18nKey="formatting_help">#</T></a>
|
<a href={markdownHelpUrl} target="_blank" class="d-inline-block float-right text-muted small font-weight-bold"><T i18nKey="formatting_help">#</T></a>
|
||||||
<form class="d-inline-block mr-2 float-right text-muted small font-weight-bold">
|
<form class="d-inline-block mr-2 float-right text-muted small font-weight-bold">
|
||||||
<label htmlFor={`file-upload-${this.id}`} class="pointer"><T i18nKey="upload_image">#</T></label>
|
<label htmlFor={`file-upload-${this.id}`} class="pointer"><T i18nKey="upload_image">#</T></label>
|
||||||
<input id={`file-upload-${this.id}`} type="file" name="file" class="d-none" onChange={linkEvent(this, this.handleImageUpload)} />
|
<input id={`file-upload-${this.id}`} type="file" accept="image/*,video/*" name="file" class="d-none" onChange={linkEvent(this, this.handleImageUpload)} />
|
||||||
</form>
|
</form>
|
||||||
|
{this.state.imageLoading &&
|
||||||
|
<svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -187,6 +192,10 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
||||||
const imageUploadUrl = `/pictshare/api/upload.php`;
|
const imageUploadUrl = `/pictshare/api/upload.php`;
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('file', file);
|
formData.append('file', file);
|
||||||
|
|
||||||
|
i.state.imageLoading = true;
|
||||||
|
i.setState(i.state);
|
||||||
|
|
||||||
fetch(imageUploadUrl, {
|
fetch(imageUploadUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
body: formData,
|
||||||
|
@ -198,9 +207,14 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
||||||
let content = i.state.commentForm.content;
|
let content = i.state.commentForm.content;
|
||||||
content = (content) ? `${content} ${markdown}` : markdown;
|
content = (content) ? `${content} ${markdown}` : markdown;
|
||||||
i.state.commentForm.content = content;
|
i.state.commentForm.content = content;
|
||||||
|
i.state.imageLoading = false;
|
||||||
i.setState(i.state);
|
i.setState(i.state);
|
||||||
})
|
})
|
||||||
.catch((error) => alert(error));
|
.catch((error) => {
|
||||||
|
i.state.imageLoading = false;
|
||||||
|
i.setState(i.state);
|
||||||
|
alert(error);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
userSearch(text: string, cb: any) {
|
userSearch(text: string, cb: any) {
|
||||||
|
|
21
ui/src/components/post-form.tsx
vendored
21
ui/src/components/post-form.tsx
vendored
|
@ -4,7 +4,7 @@ import { Subscription } from "rxjs";
|
||||||
import { retryWhen, delay, take } from 'rxjs/operators';
|
import { retryWhen, delay, take } from 'rxjs/operators';
|
||||||
import { PostForm as PostFormI, PostFormParams, Post, PostResponse, UserOperation, Community, ListCommunitiesResponse, ListCommunitiesForm, SortType, SearchForm, SearchType, SearchResponse } from '../interfaces';
|
import { PostForm as PostFormI, PostFormParams, Post, PostResponse, UserOperation, Community, ListCommunitiesResponse, ListCommunitiesForm, SortType, SearchForm, SearchType, SearchResponse } from '../interfaces';
|
||||||
import { WebSocketService, UserService } from '../services';
|
import { WebSocketService, UserService } from '../services';
|
||||||
import { msgOp, getPageTitle, debounce, validURL, capitalizeFirstLetter, imageUploadUrl, markdownHelpUrl, mdToHtml } from '../utils';
|
import { msgOp, getPageTitle, debounce, validURL, capitalizeFirstLetter, markdownHelpUrl, mdToHtml } from '../utils';
|
||||||
import * as autosize from 'autosize';
|
import * as autosize from 'autosize';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
import { T } from 'inferno-i18next';
|
import { T } from 'inferno-i18next';
|
||||||
|
@ -21,6 +21,7 @@ interface PostFormState {
|
||||||
postForm: PostFormI;
|
postForm: PostFormI;
|
||||||
communities: Array<Community>;
|
communities: Array<Community>;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
|
imageLoading: boolean;
|
||||||
previewMode: boolean;
|
previewMode: boolean;
|
||||||
suggestedTitle: string;
|
suggestedTitle: string;
|
||||||
suggestedPosts: Array<Post>;
|
suggestedPosts: Array<Post>;
|
||||||
|
@ -40,6 +41,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
},
|
},
|
||||||
communities: [],
|
communities: [],
|
||||||
loading: false,
|
loading: false,
|
||||||
|
imageLoading: false,
|
||||||
previewMode: false,
|
previewMode: false,
|
||||||
suggestedTitle: undefined,
|
suggestedTitle: undefined,
|
||||||
suggestedPosts: [],
|
suggestedPosts: [],
|
||||||
|
@ -111,8 +113,11 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
}
|
}
|
||||||
<form>
|
<form>
|
||||||
<label htmlFor="file-upload" class="pointer d-inline-block mr-2 float-right text-muted small font-weight-bold"><T i18nKey="upload_image">#</T></label>
|
<label htmlFor="file-upload" class="pointer d-inline-block mr-2 float-right text-muted small font-weight-bold"><T i18nKey="upload_image">#</T></label>
|
||||||
<input id="file-upload" type="file" name="file" class="d-none" onChange={linkEvent(this, this.handleImageUpload)} />
|
<input id="file-upload" type="file" accept="image/*,video/*" name="file" class="d-none" onChange={linkEvent(this, this.handleImageUpload)} />
|
||||||
</form>
|
</form>
|
||||||
|
{this.state.imageLoading &&
|
||||||
|
<svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg>
|
||||||
|
}
|
||||||
{this.state.crossPosts.length > 0 &&
|
{this.state.crossPosts.length > 0 &&
|
||||||
<>
|
<>
|
||||||
<div class="my-1 text-muted small font-weight-bold"><T i18nKey="cross_posts">#</T></div>
|
<div class="my-1 text-muted small font-weight-bold"><T i18nKey="cross_posts">#</T></div>
|
||||||
|
@ -275,6 +280,10 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
const imageUploadUrl = `/pictshare/api/upload.php`;
|
const imageUploadUrl = `/pictshare/api/upload.php`;
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('file', file);
|
formData.append('file', file);
|
||||||
|
|
||||||
|
i.state.imageLoading = true;
|
||||||
|
i.setState(i.state);
|
||||||
|
|
||||||
fetch(imageUploadUrl, {
|
fetch(imageUploadUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
body: formData,
|
||||||
|
@ -285,11 +294,15 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
if (res.filetype == 'mp4') {
|
if (res.filetype == 'mp4') {
|
||||||
url += '/raw';
|
url += '/raw';
|
||||||
}
|
}
|
||||||
|
|
||||||
i.state.postForm.url = url;
|
i.state.postForm.url = url;
|
||||||
|
i.state.imageLoading = false;
|
||||||
i.setState(i.state);
|
i.setState(i.state);
|
||||||
})
|
})
|
||||||
.catch((error) => alert(error));
|
.catch((error) => {
|
||||||
|
i.state.imageLoading = false;
|
||||||
|
i.setState(i.state);
|
||||||
|
alert(error);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
parseMessage(msg: any) {
|
parseMessage(msg: any) {
|
||||||
|
|
1
ui/src/utils.ts
vendored
1
ui/src/utils.ts
vendored
|
@ -15,7 +15,6 @@ import * as twemoji from 'twemoji';
|
||||||
import * as emojiShortName from 'emoji-short-name';
|
import * as emojiShortName from 'emoji-short-name';
|
||||||
|
|
||||||
export const repoUrl = 'https://github.com/dessalines/lemmy';
|
export const repoUrl = 'https://github.com/dessalines/lemmy';
|
||||||
export const imageUploadUrl = 'https://postimages.org/';
|
|
||||||
export const markdownHelpUrl = 'https://commonmark.org/help/';
|
export const markdownHelpUrl = 'https://commonmark.org/help/';
|
||||||
|
|
||||||
export const fetchLimit: number = 20;
|
export const fetchLimit: number = 20;
|
||||||
|
|
11
ui/tmp
vendored
Normal file
11
ui/tmp
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
lang | done | missing
|
||||||
|
--- | --- | ---
|
||||||
|
de | 86% | cross_posts,cross_post,users,number_of_communities,preview,upload_image,formatting_help,settings,banned,subscribed,expires,recent_comments,nsfw,show_nsfw,crypto,monero,joined,by,to,transfer_community,transfer_site,are_you_sure,yes,no
|
||||||
|
eo | 95% | number_of_communities,preview,upload_image,formatting_help,banned,are_you_sure,yes,no
|
||||||
|
es | 95% | number_of_communities,preview,upload_image,formatting_help,banned,are_you_sure,yes,no
|
||||||
|
fr | 100% |
|
||||||
|
nl | 98% | preview,upload_image,formatting_help,banned
|
||||||
|
ru | 91% | cross_posts,cross_post,number_of_communities,preview,upload_image,formatting_help,banned,recent_comments,monero,by,to,transfer_community,transfer_site,are_you_sure,yes,no
|
||||||
|
sv | 98% | preview,upload_image,formatting_help,banned
|
||||||
|
zh | 89% | cross_posts,cross_post,users,number_of_communities,preview,upload_image,formatting_help,settings,banned,recent_comments,nsfw,show_nsfw,monero,by,to,transfer_community,transfer_site,are_you_sure,yes,no
|
||||||
|
|
Loading…
Reference in a new issue