use super::*;
use crate::apub::activities::follow_community;
-use crate::apub::{format_community_name, gen_keypair_str, make_apub_endpoint, EndpointType};
+use crate::apub::{gen_keypair_str, make_apub_endpoint, EndpointType};
use diesel::PgConnection;
use std::str::FromStr;
-use url::Url;
#[derive(Serialize, Deserialize)]
pub struct GetCommunity {
}
};
- let mut community_view = match CommunityView::read(&conn, community.id, user_id) {
+ let community_view = match CommunityView::read(&conn, community.id, user_id) {
Ok(community) => community,
Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
};
let creator_user = admins.remove(creator_index);
admins.insert(0, creator_user);
- if !community.local {
- let domain = Url::parse(&community.actor_id)?;
- community_view.name =
- format_community_name(&community_view.name.to_string(), domain.host_str().unwrap());
- }
-
// Return the jwt
Ok(GetCommunityResponse {
community: community_view,
String::from_utf8_lossy(&bytes).into_owned()
}
-/// If community is on local instance, don't include the @instance part. This is only for displaying
-/// to the user and should never be used otherwise.
-pub fn format_community_name(name: &str, instance: &str) -> String {
- if instance == Settings::get().hostname {
- format!("!{}", name)
- } else {
- format!("!{}@{}", name, instance)
- }
-}
-
pub fn get_following_instances() -> Vec<Instance> {
Settings::get()
.federation
pub pool_size: u32,
}
-#[derive(Debug, Deserialize)]
+#[derive(Debug, Deserialize, Clone)]
pub struct Federation {
pub enabled: bool,
pub followed_instances: String,
user={{
name: admin.name,
avatar: admin.avatar,
+ id: admin.id,
+ local: admin.local,
+ actor_id: admin.actor_id,
}}
/>
</li>
user={{
name: banned.name,
avatar: banned.avatar,
+ id: banned.id,
+ local: banned.local,
+ actor_id: banned.actor_id,
}}
/>
</li>
user={{
name: node.comment.creator_name,
avatar: node.comment.creator_avatar,
+ id: node.comment.creator_id,
+ local: node.comment.creator_local,
+ actor_id: node.comment.creator_actor_id,
}}
/>
</span>
} from '../interfaces';
import { WebSocketService } from '../services';
import { wsJsonToRes, toast } from '../utils';
+import { CommunityLink } from './community-link';
import { i18n } from '../i18next';
declare const Sortable: any;
{this.state.communities.map(community => (
<tr>
<td>
- <Link to={`/c/${community.name}`}>
- {community.name}
- </Link>
+ <CommunityLink community={community} />
</td>
<td class="d-none d-lg-table-cell">{community.title}</td>
<td>{community.category_name}</td>
--- /dev/null
+import { Component } from 'inferno';
+import { Link } from 'inferno-router';
+import { Community } from '../interfaces';
+import { hostname } from '../utils';
+
+interface CommunityOther {
+ name: string;
+ id?: number; // Necessary if its federated
+ local?: boolean;
+ actor_id?: string;
+}
+
+interface CommunityLinkProps {
+ community: Community | CommunityOther;
+}
+
+export class CommunityLink extends Component<CommunityLinkProps, any> {
+ constructor(props: any, context: any) {
+ super(props, context);
+ }
+
+ render() {
+ let community = this.props.community;
+ let name_: string, link: string;
+ let local = community.local == null ? true : community.local;
+ if (local) {
+ name_ = community.name;
+ link = `/c/${community.name}`;
+ } else {
+ name_ = `${hostname(community.actor_id)}/${community.name}`;
+ link = `/community/${community.id}`;
+ }
+ return <Link to={link}>{name_}</Link>;
+ }
+}
removed: null,
nsfw: false,
deleted: null,
+ local: null,
+ actor_id: null,
+ last_refreshed_at: null,
+ creator_actor_id: null,
+ creator_local: null,
},
moderators: [],
admins: [],
import { DataTypeSelect } from './data-type-select';
import { SiteForm } from './site-form';
import { UserListing } from './user-listing';
+import { CommunityLink } from './community-link';
import {
wsJsonToRes,
repoUrl,
<ul class="list-inline">
{this.state.subscribedCommunities.map(community => (
<li class="list-inline-item">
- <Link to={`/c/${community.community_name}`}>
- {community.community_name}
- </Link>
+ <CommunityLink
+ community={{
+ name: community.community_name,
+ id: community.community_id,
+ local: community.community_local,
+ actor_id: community.community_actor_id,
+ }}
+ />
</li>
))}
</ul>
<ul class="list-inline">
{this.state.trendingCommunities.map(community => (
<li class="list-inline-item">
- <Link to={`/c/${community.name}`}>{community.name}</Link>
+ <CommunityLink community={community} />
</li>
))}
</ul>
user={{
name: admin.name,
avatar: admin.avatar,
+ local: admin.local,
+ actor_id: admin.actor_id,
+ id: admin.id,
}}
/>
</li>
setupTribute,
setupTippy,
emojiPicker,
+ hostname,
} from '../utils';
import autosize from 'autosize';
import Tribute from 'tributejs/src/Tribute.js';
onInput={linkEvent(this, this.handlePostCommunityChange)}
>
{this.state.communities.map(community => (
- <option value={community.id}>{community.name}</option>
+ <option value={community.id}>
+ {community.local
+ ? community.name
+ : `${hostname(community.actor_id)}/${community.name}`}
+ </option>
))}
</select>
</div>
import { PostForm } from './post-form';
import { IFramelyCard } from './iframely-card';
import { UserListing } from './user-listing';
+import { CommunityLink } from './community-link';
import {
md,
mdToHtml,
user={{
name: post.creator_name,
avatar: post.creator_avatar,
+ id: post.creator_id,
+ local: post.creator_local,
+ actor_id: post.creator_actor_id,
}}
/>
{this.isMod && (
{this.props.showCommunity && (
<span>
<span> {i18n.t('to')} </span>
- {post.local ? (
- <Link to={`/c/${post.community_name}`}>
- {post.community_name}
- </Link>
- ) : (
- <a href={post.community_actor_id} target="_blank">
- {hostname(post.ap_id)}/{post.community_name}
- </a>
- )}
+ <CommunityLink
+ community={{
+ name: post.community_name,
+ id: post.community_id,
+ local: post.community_local,
+ actor_id: post.community_actor_id,
+ }}
+ />
</span>
)}
</li>
user={{
name: this.state.recipient.name,
avatar: this.state.recipient.avatar,
+ id: this.state.recipient.id,
+ local: this.state.recipient.local,
+ actor_id: this.state.recipient.actor_id,
}}
/>
</div>
UserView,
} from '../interfaces';
import { WebSocketService, UserService } from '../services';
-import {
- mdToHtml,
- getUnixTime,
- pictshareAvatarThumbnail,
- showAvatars,
-} from '../utils';
+import { mdToHtml, getUnixTime, hostname } from '../utils';
import { CommunityForm } from './community-form';
import { UserListing } from './user-listing';
import { i18n } from '../i18next';
sidebar() {
let community = this.props.community;
+ let name_: string, link: string;
+
+ if (community.local) {
+ name_ = community.name;
+ link = `/c/${community.name}`;
+ } else {
+ name_ = `${hostname(community.actor_id)}/${community.name}`;
+ link = community.actor_id;
+ }
return (
<div>
<div class="card border-secondary mb-3">
</small>
)}
</h5>
- <Link className="text-muted" to={`/c/${community.name}`}>
- /c/{community.name}
- </Link>
+ {community.local ? (
+ <Link className="text-muted" to={link}>
+ {name_}
+ </Link>
+ ) : (
+ <a className="text-muted" href={link} target="_blank">
+ {name_}
+ </a>
+ )}
<ul class="list-inline mb-1 text-muted font-weight-bold">
{this.canMod && (
<>
user={{
name: mod.user_name,
avatar: mod.avatar,
+ id: mod.user_id,
+ local: mod.user_local,
+ actor_id: mod.user_actor_id,
}}
/>
</li>
))}
</ul>
+ {/* TODO the to= needs to be able to handle community_ids as well, since they're federated */}
<Link
class={`btn btn-sm btn-secondary btn-block mb-3 ${
(community.deleted || community.removed) && 'no-click'
import { Component } from 'inferno';
import { Link } from 'inferno-router';
import { UserView } from '../interfaces';
-import { pictshareAvatarThumbnail, showAvatars } from '../utils';
+import { pictshareAvatarThumbnail, showAvatars, hostname } from '../utils';
interface UserOther {
name: string;
+ id?: number; // Necessary if its federated
avatar?: string;
+ local?: boolean;
+ actor_id?: string;
}
interface UserListingProps {
render() {
let user = this.props.user;
+ let local = user.local == null ? true : user.local;
+ let name_: string, link: string;
+
+ if (local) {
+ name_ = user.name;
+ link = `/u/${user.name}`;
+ } else {
+ name_ = `${hostname(user.actor_id)}/${user.name}`;
+ link = `/user/${user.id}`;
+ }
+
return (
- <Link className="text-body font-weight-bold" to={`/u/${user.name}`}>
+ <Link className="text-body font-weight-bold" to={link}>
{user.avatar && showAvatars() && (
<img
height="32"
class="rounded-circle mr-2"
/>
)}
- <span>{user.name}</span>
+ <span>{name_}</span>
</Link>
);
}
setupTippy,
} from '../utils';
import { PostListing } from './post-listing';
+import { UserListing } from './user-listing';
import { SortSelect } from './sort-select';
import { ListingTypeSelect } from './listing-type-select';
import { CommentNodes } from './comment-nodes';
user: {
id: null,
name: null,
- fedi_name: null,
published: null,
number_of_posts: null,
post_score: null,
avatar: null,
show_avatars: null,
send_notifications_to_email: null,
+ actor_id: null,
+ local: null,
},
user_id: null,
username: null,
<div class="card-body">
<h5>
<ul class="list-inline mb-0">
- <li className="list-inline-item">{user.name}</li>
+ <li className="list-inline-item">
+ <UserListing user={user} />
+ </li>
{user.banned && (
<li className="list-inline-item badge badge-danger">
{i18n.t('banned')}
) : (
<>
<a
- className={`btn btn-block btn-secondary mt-3 ${!this.state
- .user.matrix_user_id && 'disabled'}`}
+ className={`btn btn-block btn-secondary mt-3 ${
+ !this.state.user.matrix_user_id && 'disabled'
+ }`}
target="_blank"
href={`https://matrix.to/#/${this.state.user.matrix_user_id}`}
>
const host = `${window.location.hostname}`;
const port = `${
- window.location.port == '4444' ? '8536' : window.location.port
+ window.location.port == '4444' ? '8540' : window.location.port
}`;
const endpoint = `${host}:${port}`;