Browse Source

Switch front end to use lemmy-js-client. Fixes #1090 (#1097)

* Switch front end to use lemmy-js-client. Fixes #1090

* Adding an HTTP client. Cleaning up Websocket client.
fix_ws_context
Dessalines 10 months ago
committed by GitHub
parent
commit
2080534744
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      README.md
  2. 4
      server/src/routes/api.rs
  3. 1
      ui/package.json
  4. 4
      ui/src/api_tests/comment.spec.ts
  5. 489
      ui/src/api_tests/shared.ts
  6. 2
      ui/src/components/admin-settings.tsx
  7. 2
      ui/src/components/comment-form.tsx
  8. 5
      ui/src/components/comment-node.tsx
  9. 4
      ui/src/components/comment-nodes.tsx
  10. 4
      ui/src/components/communities.tsx
  11. 4
      ui/src/components/community-form.tsx
  12. 2
      ui/src/components/community-link.tsx
  13. 28
      ui/src/components/community.tsx
  14. 2
      ui/src/components/create-community.tsx
  15. 2
      ui/src/components/create-post.tsx
  16. 2
      ui/src/components/create-private-message.tsx
  17. 2
      ui/src/components/footer.tsx
  18. 2
      ui/src/components/iframely-card.tsx
  19. 6
      ui/src/components/inbox.tsx
  20. 2
      ui/src/components/instances.tsx
  21. 10
      ui/src/components/listing-type-select.tsx
  22. 2
      ui/src/components/login.tsx
  23. 40
      ui/src/components/main.tsx
  24. 2
      ui/src/components/modlog.tsx
  25. 8
      ui/src/components/navbar.tsx
  26. 2
      ui/src/components/password_change.tsx
  27. 12
      ui/src/components/post-form.tsx
  28. 4
      ui/src/components/post-listing.tsx
  29. 2
      ui/src/components/post-listings.tsx
  30. 9
      ui/src/components/post.tsx
  31. 4
      ui/src/components/private-message-form.tsx
  32. 2
      ui/src/components/private-message.tsx
  33. 24
      ui/src/components/search.tsx
  34. 2
      ui/src/components/setup.tsx
  35. 2
      ui/src/components/sidebar.tsx
  36. 2
      ui/src/components/site-form.tsx
  37. 9
      ui/src/components/sort-select.tsx
  38. 2
      ui/src/components/sponsors.tsx
  39. 8
      ui/src/components/user-details.tsx
  40. 2
      ui/src/components/user-listing.tsx
  41. 52
      ui/src/components/user.tsx
  42. 1052
      ui/src/interfaces.ts
  43. 7
      ui/src/services/UserService.ts
  44. 165
      ui/src/services/WebSocketService.ts
  45. 38
      ui/src/utils.ts
  46. 5
      ui/yarn.lock

1
README.md

@ -112,6 +112,7 @@ Each Lemmy server can set its own moderation policy; appointing site-wide admins
### Libraries
- [lemmy-js-client](https://github.com/LemmyNet/lemmy-js-client)
- [Kotlin API ( under development )](https://github.com/eiknat/lemmy-client)
## Support / Donate

4
server/src/routes/api.rs

@ -94,7 +94,8 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
web::post().to(route_post::<MarkCommentAsRead>),
)
.route("/like", web::post().to(route_post::<CreateCommentLike>))
.route("/save", web::put().to(route_post::<SaveComment>)),
.route("/save", web::put().to(route_post::<SaveComment>))
.route("/list", web::get().to(route_get::<GetComments>)),
)
// Private Message
.service(
@ -136,6 +137,7 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
"/followed_communities",
web::get().to(route_get::<GetFollowedCommunities>),
)
.route("/join", web::post().to(route_post::<UserJoin>))
// Admin action. I don't like that it's in /user
.route("/ban", web::post().to(route_post::<BanUser>))
// Account actions. I don't like that they're in /user maybe /accounts

1
ui/package.json

@ -37,6 +37,7 @@
"inferno-router": "^7.4.2",
"js-cookie": "^2.2.0",
"jwt-decode": "^2.2.0",
"lemmy-js-client": "^1.0.8",
"markdown-it": "^11.0.0",
"markdown-it-container": "^3.0.0",
"markdown-it-emoji": "^1.4.0",

4
ui/src/api_tests/comment.spec.ts

@ -21,7 +21,7 @@ import {
API,
} from './shared';
import { PostResponse } from '../interfaces';
import { PostResponse } from 'lemmy-js-client';
let postRes: PostResponse;
@ -136,7 +136,7 @@ test('Remove a comment from admin and community on the same instance', async ()
test('Remove a comment from admin and community on different instance', async () => {
let alphaUser = await registerUser(alpha);
let newAlphaApi: API = {
url: alpha.url,
client: alpha.client,
auth: alphaUser.jwt,
};

489
ui/src/api_tests/shared.ts

@ -1,5 +1,3 @@
import fetch from 'node-fetch';
import {
LoginForm,
LoginResponse,
@ -20,15 +18,21 @@ import {
CommentForm,
DeleteCommentForm,
RemoveCommentForm,
SearchForm,
CommentResponse,
CommunityForm,
DeleteCommunityForm,
RemoveCommunityForm,
GetUserMentionsForm,
CommentLikeForm,
CreatePostLikeForm,
PrivateMessageForm,
EditPrivateMessageForm,
DeletePrivateMessageForm,
GetFollowedCommunitiesForm,
GetPrivateMessagesForm,
GetSiteForm,
GetPostForm,
PrivateMessageResponse,
PrivateMessagesResponse,
GetUserMentionsResponse,
@ -36,35 +40,33 @@ import {
SortType,
ListingType,
GetSiteResponse,
} from '../interfaces';
SearchType,
LemmyHttp,
} from 'lemmy-js-client';
export interface API {
url: string;
client: LemmyHttp;
auth?: string;
}
function apiUrl(api: API) {
return `${api.url}/api/v1`;
}
export let alpha: API = {
url: 'http://localhost:8540',
client: new LemmyHttp('http://localhost:8540/api/v1'),
};
export let beta: API = {
url: 'http://localhost:8550',
client: new LemmyHttp('http://localhost:8550/api/v1'),
};
export let gamma: API = {
url: 'http://localhost:8560',
client: new LemmyHttp('http://localhost:8560/api/v1'),
};
export let delta: API = {
url: 'http://localhost:8570',
client: new LemmyHttp('http://localhost:8570/api/v1'),
};
export let epsilon: API = {
url: 'http://localhost:8580',
client: new LemmyHttp('http://localhost:8580/api/v1'),
};
export async function setupLogins() {
@ -72,69 +74,31 @@ export async function setupLogins() {
username_or_email: 'lemmy_alpha',
password: 'lemmy',
};
let resAlpha: Promise<LoginResponse> = fetch(`${apiUrl(alpha)}/user/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(formAlpha),
}).then(d => d.json());
let resAlpha = alpha.client.login(formAlpha);
let formBeta = {
username_or_email: 'lemmy_beta',
password: 'lemmy',
};
let resBeta: Promise<LoginResponse> = fetch(`${apiUrl(beta)}/user/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(formBeta),
}).then(d => d.json());
let resBeta = beta.client.login(formBeta);
let formGamma = {
username_or_email: 'lemmy_gamma',
password: 'lemmy',
};
let resGamma: Promise<LoginResponse> = fetch(`${apiUrl(gamma)}/user/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(formGamma),
}).then(d => d.json());
let resGamma = gamma.client.login(formGamma);
let formDelta = {
username_or_email: 'lemmy_delta',
password: 'lemmy',
};
let resDelta: Promise<LoginResponse> = fetch(`${apiUrl(delta)}/user/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(formDelta),
}).then(d => d.json());
let resDelta = delta.client.login(formDelta);
let formEpsilon = {
username_or_email: 'lemmy_epsilon',
password: 'lemmy',
};
let resEpsilon: Promise<LoginResponse> = fetch(
`${apiUrl(epsilon)}/user/login`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(formEpsilon),
}
).then(d => d.json());
let resEpsilon = epsilon.client.login(formEpsilon);
let res = await Promise.all([
resAlpha,
@ -156,40 +120,24 @@ export async function createPost(
community_id: number
): Promise<PostResponse> {
let name = 'A jest test post';
let postForm: PostForm = {
let form: PostForm = {
name,
auth: api.auth,
community_id,
nsfw: false,
};
let createPostRes: PostResponse = await fetch(`${apiUrl(api)}/post`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(postForm),
}).then(d => d.json());
return createPostRes;
return api.client.createPost(form);
}
export async function updatePost(api: API, post: Post): Promise<PostResponse> {
let name = 'A jest test federated post, updated';
let postForm: PostForm = {
let form: PostForm = {
name,
edit_id: post.id,
auth: api.auth,
nsfw: false,
};
let updateResponse: PostResponse = await fetch(`${apiUrl(api)}/post`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(postForm),
}).then(d => d.json());
return updateResponse;
return api.client.editPost(form);
}
export async function deletePost(
@ -197,20 +145,12 @@ export async function deletePost(
deleted: boolean,
post: Post
): Promise<PostResponse> {
let deletePostForm: DeletePostForm = {
let form: DeletePostForm = {
edit_id: post.id,
deleted: deleted,
auth: api.auth,
};
let deletePostRes: PostResponse = await fetch(`${apiUrl(api)}/post/delete`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(deletePostForm),
}).then(d => d.json());
return deletePostRes;
return api.client.deletePost(form);
}
export async function removePost(
@ -218,20 +158,12 @@ export async function removePost(
removed: boolean,
post: Post
): Promise<PostResponse> {
let removePostForm: RemovePostForm = {
let form: RemovePostForm = {
edit_id: post.id,
removed,
auth: api.auth,
};
let removePostRes: PostResponse = await fetch(`${apiUrl(api)}/post/remove`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(removePostForm),
}).then(d => d.json());
return removePostRes;
return api.client.removePost(form);
}
export async function stickyPost(
@ -239,21 +171,12 @@ export async function stickyPost(
stickied: boolean,
post: Post
): Promise<PostResponse> {
let stickyPostForm: StickyPostForm = {
let form: StickyPostForm = {
edit_id: post.id,
stickied,
auth: api.auth,
};
let stickyRes: PostResponse = await fetch(`${apiUrl(api)}/post/sticky`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(stickyPostForm),
}).then(d => d.json());
return stickyRes;
return api.client.stickyPost(form);
}
export async function lockPost(
@ -261,57 +184,46 @@ export async function lockPost(
locked: boolean,
post: Post
): Promise<PostResponse> {
let lockPostForm: LockPostForm = {
let form: LockPostForm = {
edit_id: post.id,
locked,
auth: api.auth,
};
let lockRes: PostResponse = await fetch(`${apiUrl(api)}/post/lock`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(lockPostForm),
}).then(d => d.json());
return lockRes;
return api.client.lockPost(form);
}
export async function searchPost(
api: API,
post: Post
): Promise<SearchResponse> {
let searchUrl = `${apiUrl(api)}/search?q=${post.ap_id}&type_=All&sort=TopAll`;
let searchResponse: SearchResponse = await fetch(searchUrl, {
method: 'GET',
}).then(d => d.json());
return searchResponse;
let form: SearchForm = {
q: post.ap_id,
type_: SearchType.All,
sort: SortType.TopAll,
};
return api.client.search(form);
}
export async function getPost(
api: API,
post_id: number
): Promise<GetPostResponse> {
let getPostUrl = `${apiUrl(api)}/post?id=${post_id}`;
let getPostRes: GetPostResponse = await fetch(getPostUrl, {
method: 'GET',
}).then(d => d.json());
return getPostRes;
let form: GetPostForm = {
id: post_id,
};
return api.client.getPost(form);
}
export async function searchComment(
api: API,
comment: Comment
): Promise<SearchResponse> {
let searchUrl = `${apiUrl(api)}/search?q=${
comment.ap_id
}&type_=All&sort=TopAll`;
let searchResponse: SearchResponse = await fetch(searchUrl, {
method: 'GET',
}).then(d => d.json());
return searchResponse;
let form: SearchForm = {
q: comment.ap_id,
type_: SearchType.All,
sort: SortType.TopAll,
};
return api.client.search(form);
}
export async function searchForBetaCommunity(
@ -319,14 +231,12 @@ export async function searchForBetaCommunity(
): Promise<SearchResponse> {
// Make sure lemmy-beta/c/main is cached on lemmy_alpha
// Use short-hand search url
let searchUrl = `${apiUrl(
api
)}/search?q=!main@lemmy-beta:8550&type_=All&sort=TopAll`;
let searchResponse: SearchResponse = await fetch(searchUrl, {
method: 'GET',
}).then(d => d.json());
return searchResponse;
let form: SearchForm = {
q: '!main@lemmy-beta:8550',
type_: SearchType.All,
sort: SortType.TopAll,
};
return api.client.search(form);
}
export async function searchForUser(
@ -335,14 +245,12 @@ export async function searchForUser(
): Promise<SearchResponse> {
// Make sure lemmy-beta/c/main is cached on lemmy_alpha
// Use short-hand search url
let searchUrl = `${apiUrl(
api
)}/search?q=${apShortname}&type_=All&sort=TopAll`;
let searchResponse: SearchResponse = await fetch(searchUrl, {
method: 'GET',
}).then(d => d.json());
return searchResponse;
let form: SearchForm = {
q: apShortname,
type_: SearchType.All,
sort: SortType.TopAll,
};
return api.client.search(form);
}
export async function followCommunity(
@ -350,41 +258,21 @@ export async function followCommunity(
follow: boolean,
community_id: number
): Promise<CommunityResponse> {
let followForm: FollowCommunityForm = {
let form: FollowCommunityForm = {
community_id,
follow,
auth: api.auth,
};
let followRes: CommunityResponse = await fetch(
`${apiUrl(api)}/community/follow`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(followForm),
}
)
.then(d => d.json())
.catch(_e => {});
return followRes;
return api.client.followCommunity(form);
}
export async function checkFollowedCommunities(
api: API
): Promise<GetFollowedCommunitiesResponse> {
let followedCommunitiesUrl = `${apiUrl(
api
)}/user/followed_communities?&auth=${api.auth}`;
let followedCommunitiesRes: GetFollowedCommunitiesResponse = await fetch(
followedCommunitiesUrl,
{
method: 'GET',
}
).then(d => d.json());
return followedCommunitiesRes;
let form: GetFollowedCommunitiesForm = {
auth: api.auth,
};
return api.client.getFollowedCommunities(form);
}
export async function likePost(
@ -392,21 +280,13 @@ export async function likePost(
score: number,
post: Post
): Promise<PostResponse> {
let likePostForm: CreatePostLikeForm = {
let form: CreatePostLikeForm = {
post_id: post.id,
score: score,
auth: api.auth,
};
let likePostRes: PostResponse = await fetch(`${apiUrl(api)}/post/like`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(likePostForm),
}).then(d => d.json());
return likePostRes;
return api.client.likePost(form);
}
export async function createComment(
@ -415,21 +295,13 @@ export async function createComment(
parent_id?: number,
content = 'a jest test comment'
): Promise<CommentResponse> {
let commentForm: CommentForm = {
let form: CommentForm = {
content,
post_id,
parent_id,
auth: api.auth,
};
let createResponse: CommentResponse = await fetch(`${apiUrl(api)}/comment`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(commentForm),
}).then(d => d.json());
return createResponse;
return api.client.createComment(form);
}
export async function updateComment(
@ -437,20 +309,12 @@ export async function updateComment(
edit_id: number,
content = 'A jest test federated comment update'
): Promise<CommentResponse> {
let commentForm: CommentForm = {
let form: CommentForm = {
content,
edit_id,
auth: api.auth,
};
let updateResponse: CommentResponse = await fetch(`${apiUrl(api)}/comment`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(commentForm),
}).then(d => d.json());
return updateResponse;
return api.client.editComment(form);
}
export async function deleteComment(
@ -458,23 +322,12 @@ export async function deleteComment(
deleted: boolean,
edit_id: number
): Promise<CommentResponse> {
let deleteCommentForm: DeleteCommentForm = {
let form: DeleteCommentForm = {
edit_id,
deleted,
auth: api.auth,
};
let deleteCommentRes: CommentResponse = await fetch(
`${apiUrl(api)}/comment/delete`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(deleteCommentForm),
}
).then(d => d.json());
return deleteCommentRes;
return api.client.deleteComment(form);
}
export async function removeComment(
@ -482,33 +335,21 @@ export async function removeComment(
removed: boolean,
edit_id: number
): Promise<CommentResponse> {
let removeCommentForm: RemoveCommentForm = {
let form: RemoveCommentForm = {
edit_id,
removed,
auth: api.auth,
};
let removeCommentRes: CommentResponse = await fetch(
`${apiUrl(api)}/comment/remove`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(removeCommentForm),
}
).then(d => d.json());
return removeCommentRes;
return api.client.removeComment(form);
}
export async function getMentions(api: API): Promise<GetUserMentionsResponse> {
let getMentionUrl = `${apiUrl(
api
)}/user/mention?sort=New&unread_only=false&auth=${api.auth}`;
let getMentionsRes: GetUserMentionsResponse = await fetch(getMentionUrl, {
method: 'GET',
}).then(d => d.json());
return getMentionsRes;
let form: GetUserMentionsForm = {
sort: SortType.New,
unread_only: false,
auth: api.auth,
};
return api.client.getUserMentions(form);
}
export async function likeComment(
@ -516,48 +357,26 @@ export async function likeComment(
score: number,
comment: Comment
): Promise<CommentResponse> {
let likeCommentForm: CommentLikeForm = {
let form: CommentLikeForm = {
comment_id: comment.id,
score,
auth: api.auth,
};
let likeCommentRes: CommentResponse = await fetch(
`${apiUrl(api)}/comment/like`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(likeCommentForm),
}
).then(d => d.json());
return likeCommentRes;
return api.client.likeComment(form);
}
export async function createCommunity(
api: API,
name_: string = randomString(5)
): Promise<CommunityResponse> {
let communityForm: CommunityForm = {
let form: CommunityForm = {
name: name_,
title: name_,
category_id: 1,
nsfw: false,
auth: api.auth,
};
let createCommunityRes: CommunityResponse = await fetch(
`${apiUrl(api)}/community`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(communityForm),
}
).then(d => d.json());
return createCommunityRes;
return api.client.createCommunity(form);
}
export async function deleteCommunity(
@ -565,23 +384,12 @@ export async function deleteCommunity(
deleted: boolean,
edit_id: number
): Promise<CommunityResponse> {
let deleteCommunityForm: DeleteCommunityForm = {
let form: DeleteCommunityForm = {
edit_id,
deleted,
auth: api.auth,
};
let deleteResponse: CommunityResponse = await fetch(
`${apiUrl(api)}/community/delete`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(deleteCommunityForm),
}
).then(d => d.json());
return deleteResponse;
return api.client.deleteCommunity(form);
}
export async function removeCommunity(
@ -589,23 +397,12 @@ export async function removeCommunity(
removed: boolean,
edit_id: number
): Promise<CommunityResponse> {
let removeCommunityForm: RemoveCommunityForm = {
let form: RemoveCommunityForm = {
edit_id,
removed,
auth: api.auth,
};
let removeResponse: CommunityResponse = await fetch(
`${apiUrl(api)}/community/remove`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(removeCommunityForm),
}
).then(d => d.json());
return removeResponse;
return api.client.removeCommunity(form);
}
export async function createPrivateMessage(
@ -613,23 +410,12 @@ export async function createPrivateMessage(
recipient_id: number
): Promise<PrivateMessageResponse> {
let content = 'A jest test federated private message';
let privateMessageForm: PrivateMessageForm = {
let form: PrivateMessageForm = {
content,
recipient_id,
auth: api.auth,
};
let createRes: PrivateMessageResponse = await fetch(
`${apiUrl(api)}/private_message`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(privateMessageForm),
}
).then(d => d.json());
return createRes;
return api.client.createPrivateMessage(form);
}
export async function updatePrivateMessage(
@ -637,23 +423,12 @@ export async function updatePrivateMessage(
edit_id: number
): Promise<PrivateMessageResponse> {
let updatedContent = 'A jest test federated private message edited';
let updatePrivateMessageForm: EditPrivateMessageForm = {
let form: EditPrivateMessageForm = {
content: updatedContent,
edit_id,
auth: api.auth,
};
let updateRes: PrivateMessageResponse = await fetch(
`${apiUrl(api)}/private_message`,
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(updatePrivateMessageForm),
}
).then(d => d.json());
return updateRes;
return api.client.editPrivateMessage(form);
}
export async function deletePrivateMessage(
@ -661,50 +436,26 @@ export async function deletePrivateMessage(
deleted: boolean,
edit_id: number
): Promise<PrivateMessageResponse> {
let deletePrivateMessageForm: DeletePrivateMessageForm = {
let form: DeletePrivateMessageForm = {
deleted,
edit_id,
auth: api.auth,
};
let deleteRes: PrivateMessageResponse = await fetch(
`${apiUrl(api)}/private_message/delete`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(deletePrivateMessageForm),
}
).then(d => d.json());
return deleteRes;
return api.client.deletePrivateMessage(form);
}
export async function registerUser(
api: API,
username: string = randomString(5)
): Promise<LoginResponse> {
let registerForm: RegisterForm = {
let form: RegisterForm = {
username,
password: 'test',
password_verify: 'test',
admin: false,
show_nsfw: true,
};
let registerRes: Promise<LoginResponse> = fetch(
`${apiUrl(api)}/user/register`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(registerForm),
}
).then(d => d.json());
return registerRes;
return api.client.register(form);
}
export async function saveUserSettingsBio(
@ -714,54 +465,36 @@ export async function saveUserSettingsBio(
let form: UserSettingsForm = {
show_nsfw: true,
theme: 'darkly',
default_sort_type: SortType.Active,
default_listing_type: ListingType.All,
default_sort_type: Object.keys(SortType).indexOf(SortType.Active),
default_listing_type: Object.keys(ListingType).indexOf(ListingType.All),
lang: 'en',
show_avatars: true,
send_notifications_to_email: false,
bio: 'a changed bio',
auth,
};
let res: Promise<LoginResponse> = fetch(
`${apiUrl(api)}/user/save_user_settings`,
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: wrapper(form),
}
).then(d => d.json());
return res;
return api.client.saveUserSettings(form);
}
export async function getSite(
api: API,
auth: string
): Promise<GetSiteResponse> {
let siteUrl = `${apiUrl(api)}/site?auth=${auth}`;
let res: GetSiteResponse = await fetch(siteUrl, {
method: 'GET',
}).then(d => d.json());
return res;
let form: GetSiteForm = {
auth,
};
return api.client.getSite(form);
}
export async function listPrivateMessages(
api: API
): Promise<PrivateMessagesResponse> {
let getPrivateMessagesUrl = `${apiUrl(api)}/private_message/list?auth=${
api.auth
}&unread_only=false&limit=999`;
let getPrivateMessagesRes: PrivateMessagesResponse = await fetch(
getPrivateMessagesUrl,
{
method: 'GET',
}
).then(d => d.json());
return getPrivateMessagesRes;
let form: GetPrivateMessagesForm = {
auth: api.auth,
unread_only: false,
limit: 999,
};
return api.client.getPrivateMessages(form);
}
export async function unfollowRemotes(

2
ui/src/components/admin-settings.tsx

@ -9,7 +9,7 @@ import {
SiteConfigForm,
GetSiteConfigResponse,
WebSocketJsonResponse,
} from '../interfaces';
} from 'lemmy-js-client';
import { WebSocketService } from '../services';
import { wsJsonToRes, capitalizeFirstLetter, toast, randomStr } from '../utils';
import autosize from 'autosize';

2
ui/src/components/comment-form.tsx

@ -8,7 +8,7 @@ import {
WebSocketJsonResponse,
UserOperation,
CommentResponse,
} from '../interfaces';
} from 'lemmy-js-client';
import { capitalizeFirstLetter, wsJsonToRes } from '../utils';
import { WebSocketService, UserService } from '../services';
import { i18n } from '../i18next';

5
ui/src/components/comment-node.tsx

@ -16,10 +16,9 @@ import {
AddAdminForm,
TransferCommunityForm,
TransferSiteForm,
BanType,
CommentSortType,
SortType,
} from '../interfaces';
} from 'lemmy-js-client';
import { CommentSortType, BanType } from '../interfaces';
import { WebSocketService, UserService } from '../services';
import {
mdToHtml,

4
ui/src/components/comment-nodes.tsx

@ -1,11 +1,11 @@
import { Component } from 'inferno';
import { CommentSortType } from '../interfaces';
import {
CommentNode as CommentNodeI,
CommunityUser,
UserView,
CommentSortType,
SortType,
} from '../interfaces';
} from 'lemmy-js-client';
import { commentSort, commentSortSortType } from '../utils';
import { CommentNode } from './comment-node';

4
ui/src/components/communities.tsx

@ -13,7 +13,7 @@ import {
WebSocketJsonResponse,
GetSiteResponse,
Site,
} from '../interfaces';
} from 'lemmy-js-client';
import { WebSocketService } from '../services';
import { wsJsonToRes, toast, getPageFromProps } from '../utils';
import { CommunityLink } from './community-link';
@ -218,7 +218,7 @@ export class Communities extends Component<any, CommunitiesState> {
refetch() {
let listCommunitiesForm: ListCommunitiesForm = {
sort: SortType[SortType.TopAll],
sort: SortType.TopAll,
limit: communityLimit,
page: this.state.page,
};

4
ui/src/components/community-form.tsx

@ -9,12 +9,12 @@ import {
ListCategoriesResponse,
CommunityResponse,
WebSocketJsonResponse,
} from '../interfaces';
Community,
} from 'lemmy-js-client';
import { WebSocketService } from '../services';
import { wsJsonToRes, capitalizeFirstLetter, toast, randomStr } from '../utils';
import { i18n } from '../i18next';
import { Community } from '../interfaces';
import { MarkdownTextArea } from './markdown-textarea';
import { ImageUploadForm } from './image-upload-form';

2
ui/src/components/community-link.tsx

@ -1,6 +1,6 @@
import { Component } from 'inferno';
import { Link } from 'inferno-router';
import { Community } from '../interfaces';
import { Community } from 'lemmy-js-client';
import { hostname, pictrsAvatarThumbnail, showAvatars } from '../utils';
interface CommunityOther {

28
ui/src/components/community.tsx

@ -2,6 +2,7 @@ import { Component, linkEvent } from 'inferno';
import { Helmet } from 'inferno-helmet';
import { Subscription } from 'rxjs';
import { retryWhen, delay, take } from 'rxjs/operators';
import { DataType } from '../interfaces';
import {
UserOperation,
Community as CommunityI,
@ -14,7 +15,6 @@ import {
GetPostsForm,
GetCommunityForm,
ListingType,
DataType,
GetPostsResponse,
PostResponse,
AddModToCommunityResponse,
@ -26,7 +26,7 @@ import {
WebSocketJsonResponse,
GetSiteResponse,
Site,
} from '../interfaces';
} from 'lemmy-js-client';
import { WebSocketService } from '../services';
import { PostListings } from './post-listings';
import { CommentNodes } from './comment-nodes';
@ -78,7 +78,7 @@ interface CommunityProps {
interface UrlParams {
dataType?: string;
sort?: string;
sort?: SortType;
page?: number;
}
@ -287,9 +287,7 @@ export class Community extends Component<any, State> {
<SortSelect sort={this.state.sort} onChange={this.handleSortChange} />
</span>
<a
href={`/feeds/c/${this.state.communityName}.xml?sort=${
SortType[this.state.sort]
}`}
href={`/feeds/c/${this.state.communityName}.xml?sort=${this.state.sort}`}
target="_blank"
title="RSS"
rel="noopener"
@ -336,20 +334,18 @@ export class Community extends Component<any, State> {
}
handleSortChange(val: SortType) {
this.updateUrl({ sort: SortType[val].toLowerCase(), page: 1 });
this.updateUrl({ sort: val, page: 1 });
window.scrollTo(0, 0);
}
handleDataTypeChange(val: DataType) {
this.updateUrl({ dataType: DataType[val].toLowerCase(), page: 1 });
this.updateUrl({ dataType: DataType[val], page: 1 });
window.scrollTo(0, 0);
}
updateUrl(paramUpdates: UrlParams) {
const dataTypeStr =
paramUpdates.dataType || DataType[this.state.dataType].toLowerCase();
const sortStr =
paramUpdates.sort || SortType[this.state.sort].toLowerCase();
const dataTypeStr = paramUpdates.dataType || DataType[this.state.dataType];
const sortStr = paramUpdates.sort || this.state.sort;
const page = paramUpdates.page || this.state.page;
this.props.history.push(
`/c/${this.state.community.name}/data_type/${dataTypeStr}/sort/${sortStr}/page/${page}`
@ -361,8 +357,8 @@ export class Community extends Component<any, State> {
let getPostsForm: GetPostsForm = {
page: this.state.page,
limit: fetchLimit,
sort: SortType[this.state.sort],
type_: ListingType[ListingType.Community],
sort: this.state.sort,
type_: ListingType.Community,
community_id: this.state.community.id,
};
WebSocketService.Instance.getPosts(getPostsForm);
@ -370,8 +366,8 @@ export class Community extends Component<any, State> {
let getCommentsForm: GetCommentsForm = {
page: this.state.page,
limit: fetchLimit,
sort: SortType[this.state.sort],
type_: ListingType[ListingType.Community],
sort: this.state.sort,
type_: ListingType.Community,
community_id: this.state.community.id,
};
WebSocketService.Instance.getComments(getCommentsForm);

2
ui/src/components/create-community.tsx

@ -9,7 +9,7 @@ import {
WebSocketJsonResponse,
GetSiteResponse,
Site,
} from '../interfaces';
} from 'lemmy-js-client';
import { toast, wsJsonToRes } from '../utils';
import { WebSocketService, UserService } from '../services';
import { i18n } from '../i18next';

2
ui/src/components/create-post.tsx

@ -11,7 +11,7 @@ import {
WebSocketJsonResponse,
GetSiteResponse,
Site,
} from '../interfaces';
} from 'lemmy-js-client';
import { i18n } from '../i18next';
interface CreatePostState {

2
ui/src/components/create-private-message.tsx

@ -10,7 +10,7 @@ import {
GetSiteResponse,
Site,
PrivateMessageFormParams,
} from '../interfaces';
} from 'lemmy-js-client';
import { toast, wsJsonToRes } from '../utils';
import { i18n } from '../i18next';

2
ui/src/components/footer.tsx

@ -9,7 +9,7 @@ import {
UserOperation,
WebSocketJsonResponse,
GetSiteResponse,
} from '../interfaces';
} from 'lemmy-js-client';
interface FooterState {
version: string;

2
ui/src/components/iframely-card.tsx

@ -1,5 +1,5 @@
import { Component, linkEvent } from 'inferno';
import { Post } from '../interfaces';
import { Post } from 'lemmy-js-client';
import { mdToHtml } from '../utils';
import { i18n } from '../i18next';

6
ui/src/components/inbox.tsx

@ -19,7 +19,7 @@ import {
PrivateMessageResponse,
GetSiteResponse,
Site,
} from '../interfaces';
} from 'lemmy-js-client';
import { WebSocketService, UserService } from '../services';
import {
wsJsonToRes,
@ -399,7 +399,7 @@ export class Inbox extends Component<any, InboxState> {
refetch() {
let repliesForm: GetRepliesForm = {
sort: SortType[this.state.sort],
sort: this.state.sort,
unread_only: this.state.unreadOrAll == UnreadOrAll.Unread,
page: this.state.page,
limit: fetchLimit,
@ -407,7 +407,7 @@ export class Inbox extends Component<any, InboxState> {
WebSocketService.Instance.getReplies(repliesForm);
let userMentionsForm: GetUserMentionsForm = {
sort: SortType[this.state.sort],
sort: this.state.sort,
unread_only: this.state.unreadOrAll == UnreadOrAll.Unread,
page: this.state.page,
limit: fetchLimit,

2
ui/src/components/instances.tsx

@ -6,7 +6,7 @@ import {
UserOperation,
WebSocketJsonResponse,
GetSiteResponse,
} from '../interfaces';
} from 'lemmy-js-client';
import { WebSocketService } from '../services';
import { wsJsonToRes, toast } from '../utils';
import { i18n } from '../i18next';

10
ui/src/components/listing-type-select.tsx

@ -1,7 +1,7 @@
import { Component, linkEvent } from 'inferno';
import { ListingType } from '../interfaces';
import { ListingType } from 'lemmy-js-client';
import { UserService } from '../services';
import { randomStr } from '../utils';
import { i18n } from '../i18next';
interface ListingTypeSelectProps {
@ -17,6 +17,8 @@ export class ListingTypeSelect extends Component<
ListingTypeSelectProps,
ListingTypeSelectState
> {
private id = `listing-type-input-${randomStr()}`;
private emptyState: ListingTypeSelectState = {
type_: this.props.type_,
};
@ -42,6 +44,7 @@ export class ListingTypeSelect extends Component<
`}
>
<input
id={`${this.id}-subscribed`}
type="radio"
value={ListingType.Subscribed}
checked={this.state.type_ == ListingType.Subscribed}
@ -56,6 +59,7 @@ export class ListingTypeSelect extends Component<
}`}
>
<input
id={`${this.id}-all`}
type="radio"
value={ListingType.All}
checked={this.state.type_ == ListingType.All}
@ -68,6 +72,6 @@ export class ListingTypeSelect extends Component<
}
handleTypeChange(i: ListingTypeSelect, event: any) {
i.props.onChange(Number(event.target.value));
i.props.onChange(event.target.value);
}
}

2
ui/src/components/login.tsx

@ -12,7 +12,7 @@ import {
GetCaptchaResponse,
WebSocketJsonResponse,
Site,
} from '../interfaces';
} from 'lemmy-js-client';
import { WebSocketService, UserService } from '../services';
import { wsJsonToRes, validEmail, toast } from '../utils';
import { i18n } from '../i18next';

40
ui/src/components/main.tsx

@ -13,7 +13,6 @@ import {
SortType,
GetSiteResponse,
ListingType,
DataType,
SiteResponse,
GetPostsResponse,
PostResponse,
@ -26,7 +25,8 @@ import {
AddAdminResponse,
BanUserResponse,
WebSocketJsonResponse,
} from '../interfaces';
} from 'lemmy-js-client';
import { DataType } from '../interfaces';
import { WebSocketService, UserService } from '../services';
import { PostListings } from './post-listings';
import { CommentNodes } from './comment-nodes';
@ -82,9 +82,9 @@ interface MainProps {
}
interface UrlParams {
listingType?: string;
listingType?: ListingType;
dataType?: string;
sort?: string;
sort?: SortType;
page?: number;
}
@ -151,7 +151,7 @@ export class Main extends Component<any, MainState> {
}
let listCommunitiesForm: ListCommunitiesForm = {
sort: SortType[SortType.Hot],
sort: SortType.Hot,
limit: 6,
};
@ -334,13 +334,9 @@ export class Main extends Component<any, MainState> {
}
updateUrl(paramUpdates: UrlParams) {
const listingTypeStr =
paramUpdates.listingType ||
ListingType[this.state.listingType].toLowerCase();
const dataTypeStr =
paramUpdates.dataType || DataType[this.state.dataType].toLowerCase();
const sortStr =
paramUpdates.sort || SortType[this.state.sort].toLowerCase();
const listingTypeStr = paramUpdates.listingType || this.state.listingType;
const dataTypeStr = paramUpdates.dataType || DataType[this.state.dataType];
const sortStr = paramUpdates.sort || this.state.sort;
const page = paramUpdates.page || this.state.page;
this.props.history.push(
`/home/data_type/${dataTypeStr}/listing_type/${listingTypeStr}/sort/${sortStr}/page/${page}`
@ -549,7 +545,7 @@ export class Main extends Component<any, MainState> {
</span>
{this.state.listingType == ListingType.All && (
<a
href={`/feeds/all.xml?sort=${SortType[this.state.sort]}`}
href={`/feeds/all.xml?sort=${this.state.sort}`}
target="_blank"
rel="noopener"
title="RSS"
@ -562,9 +558,7 @@ export class Main extends Component<any, MainState> {
{UserService.Instance.user &&
this.state.listingType == ListingType.Subscribed && (
<a
href={`/feeds/front/${UserService.Instance.auth}.xml?sort=${
SortType[this.state.sort]
}`}
href={`/feeds/front/${UserService.Instance.auth}.xml?sort=${this.state.sort}`}
target="_blank"
title="RSS"
rel="noopener"
@ -631,17 +625,17 @@ export class Main extends Component<any, MainState> {
}
handleSortChange(val: SortType) {
this.updateUrl({ sort: SortType[val].toLowerCase(), page: 1 });
this.updateUrl({ sort: val, page: 1 });
window.scrollTo(0, 0);
}
handleListingTypeChange(val: ListingType) {
this.updateUrl({ listingType: ListingType[val].toLowerCase(), page: 1 });
this.updateUrl({ listingType: val, page: 1 });
window.scrollTo(0, 0);
}
handleDataTypeChange(val: DataType) {
this.updateUrl({ dataType: DataType[val].toLowerCase(), page: 1 });
this.updateUrl({ dataType: DataType[val], page: 1 });
window.scrollTo(0, 0);
}
@ -650,16 +644,16 @@ export class Main extends Component<any, MainState> {
let getPostsForm: GetPostsForm = {
page: this.state.page,
limit: fetchLimit,
sort: SortType[this.state.sort],
type_: ListingType[this.state.listingType],
sort: this.state.sort,
type_: this.state.listingType,
};
WebSocketService.Instance.getPosts(getPostsForm);
} else {
let getCommentsForm: GetCommentsForm = {
page: this.state.page,
limit: fetchLimit,
sort: SortType[this.state.sort],
type_: ListingType[this.state.listingType],
sort: this.state.sort,
type_: this.state.listingType,
};
WebSocketService.Instance.getComments(getCommentsForm);
}

2
ui/src/components/modlog.tsx

@ -19,7 +19,7 @@ import {
WebSocketJsonResponse,
GetSiteResponse,
Site,
} from '../interfaces';
} from 'lemmy-js-client';
import { WebSocketService } from '../services';
import { wsJsonToRes, addTypeInfo, fetchLimit, toast } from '../utils';
import { MomentTime } from './moment-time';

8
ui/src/components/navbar.tsx

@ -18,7 +18,7 @@ import {
PrivateMessage,