diff options
| author | 2025-05-26 13:28:55 +0200 | |
|---|---|---|
| committer | 2025-05-26 13:28:55 +0200 | |
| commit | fd64a1e264d828c6248dfe3fe12631af4e93a22c (patch) | |
| tree | 472d4d2b714af406eb06570ea299d3653b739a1f /web/source/settings/lib | |
| parent | [feature] update proof-of-work to allow setting required rounds (#4186) (diff) | |
| download | gotosocial-fd64a1e264d828c6248dfe3fe12631af4e93a22c.tar.xz | |
[feature] Add "Instance Info" settings panel section, with domain blocks + allows (#4193)
This pull request adds a new read-only, user-level "instance info" section to the settings panel, which presents api/v2/instance info in a nice readable format, and also gives the user authenticated access to the blocklist and allowlist of the domain.
Closes https://codeberg.org/superseriousbusiness/gotosocial/issues/3711
Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4193
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
Diffstat (limited to 'web/source/settings/lib')
| -rw-r--r-- | web/source/settings/lib/query/gts-api.ts | 16 | ||||
| -rw-r--r-- | web/source/settings/lib/query/user/domainperms.ts | 53 | ||||
| -rw-r--r-- | web/source/settings/lib/types/domain-permission.ts | 1 | ||||
| -rw-r--r-- | web/source/settings/lib/types/instance.ts | 112 | ||||
| -rw-r--r-- | web/source/settings/lib/util/index.ts | 42 |
5 files changed, 188 insertions, 36 deletions
diff --git a/web/source/settings/lib/query/gts-api.ts b/web/source/settings/lib/query/gts-api.ts index 9d38e435d..33429d8a8 100644 --- a/web/source/settings/lib/query/gts-api.ts +++ b/web/source/settings/lib/query/gts-api.ts @@ -26,7 +26,7 @@ import type { import { serialize as serializeForm } from "object-to-formdata"; import type { FetchBaseQueryMeta } from "@reduxjs/toolkit/dist/query/fetchBaseQuery"; import type { RootState } from '../../redux/store'; -import { InstanceV1 } from '../types/instance'; +import { InstanceV1, InstanceV2 } from '../types/instance'; /** * GTSFetchArgs extends standard FetchArgs used by @@ -186,6 +186,11 @@ export const gtsApi = createApi({ query: () => ({ url: `/api/v1/instance` }) + }), + instanceV2: build.query<InstanceV2, void>({ + query: () => ({ + url: `/api/v2/instance` + }) }) }) }); @@ -193,8 +198,13 @@ export const gtsApi = createApi({ /** * Query /api/v1/instance to retrieve basic instance information. * This endpoint does not require authentication/authorization. - * TODO: move this to ./instance. */ const useInstanceV1Query = gtsApi.useInstanceV1Query; -export { useInstanceV1Query }; +/** + * Query /api/v2/instance to retrieve basic instance information. + * This endpoint does not require authentication/authorization. + */ +const useInstanceV2Query = gtsApi.useInstanceV2Query; + +export { useInstanceV1Query, useInstanceV2Query }; diff --git a/web/source/settings/lib/query/user/domainperms.ts b/web/source/settings/lib/query/user/domainperms.ts new file mode 100644 index 000000000..3d8e77bfe --- /dev/null +++ b/web/source/settings/lib/query/user/domainperms.ts @@ -0,0 +1,53 @@ +/* + GoToSocial + Copyright (C) GoToSocial Authors admin@gotosocial.org + SPDX-License-Identifier: AGPL-3.0-or-later + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +import { gtsApi } from "../gts-api"; + +import type { DomainPerm } from "../../types/domain-permission"; + +const extended = gtsApi.injectEndpoints({ + endpoints: (build) => ({ + instanceDomainBlocks: build.query<DomainPerm[], void>({ + query: () => ({ + url: `/api/v1/instance/domain_blocks` + }), + }), + + instanceDomainAllows: build.query<DomainPerm[], void>({ + query: () => ({ + url: `/api/v1/instance/domain_allows` + }) + }), + }), +}); + +/** + * Get user-level view of all explicitly blocked domains. + */ +const useInstanceDomainBlocksQuery = extended.useInstanceDomainBlocksQuery; + +/** + * Get user-level view of all explicitly allowed domains. + */ +const useInstanceDomainAllowsQuery = extended.useInstanceDomainAllowsQuery; + +export { + useInstanceDomainBlocksQuery, + useInstanceDomainAllowsQuery, +}; diff --git a/web/source/settings/lib/types/domain-permission.ts b/web/source/settings/lib/types/domain-permission.ts index 27c4b56c9..3e947db61 100644 --- a/web/source/settings/lib/types/domain-permission.ts +++ b/web/source/settings/lib/types/domain-permission.ts @@ -33,6 +33,7 @@ export interface DomainPerm { obfuscate?: boolean; private_comment?: string; public_comment?: string; + comment?: string; created_at?: string; created_by?: string; subscription_id?: string; diff --git a/web/source/settings/lib/types/instance.ts b/web/source/settings/lib/types/instance.ts index 9abdc6a96..87d129d92 100644 --- a/web/source/settings/lib/types/instance.ts +++ b/web/source/settings/lib/types/instance.ts @@ -17,36 +17,52 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import { Account } from "./account"; + export interface InstanceV1 { - uri: string; - account_domain: string; - title: string; - description: string; + uri: string; + account_domain: string; + title: string; + description: string; description_text?: string; - short_description: string; + short_description: string; short_description_text?: string; - custom_css: string; - email: string; - version: string; - debug?: boolean; - languages: any[]; // TODO: define this - registrations: boolean; - approval_required: boolean; - invites_enabled: boolean; - configuration: InstanceConfiguration; - urls: InstanceUrls; - stats: InstanceStats; - thumbnail: string; - contact_account: Object; // TODO: define this. - max_toot_chars: number; - rules: any[]; // TODO: define this - terms?: string; + custom_css: string; + email: string; + version: string; + debug?: boolean; + languages: string[]; + registrations: boolean; + approval_required: boolean; + invites_enabled: boolean; + configuration: InstanceV1Configuration; + urls: InstanceV1Urls; + stats: InstanceStats; + thumbnail: string; + contact_account: Account; + max_toot_chars: number; + rules: any[]; // TODO: define this + terms?: string; terms_text?: string; } -export interface InstanceConfiguration { +export interface InstanceV2 { + domain: string; + account_domain: string; + title: string; + version: string; + debug: boolean; + source_url: string; + description: string; + custom_css: string; + thumbnail: InstanceV2Thumbnail; + languages: string[]; + configuration: InstanceV2Configuration; +} + +export interface InstanceV1Configuration { statuses: InstanceStatuses; - media_attachments: InstanceMediaAttachments; + media_attachments: InstanceV1MediaAttachments; polls: InstancePolls; accounts: InstanceAccounts; emojis: InstanceEmojis; @@ -63,15 +79,6 @@ export interface InstanceEmojis { emoji_size_limit: number; } -export interface InstanceMediaAttachments { - supported_mime_types: string[]; - image_size_limit: number; - image_matrix_limit: number; - video_size_limit: number; - video_frame_rate_limit: number; - video_matrix_limit: number; -} - export interface InstancePolls { max_options: number; max_characters_per_option: number; @@ -92,7 +99,46 @@ export interface InstanceStats { user_count: number; } -export interface InstanceUrls { +export interface InstanceV1Urls { streaming_api: string; } +export interface InstanceV1MediaAttachments { + supported_mime_types: string[]; + image_size_limit: number; + image_matrix_limit: number; + video_size_limit: number; + video_frame_rate_limit: number; + video_matrix_limit: number; +} + +export interface InstanceV2Configuration { + urls: InstanceV2URLs; + accounts: InstanceAccounts; + statuses: InstanceStatuses; + media_attachments: InstanceV2MediaAttachments; + polls: InstancePolls; + translation: InstanceV2Translation; + emojis: InstanceEmojis; +} + +export interface InstanceV2MediaAttachments extends InstanceV1MediaAttachments { + description_limit: number; +} + +export interface InstanceV2Thumbnail { + url: string; + thumbnail_type?: string; + static_url?: string; + thumbnail_static_type?: string; + thumbnail_description?: string; + blurhash?: string; +} + +export interface InstanceV2Translation { + enabled: boolean; +} + +export interface InstanceV2URLs { + streaming: string; +} diff --git a/web/source/settings/lib/util/index.ts b/web/source/settings/lib/util/index.ts index 8bcf5ab5d..46b35fd70 100644 --- a/web/source/settings/lib/util/index.ts +++ b/web/source/settings/lib/util/index.ts @@ -22,6 +22,8 @@ import { useMemo } from "react"; import { AdminAccount } from "../types/account"; import { store } from "../../redux/store"; +import humanizeDuration from "humanize-duration"; + export function yesOrNo(b: boolean): string { return b ? "yes" : "no"; } @@ -54,3 +56,43 @@ export function useCapitalize(i?: string): string { return i.charAt(0).toUpperCase() + i.slice(1); }, [i]); } + +/** + * Return human-readable string representation of given bytes. + * + * Adapted from https://stackoverflow.com/a/14919494. + */ +export function useHumanReadableBytes(bytes: number): string { + return useMemo(() => { + const thresh = 1024; + const digitPrecision = 2; + const r = 10**digitPrecision; + const units = ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']; + + if (Math.abs(bytes) < thresh) { + return bytes + ' B'; + } + + let u = -1; + let threshed = bytes; + do { threshed /= thresh; ++u; + } while (Math.round(Math.abs(threshed) * r) / r >= thresh && u < units.length - 1); + + return threshed.toFixed(digitPrecision) + ' ' + units[u]; + }, [bytes]); +} + +/** + * Return human-readable string representation of given time in seconds. + */ +export function useHumanReadableDuration(seconds: number): string { + return useMemo(() => { + if (seconds % 2629746 === 0) { + const n = seconds / 2629746; + return n + " month" + (n !== 1 ? "s" : ""); + } + + const ms = seconds*1000; + return humanizeDuration(ms); + }, [seconds]); +} |
