mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-12-23 03:11:32 +00:00
* Add a simple linked instances page. Fixes #1070 * Changing allowed_instances to federated_instances.
This commit is contained in:
parent
3da47352be
commit
bc523abd62
14 changed files with 136 additions and 8 deletions
|
@ -133,6 +133,20 @@ impl Settings {
|
|||
fs::read_to_string(CONFIG_FILE)
|
||||
}
|
||||
|
||||
pub fn get_allowed_instances(&self) -> Vec<String> {
|
||||
let mut allowed_instances: Vec<String> = self
|
||||
.federation
|
||||
.allowed_instances
|
||||
.split(',')
|
||||
.map(|d| d.to_string())
|
||||
.collect();
|
||||
|
||||
// The defaults.hjson config always returns a [""]
|
||||
allowed_instances.retain(|d| !d.eq(""));
|
||||
|
||||
allowed_instances
|
||||
}
|
||||
|
||||
pub fn save_config_file(data: &str) -> Result<String, Error> {
|
||||
fs::write(CONFIG_FILE, data)?;
|
||||
|
||||
|
|
|
@ -130,6 +130,7 @@ pub struct GetSiteResponse {
|
|||
pub online: usize,
|
||||
version: String,
|
||||
my_user: Option<User_>,
|
||||
federated_instances: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
|
@ -433,6 +434,7 @@ impl Perform for Oper<GetSite> {
|
|||
online,
|
||||
version: version::VERSION.to_string(),
|
||||
my_user,
|
||||
federated_instances: Settings::get().get_allowed_instances(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -659,6 +661,7 @@ impl Perform for Oper<TransferSite> {
|
|||
online: 0,
|
||||
version: version::VERSION.to_string(),
|
||||
my_user: Some(user),
|
||||
federated_instances: Settings::get().get_allowed_instances(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,12 +76,8 @@ fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> {
|
|||
return Err(anyhow!("invalid apub id scheme: {:?}", apub_id.scheme()).into());
|
||||
}
|
||||
|
||||
let mut allowed_instances: Vec<String> = Settings::get()
|
||||
.federation
|
||||
.allowed_instances
|
||||
.split(',')
|
||||
.map(|d| d.to_string())
|
||||
.collect();
|
||||
let mut allowed_instances: Vec<String> = Settings::get().get_allowed_instances();
|
||||
|
||||
// need to allow this explicitly because apub activities might contain objects from our local
|
||||
// instance. replace is needed to remove the port in our federation test setup.
|
||||
let settings = Settings::get();
|
||||
|
|
|
@ -40,7 +40,8 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
|||
)
|
||||
.route("/search", web::get().to(index))
|
||||
.route("/sponsors", web::get().to(index))
|
||||
.route("/password_change/{token}", web::get().to(index));
|
||||
.route("/password_change/{token}", web::get().to(index))
|
||||
.route("/instances", web::get().to(index));
|
||||
}
|
||||
|
||||
async fn index() -> Result<NamedFile, Error> {
|
||||
|
|
1
ui/src/components/admin-settings.tsx
vendored
1
ui/src/components/admin-settings.tsx
vendored
|
@ -48,6 +48,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
|||
banned: [],
|
||||
online: null,
|
||||
version: null,
|
||||
federated_instances: null,
|
||||
},
|
||||
siteConfigForm: {
|
||||
config_hjson: null,
|
||||
|
|
5
ui/src/components/footer.tsx
vendored
5
ui/src/components/footer.tsx
vendored
|
@ -51,6 +51,11 @@ export class Footer extends Component<any, FooterState> {
|
|||
{i18n.t('modlog')}
|
||||
</Link>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<Link class="nav-link" to="/instances">
|
||||
{i18n.t('instances')}
|
||||
</Link>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href={'/docs/index.html'}>
|
||||
{i18n.t('docs')}
|
||||
|
|
98
ui/src/components/instances.tsx
vendored
Normal file
98
ui/src/components/instances.tsx
vendored
Normal file
|
@ -0,0 +1,98 @@
|
|||
import { Component } from 'inferno';
|
||||
import { Helmet } from 'inferno-helmet';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { retryWhen, delay, take } from 'rxjs/operators';
|
||||
import {
|
||||
UserOperation,
|
||||
WebSocketJsonResponse,
|
||||
GetSiteResponse,
|
||||
} from '../interfaces';
|
||||
import { WebSocketService } from '../services';
|
||||
import { wsJsonToRes, toast } from '../utils';
|
||||
import { i18n } from '../i18next';
|
||||
|
||||
interface InstancesState {
|
||||
loading: boolean;
|
||||
siteRes: GetSiteResponse;
|
||||
}
|
||||
|
||||
export class Instances extends Component<any, InstancesState> {
|
||||
private subscription: Subscription;
|
||||
private emptyState: InstancesState = {
|
||||
loading: true,
|
||||
siteRes: undefined,
|
||||
};
|
||||
|
||||
constructor(props: any, context: any) {
|
||||
super(props, context);
|
||||
this.state = this.emptyState;
|
||||
this.subscription = WebSocketService.Instance.subject
|
||||
.pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
|
||||
.subscribe(
|
||||
msg => this.parseMessage(msg),
|
||||
err => console.error(err),
|
||||
() => console.log('complete')
|
||||
);
|
||||
|
||||
WebSocketService.Instance.getSite();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
|
||||
get documentTitle(): string {
|
||||
if (this.state.siteRes) {
|
||||
return `${i18n.t('instances')} - ${this.state.siteRes.site.name}`;
|
||||
} else {
|
||||
return 'Lemmy';
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div class="container">
|
||||
<Helmet title={this.documentTitle} />
|
||||
{this.state.loading ? (
|
||||
<h5 class="">
|
||||
<svg class="icon icon-spinner spin">
|
||||
<use xlinkHref="#icon-spinner"></use>
|
||||
</svg>
|
||||
</h5>
|
||||
) : (
|
||||
<div>
|
||||
<h5>{i18n.t('linked_instances')}</h5>
|
||||
{this.state.siteRes &&
|
||||
this.state.siteRes.federated_instances.length ? (
|
||||
<ul>
|
||||
{this.state.siteRes.federated_instances.map(i => (
|
||||
<li>
|
||||
<a href={`https://${i}`} target="_blank" rel="noopener">
|
||||
{i}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<div>{i18n.t('none_found')}</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
parseMessage(msg: WebSocketJsonResponse) {
|
||||
console.log(msg);
|
||||
let res = wsJsonToRes(msg);
|
||||
if (msg.error) {
|
||||
toast(i18n.t(msg.error), 'danger');
|
||||
return;
|
||||
} else if (res.op == UserOperation.GetSite) {
|
||||
let data = res.data as GetSiteResponse;
|
||||
this.state.siteRes = data;
|
||||
this.state.loading = false;
|
||||
this.setState(this.state);
|
||||
}
|
||||
}
|
||||
}
|
1
ui/src/components/main.tsx
vendored
1
ui/src/components/main.tsx
vendored
|
@ -114,6 +114,7 @@ export class Main extends Component<any, MainState> {
|
|||
banned: [],
|
||||
online: null,
|
||||
version: null,
|
||||
federated_instances: null,
|
||||
},
|
||||
showEditSite: false,
|
||||
loading: true,
|
||||
|
|
1
ui/src/components/navbar.tsx
vendored
1
ui/src/components/navbar.tsx
vendored
|
@ -82,6 +82,7 @@ export class Navbar extends Component<any, NavbarState> {
|
|||
banned: [],
|
||||
online: null,
|
||||
version: null,
|
||||
federated_instances: null,
|
||||
},
|
||||
searchParam: '',
|
||||
toggleSearch: false,
|
||||
|
|
1
ui/src/components/post.tsx
vendored
1
ui/src/components/post.tsx
vendored
|
@ -97,6 +97,7 @@ export class Post extends Component<any, PostState> {
|
|||
},
|
||||
online: null,
|
||||
version: null,
|
||||
federated_instances: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
1
ui/src/components/user.tsx
vendored
1
ui/src/components/user.tsx
vendored
|
@ -142,6 +142,7 @@ export class User extends Component<any, UserState> {
|
|||
},
|
||||
version: undefined,
|
||||
my_user: undefined,
|
||||
federated_instances: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
2
ui/src/index.tsx
vendored
2
ui/src/index.tsx
vendored
|
@ -19,6 +19,7 @@ import { AdminSettings } from './components/admin-settings';
|
|||
import { Inbox } from './components/inbox';
|
||||
import { Search } from './components/search';
|
||||
import { Sponsors } from './components/sponsors';
|
||||
import { Instances } from './components/instances';
|
||||
import { Symbols } from './components/symbols';
|
||||
import { i18n } from './i18next';
|
||||
|
||||
|
@ -89,6 +90,7 @@ class Index extends Component<any, any> {
|
|||
path={`/password_change/:token`}
|
||||
component={PasswordChange}
|
||||
/>
|
||||
<Route path={`/instances`} component={Instances} />
|
||||
</Switch>
|
||||
<Symbols />
|
||||
</div>
|
||||
|
|
1
ui/src/interfaces.ts
vendored
1
ui/src/interfaces.ts
vendored
|
@ -867,6 +867,7 @@ export interface GetSiteResponse {
|
|||
online: number;
|
||||
version: string;
|
||||
my_user?: User;
|
||||
federated_instances: Array<string>;
|
||||
}
|
||||
|
||||
export interface SiteResponse {
|
||||
|
|
5
ui/translations/en.json
vendored
5
ui/translations/en.json
vendored
|
@ -294,5 +294,8 @@
|
|||
"invalid_post_title": "Invalid post title",
|
||||
"invalid_url": "Invalid URL.",
|
||||
"play_captcha_audio": "Play Captcha Audio",
|
||||
"bio": "Bio"
|
||||
"bio": "Bio",
|
||||
"instances": "Instances",
|
||||
"linked_instances": "Linked Instances",
|
||||
"none_found": "None found."
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue