localize room settings
This commit is contained in:
parent
45dc4fa8cf
commit
148120a1d4
33 changed files with 836 additions and 291 deletions
|
|
@ -607,5 +607,228 @@
|
|||
"existing_space": "Existing Space",
|
||||
"add_room": "Add Room",
|
||||
"existing_room": "Existing Room"
|
||||
},
|
||||
|
||||
"RoomSettings": {
|
||||
"general": "General",
|
||||
"members": "Members",
|
||||
"permissions": "Permissions",
|
||||
"emojis_stickers": "Emojis & Stickers",
|
||||
"developer_tools": "Developer Tools",
|
||||
|
||||
"profile": "Profile",
|
||||
"edit": "Edit",
|
||||
"unknown": "Unknown",
|
||||
"avatar": "Avatar",
|
||||
"upload": "Upload",
|
||||
"reset": "Reset",
|
||||
"remove": "Remove",
|
||||
"name": "Name",
|
||||
"topic": "Topic",
|
||||
"save": "Save",
|
||||
"cancel": "Cancel",
|
||||
|
||||
"options": "Options",
|
||||
"addresses": "Addresses",
|
||||
"advanced_options": "Advanced Options",
|
||||
|
||||
"space_access": "Space Access",
|
||||
"room_access": "Room Access",
|
||||
"space_access_desc": "Change how people can join the space.",
|
||||
"room_access_desc": "Change how people can join the room.",
|
||||
|
||||
"join_invite_only": "Invite Only",
|
||||
"join_knock_invite": "Knock & Invite",
|
||||
"join_space_members_or_knock": "Space Members or Knock",
|
||||
"join_space_members": "Space Members",
|
||||
"join_public": "Public",
|
||||
"join_unsupported": "Unsupported",
|
||||
|
||||
"history_visibility": "Message History Visibility",
|
||||
"history_visibility_desc": "Changes to history visibility will only apply to future messages and will not affect existing history.",
|
||||
"visibility_after_invite": "After Invite",
|
||||
"visibility_after_join": "After Join",
|
||||
"visibility_all_messages": "All Messages",
|
||||
"visibility_all_messages_guests": "All Messages (Guests)",
|
||||
|
||||
"room_encryption": "Room Encryption",
|
||||
"encryption_enabled_desc": "Messages in this room are protected by end-to-end encryption.",
|
||||
"encryption_disabled_desc": "Once enabled, encryption cannot be disabled!",
|
||||
"enabled": "Enabled",
|
||||
"enable": "Enable",
|
||||
"enable_encryption": "Enable Encryption",
|
||||
"enable_encryption_confirm": "Are you sure? Once enabled, encryption cannot be disabled!",
|
||||
"enable_e2e_encryption": "Enable E2E Encryption",
|
||||
|
||||
"publish_to_directory": "Publish to Directory",
|
||||
"publish_space_desc": "List the space in the public directory to make it discoverable by others.",
|
||||
"publish_room_desc": "List the room in the public directory to make it discoverable by others.",
|
||||
|
||||
"published_addresses": "Published Addresses",
|
||||
"published_addresses_desc": "If access is <b>Public</b>, Published addresses will be used to join by anyone.",
|
||||
"no_addresses": "No Addresses",
|
||||
"no_addresses_hint": "To publish an address, it needs to be set as a local address first",
|
||||
"main": "Main",
|
||||
"unset_main": "Unset Main",
|
||||
"set_main": "Set Main",
|
||||
"address_in_use": "Address is already in use!",
|
||||
"published": "Published",
|
||||
"unpublish": "Unpublish",
|
||||
"publish": "Publish",
|
||||
"delete": "Delete",
|
||||
"selected_count": "{{count}} Selected",
|
||||
|
||||
"local_addresses": "Local Addresses",
|
||||
"local_addresses_desc": "Set local address so users can join through your homeserver.",
|
||||
"collapse": "Collapse",
|
||||
"expand": "Expand",
|
||||
"loading": "Loading...",
|
||||
|
||||
"space_upgrade": "Space Upgrade",
|
||||
"room_upgrade": "Room Upgrade",
|
||||
"upgrade": "Upgrade",
|
||||
"action_irreversible": "This action is irreversible!",
|
||||
"upgrade_space": "Upgrade Space",
|
||||
"upgrade_room": "Upgrade Room",
|
||||
"space_replaced": "This space has been replaced!",
|
||||
"room_replaced": "This room has been replaced!",
|
||||
"current_version": "Current version: {{version}}.",
|
||||
"old_space": "Old Space",
|
||||
"old_room": "Old Room",
|
||||
"open_new_space": "Open New Space",
|
||||
"open_new_room": "Open New Room",
|
||||
|
||||
"members_count": "{{count}} Members",
|
||||
"search": "Search",
|
||||
"no_results": "No Results",
|
||||
"results_count": "{{count}} Results",
|
||||
"scroll_to_top": "Scroll to Top",
|
||||
"no_membership_members": "No \"{{filter}}\" Members",
|
||||
|
||||
"filter_joined": "Joined",
|
||||
"filter_invited": "Invited",
|
||||
"filter_left": "Left",
|
||||
"filter_kicked": "Kicked",
|
||||
"filter_banned": "Banned",
|
||||
|
||||
"sort_a_to_z": "A to Z",
|
||||
"sort_z_to_a": "Z to A",
|
||||
"sort_newest": "Newest",
|
||||
"sort_oldest": "Oldest",
|
||||
|
||||
"perm_messages": "Messages",
|
||||
"perm_send_messages": "Send Messages",
|
||||
"perm_send_stickers": "Send Stickers",
|
||||
"perm_send_reactions": "Send Reactions",
|
||||
"perm_ping_room": "Ping @room",
|
||||
"perm_pin_messages": "Pin Messages",
|
||||
"perm_other_message_events": "Other Message Events",
|
||||
"perm_calls": "Calls",
|
||||
"perm_join_call": "Join Call",
|
||||
"perm_moderation": "Moderation",
|
||||
"perm_invite": "Invite",
|
||||
"perm_kick": "Kick",
|
||||
"perm_ban": "Ban",
|
||||
"perm_delete_others_messages": "Delete Others' Messages",
|
||||
"perm_delete_self_messages": "Delete Self Messages",
|
||||
"perm_room_overview": "Room Overview",
|
||||
"perm_room_avatar": "Room Avatar",
|
||||
"perm_room_name": "Room Name",
|
||||
"perm_room_topic": "Room Topic",
|
||||
"perm_settings": "Settings",
|
||||
"perm_change_room_access": "Change Room Access",
|
||||
"perm_publish_address": "Publish Address",
|
||||
"perm_change_all_permission": "Change All Permissions",
|
||||
"perm_edit_power_levels": "Edit Power Levels",
|
||||
"perm_enable_encryption": "Enable Encryption",
|
||||
"perm_history_visibility": "History Visibility",
|
||||
"perm_upgrade_room": "Upgrade Room",
|
||||
"perm_other_settings": "Other Settings",
|
||||
"perm_other": "Other",
|
||||
"perm_manage_emojis_stickers": "Manage Emojis & Stickers",
|
||||
"perm_change_server_acls": "Change Server ACLs",
|
||||
"perm_modify_widgets": "Modify Widgets",
|
||||
|
||||
"founders": "Founders",
|
||||
"founders_desc": "Founding members have all permissions and can only be changed during a room upgrade.",
|
||||
"power_levels": "Power Levels",
|
||||
"power_levels_desc": "Manage and customize incremental power levels for users.",
|
||||
|
||||
"new_power_level": "New Power Level",
|
||||
"new_power_level_desc": "Create a new power level.",
|
||||
"power_level_placeholder": "Bot",
|
||||
"create": "Create",
|
||||
"color": "Color",
|
||||
"pick": "Pick",
|
||||
"power": "Power",
|
||||
"icon": "Icon",
|
||||
"import": "Import",
|
||||
"undo": "Undo",
|
||||
"used_power_level": "Used Power Level",
|
||||
"used_power_level_desc": "You have to remove its use before you can delete it.",
|
||||
"changes_saved": "Changes saved! Apply when ready.",
|
||||
"failed_to_apply": "Failed to apply changes! Please try again.",
|
||||
"apply_changes": "Apply Changes",
|
||||
"and_above": "& Above",
|
||||
|
||||
"users": "Users",
|
||||
"default_power": "Default Power",
|
||||
"default_power_desc": "Default power level for all users.",
|
||||
|
||||
"packs": "Packs",
|
||||
"new_pack": "New Pack",
|
||||
"new_pack_desc": "Add your own emoji and sticker pack to use in room.",
|
||||
"no_packs": "No Packs",
|
||||
"no_packs_desc": "There are no emoji or sticker packs to display at the moment.",
|
||||
"view": "View",
|
||||
"failed_to_remove_packs": "Failed to remove packs! Please try again.",
|
||||
"delete_selected_packs": "Delete selected packs. ({{count}} selected)",
|
||||
|
||||
"enable_developer_tools": "Enable Developer Tools",
|
||||
"room_id": "Room ID",
|
||||
"room_id_desc": "Copy room ID to clipboard.",
|
||||
"copy": "Copy",
|
||||
"data": "Data",
|
||||
"new_message_event": "New Message Event",
|
||||
"new_message_event_desc": "Create and send a new message event within the room.",
|
||||
"compose": "Compose",
|
||||
"room_state": "Room State",
|
||||
"room_state_desc": "State events of the room.",
|
||||
"events": "Events",
|
||||
"total": "Total: {{count}}",
|
||||
"add_new": "Add New",
|
||||
"default_key": "Default",
|
||||
"account_data": "Account Data",
|
||||
"account_data_desc": "Private personalization data stored within room.",
|
||||
"state_event": "State Event",
|
||||
"json_content": "JSON Content",
|
||||
"state_event_type": "State Event Type",
|
||||
"message_event_type": "Message Event Type",
|
||||
"send": "Send",
|
||||
"state_key_optional": "State Key (Optional)",
|
||||
|
||||
"pack": "Pack",
|
||||
"images_usage": "Images Usage",
|
||||
"images_usage_desc": "Select how the images are being used: as emojis, as stickers, or as both.",
|
||||
"images": "Images",
|
||||
"upload_images": "Upload Images",
|
||||
"upload_images_desc": "Select images from your storage to upload them in pack.",
|
||||
"select": "Select",
|
||||
"pack_avatar": "Pack Avatar",
|
||||
"attribution": "Attribution",
|
||||
"shortcode": "Shortcode:",
|
||||
"body": "Body:",
|
||||
"usage_both": "Both",
|
||||
"usage_sticker": "Sticker",
|
||||
"usage_emoji": "Emoji",
|
||||
|
||||
"power_goku": "Goku",
|
||||
"power_manager": "Manager",
|
||||
"power_founder": "Founder",
|
||||
"power_admin": "Admin",
|
||||
"power_moderator": "Moderator",
|
||||
"power_member": "Member",
|
||||
"power_muted": "Muted",
|
||||
"power_team": "Team"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -609,5 +609,228 @@
|
|||
"existing_space": "Существующее пространство",
|
||||
"add_room": "Добавить комнату",
|
||||
"existing_room": "Существующая комната"
|
||||
},
|
||||
|
||||
"RoomSettings": {
|
||||
"general": "Основные",
|
||||
"members": "Участники",
|
||||
"permissions": "Права доступа",
|
||||
"emojis_stickers": "Эмодзи и стикеры",
|
||||
"developer_tools": "Инструменты разработчика",
|
||||
|
||||
"profile": "Профиль",
|
||||
"edit": "Редактировать",
|
||||
"unknown": "Неизвестно",
|
||||
"avatar": "Аватар",
|
||||
"upload": "Загрузить",
|
||||
"reset": "Сбросить",
|
||||
"remove": "Удалить",
|
||||
"name": "Название",
|
||||
"topic": "Тема",
|
||||
"save": "Сохранить",
|
||||
"cancel": "Отмена",
|
||||
|
||||
"options": "Настройки",
|
||||
"addresses": "Адреса",
|
||||
"advanced_options": "Дополнительные настройки",
|
||||
|
||||
"space_access": "Доступ к пространству",
|
||||
"room_access": "Доступ к комнате",
|
||||
"space_access_desc": "Изменить способ вступления в пространство.",
|
||||
"room_access_desc": "Изменить способ вступления в комнату.",
|
||||
|
||||
"join_invite_only": "Только по приглашению",
|
||||
"join_knock_invite": "Запрос и приглашение",
|
||||
"join_space_members_or_knock": "Участники пространства или запрос",
|
||||
"join_space_members": "Участники пространства",
|
||||
"join_public": "Публичный",
|
||||
"join_unsupported": "Не поддерживается",
|
||||
|
||||
"history_visibility": "Видимость истории сообщений",
|
||||
"history_visibility_desc": "Изменения видимости истории применяются только к новым сообщениям и не затрагивают существующую историю.",
|
||||
"visibility_after_invite": "После приглашения",
|
||||
"visibility_after_join": "После вступления",
|
||||
"visibility_all_messages": "Все сообщения",
|
||||
"visibility_all_messages_guests": "Все сообщения (гости)",
|
||||
|
||||
"room_encryption": "Шифрование комнаты",
|
||||
"encryption_enabled_desc": "Сообщения в этой комнате защищены сквозным шифрованием.",
|
||||
"encryption_disabled_desc": "После включения шифрование невозможно отключить!",
|
||||
"enabled": "Включено",
|
||||
"enable": "Включить",
|
||||
"enable_encryption": "Включить шифрование",
|
||||
"enable_encryption_confirm": "Вы уверены? После включения шифрование невозможно отключить!",
|
||||
"enable_e2e_encryption": "Включить E2E-шифрование",
|
||||
|
||||
"publish_to_directory": "Показывать в поиске",
|
||||
"publish_space_desc": "Сделать пространство видимым в общем списке, чтобы другие пользователи могли его найти.",
|
||||
"publish_room_desc": "Сделать комнату видимой в общем списке, чтобы другие пользователи могли её найти.",
|
||||
|
||||
"published_addresses": "Опубликованные адреса",
|
||||
"published_addresses_desc": "Если доступ <b>публичный</b>, опубликованные адреса будут использоваться для присоединения.",
|
||||
"no_addresses": "Нет адресов",
|
||||
"no_addresses_hint": "Чтобы опубликовать адрес, его сначала нужно задать как локальный",
|
||||
"main": "Основной",
|
||||
"unset_main": "Снять основной",
|
||||
"set_main": "Сделать основным",
|
||||
"address_in_use": "Адрес уже занят!",
|
||||
"published": "Опубликован",
|
||||
"unpublish": "Снять публикацию",
|
||||
"publish": "Опубликовать",
|
||||
"delete": "Удалить",
|
||||
"selected_count": "Выбрано: {{count}}",
|
||||
|
||||
"local_addresses": "Локальные адреса",
|
||||
"local_addresses_desc": "Задайте локальный адрес, чтобы пользователи могли присоединиться через ваш сервер.",
|
||||
"collapse": "Свернуть",
|
||||
"expand": "Развернуть",
|
||||
"loading": "Загрузка...",
|
||||
|
||||
"space_upgrade": "Обновление пространства",
|
||||
"room_upgrade": "Обновление комнаты",
|
||||
"upgrade": "Обновить",
|
||||
"action_irreversible": "Это действие необратимо!",
|
||||
"upgrade_space": "Обновить пространство",
|
||||
"upgrade_room": "Обновить комнату",
|
||||
"space_replaced": "Это пространство было заменено!",
|
||||
"room_replaced": "Эта комната была заменена!",
|
||||
"current_version": "Текущая версия: {{version}}.",
|
||||
"old_space": "Старое пространство",
|
||||
"old_room": "Старая комната",
|
||||
"open_new_space": "Открыть новое пространство",
|
||||
"open_new_room": "Открыть новую комнату",
|
||||
|
||||
"members_count": "{{count}} участников",
|
||||
"search": "Поиск",
|
||||
"no_results": "Ничего не найдено",
|
||||
"results_count": "{{count}} результатов",
|
||||
"scroll_to_top": "Наверх",
|
||||
"no_membership_members": "Нет участников «{{filter}}»",
|
||||
|
||||
"filter_joined": "Вступившие",
|
||||
"filter_invited": "Приглашённые",
|
||||
"filter_left": "Вышедшие",
|
||||
"filter_kicked": "Исключённые",
|
||||
"filter_banned": "Забаненные",
|
||||
|
||||
"sort_a_to_z": "А — Я",
|
||||
"sort_z_to_a": "Я — А",
|
||||
"sort_newest": "Новые",
|
||||
"sort_oldest": "Старые",
|
||||
|
||||
"perm_messages": "Сообщения",
|
||||
"perm_send_messages": "Отправка сообщений",
|
||||
"perm_send_stickers": "Отправка стикеров",
|
||||
"perm_send_reactions": "Отправка реакций",
|
||||
"perm_ping_room": "Упоминание @room",
|
||||
"perm_pin_messages": "Закрепление сообщений",
|
||||
"perm_other_message_events": "Прочие события сообщений",
|
||||
"perm_calls": "Звонки",
|
||||
"perm_join_call": "Присоединиться к звонку",
|
||||
"perm_moderation": "Модерация",
|
||||
"perm_invite": "Приглашение",
|
||||
"perm_kick": "Исключение",
|
||||
"perm_ban": "Бан",
|
||||
"perm_delete_others_messages": "Удаление чужих сообщений",
|
||||
"perm_delete_self_messages": "Удаление своих сообщений",
|
||||
"perm_room_overview": "Обзор комнаты",
|
||||
"perm_room_avatar": "Аватар комнаты",
|
||||
"perm_room_name": "Название комнаты",
|
||||
"perm_room_topic": "Тема комнаты",
|
||||
"perm_settings": "Настройки",
|
||||
"perm_change_room_access": "Изменение доступа к комнате",
|
||||
"perm_publish_address": "Публикация адреса",
|
||||
"perm_change_all_permission": "Изменение всех прав",
|
||||
"perm_edit_power_levels": "Редактирование уровней власти",
|
||||
"perm_enable_encryption": "Включение шифрования",
|
||||
"perm_history_visibility": "Видимость истории",
|
||||
"perm_upgrade_room": "Обновление комнаты",
|
||||
"perm_other_settings": "Прочие настройки",
|
||||
"perm_other": "Прочее",
|
||||
"perm_manage_emojis_stickers": "Управление эмодзи и стикерами",
|
||||
"perm_change_server_acls": "Изменение ACL серверов",
|
||||
"perm_modify_widgets": "Изменение виджетов",
|
||||
|
||||
"founders": "Основатели",
|
||||
"founders_desc": "Основатели имеют все права. Изменить их состав можно только при обновлении комнаты.",
|
||||
"power_levels": "Уровни власти",
|
||||
"power_levels_desc": "Управление и настройка уровней власти для пользователей.",
|
||||
|
||||
"new_power_level": "Новый уровень власти",
|
||||
"power_level_placeholder": "Бот",
|
||||
"new_power_level_desc": "Создать новый уровень власти.",
|
||||
"create": "Создать",
|
||||
"color": "Цвет",
|
||||
"pick": "Выбрать",
|
||||
"power": "Уровень",
|
||||
"icon": "Иконка",
|
||||
"import": "Импорт",
|
||||
"undo": "Отменить",
|
||||
"used_power_level": "Используемый уровень власти",
|
||||
"used_power_level_desc": "Необходимо убрать его использование, прежде чем удалить.",
|
||||
"changes_saved": "Изменения сохранены! Примените, когда будете готовы.",
|
||||
"failed_to_apply": "Не удалось применить изменения! Попробуйте ещё раз.",
|
||||
"apply_changes": "Применить изменения",
|
||||
"and_above": "и выше",
|
||||
|
||||
"users": "Пользователи",
|
||||
"default_power": "Уровень по умолчанию",
|
||||
"default_power_desc": "Уровень власти по умолчанию для всех пользователей.",
|
||||
|
||||
"packs": "Паки",
|
||||
"new_pack": "Новый пак",
|
||||
"new_pack_desc": "Добавьте свой пак эмодзи и стикеров для использования в комнате.",
|
||||
"no_packs": "Нет паков",
|
||||
"no_packs_desc": "На данный момент нет паков эмодзи или стикеров для отображения.",
|
||||
"view": "Открыть",
|
||||
"failed_to_remove_packs": "Не удалось удалить паки! Попробуйте ещё раз.",
|
||||
"delete_selected_packs": "Удалить выбранные паки. (Выбрано: {{count}})",
|
||||
|
||||
"enable_developer_tools": "Включить инструменты разработчика",
|
||||
"room_id": "ID комнаты",
|
||||
"room_id_desc": "Скопировать ID комнаты в буфер обмена.",
|
||||
"copy": "Копировать",
|
||||
"data": "Данные",
|
||||
"new_message_event": "Новое событие сообщения",
|
||||
"new_message_event_desc": "Создать и отправить новое событие сообщения в комнату.",
|
||||
"compose": "Создать",
|
||||
"room_state": "Состояние комнаты",
|
||||
"room_state_desc": "State-события комнаты.",
|
||||
"events": "События",
|
||||
"total": "Всего: {{count}}",
|
||||
"add_new": "Добавить",
|
||||
"default_key": "По умолчанию",
|
||||
"account_data": "Данные аккаунта",
|
||||
"account_data_desc": "Персональные данные, хранящиеся в комнате.",
|
||||
"state_event": "State-событие",
|
||||
"json_content": "JSON-содержимое",
|
||||
"state_event_type": "Тип state-события",
|
||||
"message_event_type": "Тип события сообщения",
|
||||
"send": "Отправить",
|
||||
"state_key_optional": "State Key (необязательно)",
|
||||
|
||||
"pack": "Пак",
|
||||
"images_usage": "Использование изображений",
|
||||
"images_usage_desc": "Выберите, как используются изображения: как эмодзи, как стикеры или как и то, и другое.",
|
||||
"images": "Изображения",
|
||||
"upload_images": "Загрузить изображения",
|
||||
"upload_images_desc": "Выберите изображения из хранилища для загрузки в пак.",
|
||||
"select": "Выбрать",
|
||||
"pack_avatar": "Аватар пака",
|
||||
"attribution": "Авторство",
|
||||
"shortcode": "Шорткод:",
|
||||
"body": "Описание:",
|
||||
"usage_both": "Оба",
|
||||
"usage_sticker": "Стикер",
|
||||
"usage_emoji": "Эмодзи",
|
||||
|
||||
"power_goku": "Гоку",
|
||||
"power_manager": "Менеджер",
|
||||
"power_founder": "Основатель",
|
||||
"power_admin": "Админ",
|
||||
"power_moderator": "Модератор",
|
||||
"power_member": "Участник",
|
||||
"power_muted": "Без голоса",
|
||||
"power_team": "Команда"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import {
|
|||
Scroll,
|
||||
config,
|
||||
} from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { MatrixError } from 'matrix-js-sdk';
|
||||
import { Cursor } from '../plugins/text-area';
|
||||
import { syntaxErrorPosition } from '../utils/dom';
|
||||
|
|
@ -47,6 +48,7 @@ function AccountDataEdit({
|
|||
onCancel,
|
||||
onSave,
|
||||
}: AccountDataEditProps) {
|
||||
const { t } = useTranslation();
|
||||
const alive = useAlive();
|
||||
|
||||
const textAreaRef = useRef<HTMLTextAreaElement>(null);
|
||||
|
|
@ -121,7 +123,7 @@ function AccountDataEdit({
|
|||
aria-disabled={submitting}
|
||||
>
|
||||
<Box shrink="No" direction="Column" gap="100">
|
||||
<Text size="L400">Account Data</Text>
|
||||
<Text size="L400">{t('RoomSettings.account_data')}</Text>
|
||||
<Box gap="300">
|
||||
<Box grow="Yes" direction="Column">
|
||||
<Input
|
||||
|
|
@ -142,7 +144,7 @@ function AccountDataEdit({
|
|||
disabled={submitting}
|
||||
before={submitting && <Spinner variant="Primary" fill="Solid" size="300" />}
|
||||
>
|
||||
<Text size="B400">Save</Text>
|
||||
<Text size="B400">{t('RoomSettings.save')}</Text>
|
||||
</Button>
|
||||
<Button
|
||||
variant="Secondary"
|
||||
|
|
@ -153,7 +155,7 @@ function AccountDataEdit({
|
|||
onClick={onCancel}
|
||||
disabled={submitting}
|
||||
>
|
||||
<Text size="B400">Cancel</Text>
|
||||
<Text size="B400">{t('RoomSettings.cancel')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
|
|
@ -165,7 +167,7 @@ function AccountDataEdit({
|
|||
</Box>
|
||||
<Box grow="Yes" direction="Column" gap="100">
|
||||
<Box shrink="No">
|
||||
<Text size="L400">JSON Content</Text>
|
||||
<Text size="L400">{t('RoomSettings.json_content')}</Text>
|
||||
</Box>
|
||||
<TextAreaComponent
|
||||
ref={textAreaRef}
|
||||
|
|
@ -198,6 +200,7 @@ type AccountDataViewProps = {
|
|||
onEdit: () => void;
|
||||
};
|
||||
function AccountDataView({ type, defaultContent, onEdit }: AccountDataViewProps) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Box
|
||||
direction="Column"
|
||||
|
|
@ -208,7 +211,7 @@ function AccountDataView({ type, defaultContent, onEdit }: AccountDataViewProps)
|
|||
>
|
||||
<Box shrink="No" gap="300" alignItems="End">
|
||||
<Box grow="Yes" direction="Column" gap="100">
|
||||
<Text size="L400">Account Data</Text>
|
||||
<Text size="L400">{t('RoomSettings.account_data')}</Text>
|
||||
<Input
|
||||
variant="SurfaceVariant"
|
||||
size="400"
|
||||
|
|
@ -219,11 +222,11 @@ function AccountDataView({ type, defaultContent, onEdit }: AccountDataViewProps)
|
|||
/>
|
||||
</Box>
|
||||
<Button variant="Secondary" size="400" radii="300" onClick={onEdit}>
|
||||
<Text size="B400">Edit</Text>
|
||||
<Text size="B400">{t('RoomSettings.edit')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
<Box grow="Yes" direction="Column" gap="100">
|
||||
<Text size="L400">JSON Content</Text>
|
||||
<Text size="L400">{t('RoomSettings.json_content')}</Text>
|
||||
<SequenceCard variant="SurfaceVariant">
|
||||
<Scroll visibility="Always" size="300" hideTrack>
|
||||
<TextViewerContent
|
||||
|
|
@ -254,6 +257,7 @@ export function AccountDataEditor({
|
|||
submitChange,
|
||||
requestClose,
|
||||
}: AccountDataEditorProps) {
|
||||
const { t } = useTranslation();
|
||||
const [data, setData] = useState<AccountDataInfo>({
|
||||
type: type ?? '',
|
||||
content: content ?? {},
|
||||
|
|
@ -290,7 +294,7 @@ export function AccountDataEditor({
|
|||
onClick={requestClose}
|
||||
before={<Icon size="100" src={Icons.ArrowLeft} />}
|
||||
>
|
||||
<Text size="T300">Developer Tools</Text>
|
||||
<Text size="T300">{t('RoomSettings.developer_tools')}</Text>
|
||||
</Chip>
|
||||
</Box>
|
||||
<Box shrink="No">
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import {
|
|||
} from 'folds';
|
||||
import { JoinRule } from 'matrix-js-sdk';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { stopPropagation } from '../utils/keyboard';
|
||||
import { getRoomIconSrc } from '../utils/room';
|
||||
|
||||
|
|
@ -37,18 +38,20 @@ export const useJoinRuleIcons = (roomType?: string): JoinRuleIcons =>
|
|||
);
|
||||
|
||||
type JoinRuleLabels = Record<ExtendedJoinRules, string>;
|
||||
export const useRoomJoinRuleLabel = (): JoinRuleLabels =>
|
||||
useMemo(
|
||||
export const useRoomJoinRuleLabel = (): JoinRuleLabels => {
|
||||
const { t } = useTranslation();
|
||||
return useMemo(
|
||||
() => ({
|
||||
[JoinRule.Invite]: 'Invite Only',
|
||||
[JoinRule.Knock]: 'Knock & Invite',
|
||||
knock_restricted: 'Space Members or Knock',
|
||||
[JoinRule.Restricted]: 'Space Members',
|
||||
[JoinRule.Public]: 'Public',
|
||||
[JoinRule.Private]: 'Invite Only',
|
||||
[JoinRule.Invite]: t('RoomSettings.join_invite_only'),
|
||||
[JoinRule.Knock]: t('RoomSettings.join_knock_invite'),
|
||||
knock_restricted: t('RoomSettings.join_space_members_or_knock'),
|
||||
[JoinRule.Restricted]: t('RoomSettings.join_space_members'),
|
||||
[JoinRule.Public]: t('RoomSettings.join_public'),
|
||||
[JoinRule.Private]: t('RoomSettings.join_invite_only'),
|
||||
}),
|
||||
[]
|
||||
[t]
|
||||
);
|
||||
};
|
||||
|
||||
type JoinRulesSwitcherProps<T extends ExtendedJoinRules[]> = {
|
||||
icons: JoinRuleIcons;
|
||||
|
|
@ -68,6 +71,7 @@ export function JoinRulesSwitcher<T extends ExtendedJoinRules[]>({
|
|||
disabled,
|
||||
changing,
|
||||
}: JoinRulesSwitcherProps<T>) {
|
||||
const { t } = useTranslation();
|
||||
const [cords, setCords] = useState<RectCords>();
|
||||
|
||||
const handleOpenMenu: MouseEventHandler<HTMLButtonElement> = (evt) => {
|
||||
|
|
@ -138,7 +142,7 @@ export function JoinRulesSwitcher<T extends ExtendedJoinRules[]>({
|
|||
onClick={handleOpenMenu}
|
||||
disabled={disabled}
|
||||
>
|
||||
<Text size="B300">{labels[value] ?? 'Unsupported'}</Text>
|
||||
<Text size="B300">{labels[value] ?? t('RoomSettings.join_unsupported')}</Text>
|
||||
</Button>
|
||||
</PopOut>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { as, Box, Text, config, Button, Menu, Spinner } from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
ImagePack,
|
||||
ImageUsage,
|
||||
|
|
@ -33,6 +34,7 @@ export type ImagePackContentProps = {
|
|||
|
||||
export const ImagePackContent = as<'div', ImagePackContentProps>(
|
||||
({ imagePack, canEdit, onUpdate, ...props }, ref) => {
|
||||
const { t } = useTranslation();
|
||||
const useAuthentication = useMediaAuthentication();
|
||||
|
||||
const [metaEditing, setMetaEditing] = useState(false);
|
||||
|
|
@ -256,11 +258,11 @@ export const ImagePackContent = as<'div', ImagePackContentProps>(
|
|||
<Box grow="Yes" direction="Column">
|
||||
{applyState.status === AsyncStatus.Error ? (
|
||||
<Text size="T200">
|
||||
<b>Failed to apply changes! Please try again.</b>
|
||||
<b>{t('RoomSettings.failed_to_apply')}</b>
|
||||
</Text>
|
||||
) : (
|
||||
<Text size="T200">
|
||||
<b>Changes saved! Apply when ready.</b>
|
||||
<b>{t('RoomSettings.changes_saved')}</b>
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
|
|
@ -273,7 +275,7 @@ export const ImagePackContent = as<'div', ImagePackContentProps>(
|
|||
disabled={!canApplyChanges || applying}
|
||||
onClick={handleResetSavedChanges}
|
||||
>
|
||||
<Text size="B300">Reset</Text>
|
||||
<Text size="B300">{t('RoomSettings.reset')}</Text>
|
||||
</Button>
|
||||
<Button
|
||||
size="300"
|
||||
|
|
@ -283,14 +285,14 @@ export const ImagePackContent = as<'div', ImagePackContentProps>(
|
|||
before={applying && <Spinner variant="Success" fill="Solid" size="100" />}
|
||||
onClick={applyChanges}
|
||||
>
|
||||
<Text size="B300">Apply Changes</Text>
|
||||
<Text size="B300">{t('RoomSettings.apply_changes')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Menu>
|
||||
)}
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Pack</Text>
|
||||
<Text size="L400">{t('RoomSettings.pack')}</Text>
|
||||
<SequenceCard
|
||||
style={{ padding: config.space.S300 }}
|
||||
variant="SurfaceVariant"
|
||||
|
|
@ -318,8 +320,8 @@ export const ImagePackContent = as<'div', ImagePackContentProps>(
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Images Usage"
|
||||
description="Select how the images are being used: as emojis, as stickers, or as both."
|
||||
title={t('RoomSettings.images_usage')}
|
||||
description={t('RoomSettings.images_usage_desc')}
|
||||
after={
|
||||
<UsageSwitcher
|
||||
usage={currentMeta.usage}
|
||||
|
|
@ -332,7 +334,7 @@ export const ImagePackContent = as<'div', ImagePackContentProps>(
|
|||
</Box>
|
||||
{images.length === 0 && !canEdit ? null : (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Images</Text>
|
||||
<Text size="L400">{t('RoomSettings.images')}</Text>
|
||||
{canEdit && (
|
||||
<SequenceCard
|
||||
style={{ padding: config.space.S300 }}
|
||||
|
|
@ -341,8 +343,8 @@ export const ImagePackContent = as<'div', ImagePackContentProps>(
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Upload Images"
|
||||
description="Select images from your storage to upload them in pack."
|
||||
title={t('RoomSettings.upload_images')}
|
||||
description={t('RoomSettings.upload_images_desc')}
|
||||
after={
|
||||
<Button
|
||||
variant="Secondary"
|
||||
|
|
@ -353,7 +355,7 @@ export const ImagePackContent = as<'div', ImagePackContentProps>(
|
|||
outlined
|
||||
onClick={() => pickFiles('image/*')}
|
||||
>
|
||||
<Text size="B300">Select</Text>
|
||||
<Text size="B300">{t('RoomSettings.select')}</Text>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Box, IconButton, Text, Icon, Icons, Scroll, Chip } from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PackAddress } from '../../plugins/custom-emoji';
|
||||
import { Page, PageHeader, PageContent } from '../page';
|
||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||
|
|
@ -11,6 +12,7 @@ type ImagePackViewProps = {
|
|||
requestClose: () => void;
|
||||
};
|
||||
export function ImagePackView({ address, requestClose }: ImagePackViewProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const room = address && mx.getRoom(address.roomId);
|
||||
|
||||
|
|
@ -25,7 +27,7 @@ export function ImagePackView({ address, requestClose }: ImagePackViewProps) {
|
|||
onClick={requestClose}
|
||||
before={<Icon size="100" src={Icons.ArrowLeft} />}
|
||||
>
|
||||
<Text size="T300">Emojis & Stickers</Text>
|
||||
<Text size="T300">{t('RoomSettings.emojis_stickers')}</Text>
|
||||
</Chip>
|
||||
</Box>
|
||||
<Box shrink="No">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React, { FormEventHandler, ReactNode, useMemo, useState } from 'react';
|
||||
import { Badge, Box, Button, Chip, Icon, Icons, Input, Text } from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { UsageSwitcher, useUsageStr } from './UsageSwitcher';
|
||||
import { mxcUrlToHttp } from '../../utils/matrix';
|
||||
import * as css from './style.css';
|
||||
|
|
@ -30,6 +31,7 @@ export function ImageTile({
|
|||
onDeleteToggle,
|
||||
deleted,
|
||||
}: ImageTileProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const getUsageStr = useUsageStr();
|
||||
|
||||
|
|
@ -71,7 +73,7 @@ export function ImageTile({
|
|||
radii="Pill"
|
||||
onClick={() => onDeleteToggle?.(defaultShortcode)}
|
||||
>
|
||||
{deleted ? <Text size="B300">Undo</Text> : <Icon size="50" src={Icons.Delete} />}
|
||||
{deleted ? <Text size="B300">{t('RoomSettings.undo')}</Text> : <Icon size="50" src={Icons.Delete} />}
|
||||
</Chip>
|
||||
{!deleted && (
|
||||
<Chip
|
||||
|
|
@ -79,7 +81,7 @@ export function ImageTile({
|
|||
radii="Pill"
|
||||
onClick={() => onEdit?.(defaultShortcode, image)}
|
||||
>
|
||||
<Text size="B300">Edit</Text>
|
||||
<Text size="B300">{t('RoomSettings.edit')}</Text>
|
||||
</Chip>
|
||||
)}
|
||||
</Box>
|
||||
|
|
@ -120,6 +122,7 @@ export function ImageTileEdit({
|
|||
onCancel,
|
||||
onSave,
|
||||
}: ImageTileEditProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const defaultUsage = image.usage ?? packUsage;
|
||||
|
||||
|
|
@ -171,7 +174,7 @@ export function ImageTileEdit({
|
|||
<Box as="form" onSubmit={handleSubmit} direction="Column" gap="200">
|
||||
<Box direction="Column" className={css.ImagePackImageInputs}>
|
||||
<Input
|
||||
before={<Text size="L400">Shortcode:</Text>}
|
||||
before={<Text size="L400">{t('RoomSettings.shortcode')}</Text>}
|
||||
defaultValue={image.shortcode}
|
||||
name="shortcodeInput"
|
||||
variant="Secondary"
|
||||
|
|
@ -181,7 +184,7 @@ export function ImageTileEdit({
|
|||
autoFocus
|
||||
/>
|
||||
<Input
|
||||
before={<Text size="L400">Body:</Text>}
|
||||
before={<Text size="L400">{t('RoomSettings.body')}</Text>}
|
||||
defaultValue={image.body}
|
||||
name="bodyInput"
|
||||
variant="Secondary"
|
||||
|
|
@ -195,7 +198,7 @@ export function ImageTileEdit({
|
|||
</Box>
|
||||
<Box grow="Yes" />
|
||||
<Button type="submit" variant="Success" size="300" radii="300">
|
||||
<Text size="B300">Save</Text>
|
||||
<Text size="B300">{t('RoomSettings.save')}</Text>
|
||||
</Button>
|
||||
<Button
|
||||
type="reset"
|
||||
|
|
@ -205,7 +208,7 @@ export function ImageTileEdit({
|
|||
radii="300"
|
||||
onClick={() => onCancel(defaultShortcode)}
|
||||
>
|
||||
<Text size="B300">Cancel</Text>
|
||||
<Text size="B300">{t('RoomSettings.cancel')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import {
|
|||
Chip,
|
||||
} from 'folds';
|
||||
import Linkify from 'linkify-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { mxcUrlToHttp } from '../../utils/matrix';
|
||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||
import { nameInitials } from '../../utils/common';
|
||||
|
|
@ -31,13 +32,14 @@ type ImagePackAvatarProps = {
|
|||
name?: string;
|
||||
};
|
||||
function ImagePackAvatar({ url, name }: ImagePackAvatarProps) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Avatar size="500" className={ContainerColor({ variant: 'Secondary' })}>
|
||||
{url ? (
|
||||
<AvatarImage src={url} alt={name ?? 'Unknown'} />
|
||||
<AvatarImage src={url} alt={name ?? t('RoomSettings.unknown')} />
|
||||
) : (
|
||||
<AvatarFallback>
|
||||
<Text size="H2">{nameInitials(name ?? 'Unknown')}</Text>
|
||||
<Text size="H2">{nameInitials(name ?? t('RoomSettings.unknown'))}</Text>
|
||||
</AvatarFallback>
|
||||
)}
|
||||
</Avatar>
|
||||
|
|
@ -50,6 +52,7 @@ type ImagePackProfileProps = {
|
|||
onEdit?: () => void;
|
||||
};
|
||||
export function ImagePackProfile({ meta, canEdit, onEdit }: ImagePackProfileProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const useAuthentication = useMediaAuthentication();
|
||||
const avatarUrl = meta.avatar
|
||||
|
|
@ -61,7 +64,7 @@ export function ImagePackProfile({ meta, canEdit, onEdit }: ImagePackProfileProp
|
|||
<Box grow="Yes" direction="Column" gap="300">
|
||||
<Box direction="Column" gap="100">
|
||||
<Text className={BreakWord} size="H5">
|
||||
{meta.name ?? 'Unknown'}
|
||||
{meta.name ?? t('RoomSettings.unknown')}
|
||||
</Text>
|
||||
{meta.attribution && (
|
||||
<Text className={BreakWord} size="T200">
|
||||
|
|
@ -79,7 +82,7 @@ export function ImagePackProfile({ meta, canEdit, onEdit }: ImagePackProfileProp
|
|||
onClick={onEdit}
|
||||
outlined
|
||||
>
|
||||
<Text size="B300">Edit</Text>
|
||||
<Text size="B300">{t('RoomSettings.edit')}</Text>
|
||||
</Chip>
|
||||
</Box>
|
||||
)}
|
||||
|
|
@ -97,6 +100,7 @@ type ImagePackProfileEditProps = {
|
|||
onSave: (meta: PackMetaReader) => void;
|
||||
};
|
||||
export function ImagePackProfileEdit({ meta, onCancel, onSave }: ImagePackProfileEditProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const useAuthentication = useMediaAuthentication();
|
||||
const [avatar, setAvatar] = useState(meta.avatar);
|
||||
|
|
@ -147,7 +151,7 @@ export function ImagePackProfileEdit({ meta, onCancel, onSave }: ImagePackProfil
|
|||
<Box as="form" onSubmit={handleSubmit} direction="Column" gap="400">
|
||||
<Box gap="400">
|
||||
<Box grow="Yes" direction="Column" gap="100">
|
||||
<Text size="L400">Pack Avatar</Text>
|
||||
<Text size="L400">{t('RoomSettings.pack_avatar')}</Text>
|
||||
{uploadAtom ? (
|
||||
<Box gap="200" direction="Column">
|
||||
<CompactUploadCardRenderer
|
||||
|
|
@ -166,7 +170,7 @@ export function ImagePackProfileEdit({ meta, onCancel, onSave }: ImagePackProfil
|
|||
radii="300"
|
||||
onClick={() => pickFile('image/*')}
|
||||
>
|
||||
<Text size="B300">Upload</Text>
|
||||
<Text size="B300">{t('RoomSettings.upload')}</Text>
|
||||
</Button>
|
||||
{!avatar && meta.avatar && (
|
||||
<Button
|
||||
|
|
@ -177,7 +181,7 @@ export function ImagePackProfileEdit({ meta, onCancel, onSave }: ImagePackProfil
|
|||
radii="300"
|
||||
onClick={() => setAvatar(meta.avatar)}
|
||||
>
|
||||
<Text size="B300">Reset</Text>
|
||||
<Text size="B300">{t('RoomSettings.reset')}</Text>
|
||||
</Button>
|
||||
)}
|
||||
{avatar && (
|
||||
|
|
@ -189,7 +193,7 @@ export function ImagePackProfileEdit({ meta, onCancel, onSave }: ImagePackProfil
|
|||
radii="300"
|
||||
onClick={() => setAvatar(undefined)}
|
||||
>
|
||||
<Text size="B300">Remove</Text>
|
||||
<Text size="B300">{t('RoomSettings.remove')}</Text>
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
|
|
@ -200,11 +204,11 @@ export function ImagePackProfileEdit({ meta, onCancel, onSave }: ImagePackProfil
|
|||
</Box>
|
||||
</Box>
|
||||
<Box direction="Inherit" gap="100">
|
||||
<Text size="L400">Name</Text>
|
||||
<Text size="L400">{t('RoomSettings.name')}</Text>
|
||||
<Input name="nameInput" defaultValue={meta.name} variant="Secondary" radii="300" required />
|
||||
</Box>
|
||||
<Box direction="Inherit" gap="100">
|
||||
<Text size="L400">Attribution</Text>
|
||||
<Text size="L400">{t('RoomSettings.attribution')}</Text>
|
||||
<TextArea
|
||||
name="attributionTextArea"
|
||||
defaultValue={meta.attribution}
|
||||
|
|
@ -214,7 +218,7 @@ export function ImagePackProfileEdit({ meta, onCancel, onSave }: ImagePackProfil
|
|||
</Box>
|
||||
<Box gap="300">
|
||||
<Button type="submit" variant="Success" size="300" radii="300" disabled={uploadingAvatar}>
|
||||
<Text size="B300">Save</Text>
|
||||
<Text size="B300">{t('RoomSettings.save')}</Text>
|
||||
</Button>
|
||||
<Button
|
||||
type="reset"
|
||||
|
|
@ -224,7 +228,7 @@ export function ImagePackProfileEdit({ meta, onCancel, onSave }: ImagePackProfil
|
|||
size="300"
|
||||
radii="300"
|
||||
>
|
||||
<Text size="B300">Cancel</Text>
|
||||
<Text size="B300">{t('RoomSettings.cancel')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,20 @@
|
|||
import React, { MouseEventHandler, useMemo, useState } from 'react';
|
||||
import { Box, Button, config, Icon, Icons, Menu, MenuItem, PopOut, RectCords, Text } from 'folds';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ImageUsage } from '../../plugins/custom-emoji';
|
||||
import { stopPropagation } from '../../utils/keyboard';
|
||||
|
||||
export const useUsageStr = (): ((usage: ImageUsage[]) => string) => {
|
||||
const { t } = useTranslation();
|
||||
const getUsageStr = (usage: ImageUsage[]): string => {
|
||||
const sticker = usage.includes(ImageUsage.Sticker);
|
||||
const emoticon = usage.includes(ImageUsage.Emoticon);
|
||||
|
||||
if (sticker && emoticon) return 'Both';
|
||||
if (sticker) return 'Sticker';
|
||||
if (emoticon) return 'Emoji';
|
||||
return 'Both';
|
||||
if (sticker && emoticon) return t('RoomSettings.usage_both');
|
||||
if (sticker) return t('RoomSettings.usage_sticker');
|
||||
if (emoticon) return t('RoomSettings.usage_emoji');
|
||||
return t('RoomSettings.usage_both');
|
||||
};
|
||||
return getUsageStr;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
config,
|
||||
color,
|
||||
} from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Page, PageContent, PageHeader } from '../../../components/page';
|
||||
import { SequenceCard } from '../../../components/sequence-card';
|
||||
import { SequenceCardStyle } from '../styles.css';
|
||||
|
|
@ -35,6 +36,7 @@ type DeveloperToolsProps = {
|
|||
requestClose: () => void;
|
||||
};
|
||||
export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
||||
const { t } = useTranslation();
|
||||
const [developerTools, setDeveloperTools] = useSetting(settingsAtom, 'developerTools');
|
||||
const mx = useMatrixClient();
|
||||
const room = useRoom();
|
||||
|
|
@ -88,7 +90,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
<Box grow="Yes" gap="200">
|
||||
<Box grow="Yes" alignItems="Center" gap="200">
|
||||
<Text size="H3" truncate>
|
||||
Developer Tools
|
||||
{t('RoomSettings.developer_tools')}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box shrink="No">
|
||||
|
|
@ -103,7 +105,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
<PageContent>
|
||||
<Box direction="Column" gap="700">
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Options</Text>
|
||||
<Text size="L400">{t('RoomSettings.options')}</Text>
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
|
|
@ -111,7 +113,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Enable Developer Tools"
|
||||
title={t('RoomSettings.enable_developer_tools')}
|
||||
after={
|
||||
<Switch
|
||||
variant="Primary"
|
||||
|
|
@ -129,8 +131,8 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Room ID"
|
||||
description={`Copy room ID to clipboard. ("${room.roomId}")`}
|
||||
title={t('RoomSettings.room_id')}
|
||||
description={`${t('RoomSettings.room_id_desc')} ("${room.roomId}")`}
|
||||
after={
|
||||
<Button
|
||||
onClick={() => copyToClipboard(room.roomId ?? '<NO_ROOM_ID_FOUND>')}
|
||||
|
|
@ -140,7 +142,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
radii="300"
|
||||
outlined
|
||||
>
|
||||
<Text size="B300">Copy</Text>
|
||||
<Text size="B300">{t('RoomSettings.copy')}</Text>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
|
|
@ -150,7 +152,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
|
||||
{developerTools && (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Data</Text>
|
||||
<Text size="L400">{t('RoomSettings.data')}</Text>
|
||||
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
|
|
@ -159,8 +161,8 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="New Message Event"
|
||||
description="Create and send a new message event within the room."
|
||||
title={t('RoomSettings.new_message_event')}
|
||||
description={t('RoomSettings.new_message_event_desc')}
|
||||
after={
|
||||
<Button
|
||||
onClick={() => setComposeEvent({})}
|
||||
|
|
@ -170,7 +172,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
radii="300"
|
||||
outlined
|
||||
>
|
||||
<Text size="B300">Compose</Text>
|
||||
<Text size="B300">{t('RoomSettings.compose')}</Text>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
|
|
@ -182,8 +184,8 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Room State"
|
||||
description="State events of the room."
|
||||
title={t('RoomSettings.room_state')}
|
||||
description={t('RoomSettings.room_state_desc')}
|
||||
after={
|
||||
<Button
|
||||
onClick={() => setExpandState(!expandState)}
|
||||
|
|
@ -200,15 +202,15 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
/>
|
||||
}
|
||||
>
|
||||
<Text size="B300">{expandState ? 'Collapse' : 'Expand'}</Text>
|
||||
<Text size="B300">{expandState ? t('RoomSettings.collapse') : t('RoomSettings.expand')}</Text>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
{expandState && (
|
||||
<Box direction="Column" gap="100">
|
||||
<Box justifyContent="SpaceBetween">
|
||||
<Text size="L400">Events</Text>
|
||||
<Text size="L400">Total: {roomState.size}</Text>
|
||||
<Text size="L400">{t('RoomSettings.events')}</Text>
|
||||
<Text size="L400">{t('RoomSettings.total', { count: roomState.size })}</Text>
|
||||
</Box>
|
||||
<CutoutCard>
|
||||
<MenuItem
|
||||
|
|
@ -221,7 +223,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
Add New
|
||||
{t('RoomSettings.add_new')}
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
|
|
@ -275,7 +277,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
Add New
|
||||
{t('RoomSettings.add_new')}
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
|
|
@ -298,7 +300,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
{stateKey ? `"${stateKey}"` : 'Default'}
|
||||
{stateKey ? `"${stateKey}"` : t('RoomSettings.default_key')}
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
|
|
@ -319,8 +321,8 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Account Data"
|
||||
description="Private personalization data stored within room."
|
||||
title={t('RoomSettings.account_data')}
|
||||
description={t('RoomSettings.account_data_desc')}
|
||||
after={
|
||||
<Button
|
||||
onClick={() => setExpandAccountData(!expandAccountData)}
|
||||
|
|
@ -337,15 +339,15 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
/>
|
||||
}
|
||||
>
|
||||
<Text size="B300">{expandAccountData ? 'Collapse' : 'Expand'}</Text>
|
||||
<Text size="B300">{expandAccountData ? t('RoomSettings.collapse') : t('RoomSettings.expand')}</Text>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
{expandAccountData && (
|
||||
<Box direction="Column" gap="100">
|
||||
<Box justifyContent="SpaceBetween">
|
||||
<Text size="L400">Events</Text>
|
||||
<Text size="L400">Total: {accountData.size}</Text>
|
||||
<Text size="L400">{t('RoomSettings.events')}</Text>
|
||||
<Text size="L400">{t('RoomSettings.total', { count: accountData.size })}</Text>
|
||||
</Box>
|
||||
<CutoutCard>
|
||||
<MenuItem
|
||||
|
|
@ -358,7 +360,7 @@ export function DeveloperTools({ requestClose }: DeveloperToolsProps) {
|
|||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="T200" truncate>
|
||||
Add New
|
||||
{t('RoomSettings.add_new')}
|
||||
</Text>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import React, { useCallback, useRef, useState, FormEventHandler, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { MatrixError } from 'matrix-js-sdk';
|
||||
import {
|
||||
Box,
|
||||
|
|
@ -31,6 +32,7 @@ export type SendRoomEventProps = {
|
|||
requestClose: () => void;
|
||||
};
|
||||
export function SendRoomEvent({ type, stateKey, requestClose }: SendRoomEventProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const room = useRoom();
|
||||
const alive = useAlive();
|
||||
|
|
@ -114,7 +116,7 @@ export function SendRoomEvent({ type, stateKey, requestClose }: SendRoomEventPro
|
|||
onClick={requestClose}
|
||||
before={<Icon size="100" src={Icons.ArrowLeft} />}
|
||||
>
|
||||
<Text size="T300">Developer Tools</Text>
|
||||
<Text size="T300">{t('RoomSettings.developer_tools')}</Text>
|
||||
</Chip>
|
||||
</Box>
|
||||
<Box shrink="No">
|
||||
|
|
@ -135,7 +137,7 @@ export function SendRoomEvent({ type, stateKey, requestClose }: SendRoomEventPro
|
|||
aria-disabled={submitting}
|
||||
>
|
||||
<Box shrink="No" direction="Column" gap="100">
|
||||
<Text size="L400">{composeStateEvent ? 'State Event Type' : 'Message Event Type'}</Text>
|
||||
<Text size="L400">{composeStateEvent ? t('RoomSettings.state_event_type') : t('RoomSettings.message_event_type')}</Text>
|
||||
<Box gap="300">
|
||||
<Box grow="Yes" direction="Column">
|
||||
<Input
|
||||
|
|
@ -156,7 +158,7 @@ export function SendRoomEvent({ type, stateKey, requestClose }: SendRoomEventPro
|
|||
disabled={submitting}
|
||||
before={submitting && <Spinner variant="Primary" fill="Solid" size="300" />}
|
||||
>
|
||||
<Text size="B400">Send</Text>
|
||||
<Text size="B400">{t('RoomSettings.send')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
|
|
@ -168,7 +170,7 @@ export function SendRoomEvent({ type, stateKey, requestClose }: SendRoomEventPro
|
|||
</Box>
|
||||
{composeStateEvent && (
|
||||
<Box shrink="No" direction="Column" gap="100">
|
||||
<Text size="L400">State Key (Optional)</Text>
|
||||
<Text size="L400">{t('RoomSettings.state_key_optional')}</Text>
|
||||
<Input
|
||||
variant="Background"
|
||||
name="stateKeyInput"
|
||||
|
|
@ -181,7 +183,7 @@ export function SendRoomEvent({ type, stateKey, requestClose }: SendRoomEventPro
|
|||
)}
|
||||
<Box grow="Yes" direction="Column" gap="100">
|
||||
<Box shrink="No">
|
||||
<Text size="L400">JSON Content</Text>
|
||||
<Text size="L400">{t('RoomSettings.json_content')}</Text>
|
||||
</Box>
|
||||
<TextAreaComponent
|
||||
ref={textAreaRef}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import {
|
|||
Spinner,
|
||||
Button,
|
||||
} from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { MatrixError } from 'matrix-js-sdk';
|
||||
import { Page, PageHeader } from '../../../components/page';
|
||||
import { SequenceCard } from '../../../components/sequence-card';
|
||||
|
|
@ -41,6 +42,7 @@ type StateEventEditProps = {
|
|||
requestClose: () => void;
|
||||
};
|
||||
function StateEventEdit({ type, stateKey, content, requestClose }: StateEventEditProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const room = useRoom();
|
||||
const alive = useAlive();
|
||||
|
|
@ -118,7 +120,7 @@ function StateEventEdit({ type, stateKey, content, requestClose }: StateEventEdi
|
|||
aria-disabled={submitting}
|
||||
>
|
||||
<Box shrink="No" direction="Column" gap="100">
|
||||
<Text size="L400">State Event</Text>
|
||||
<Text size="L400">{t('RoomSettings.state_event')}</Text>
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
|
|
@ -138,7 +140,7 @@ function StateEventEdit({ type, stateKey, content, requestClose }: StateEventEdi
|
|||
disabled={submitting}
|
||||
before={submitting && <Spinner variant="Primary" fill="Solid" size="300" />}
|
||||
>
|
||||
<Text size="B300">Save</Text>
|
||||
<Text size="B300">{t('RoomSettings.save')}</Text>
|
||||
</Button>
|
||||
<Button
|
||||
variant="Secondary"
|
||||
|
|
@ -148,7 +150,7 @@ function StateEventEdit({ type, stateKey, content, requestClose }: StateEventEdi
|
|||
onClick={requestClose}
|
||||
disabled={submitting}
|
||||
>
|
||||
<Text size="B300">Cancel</Text>
|
||||
<Text size="B300">{t('RoomSettings.cancel')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
}
|
||||
|
|
@ -163,7 +165,7 @@ function StateEventEdit({ type, stateKey, content, requestClose }: StateEventEdi
|
|||
</Box>
|
||||
<Box grow="Yes" direction="Column" gap="100">
|
||||
<Box shrink="No">
|
||||
<Text size="L400">JSON Content</Text>
|
||||
<Text size="L400">{t('RoomSettings.json_content')}</Text>
|
||||
</Box>
|
||||
<TextAreaComponent
|
||||
ref={textAreaRef}
|
||||
|
|
@ -194,12 +196,13 @@ type StateEventViewProps = {
|
|||
onEditContent?: (content: object) => void;
|
||||
};
|
||||
function StateEventView({ content, eventJSONStr, onEditContent }: StateEventViewProps) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Box direction="Column" style={{ padding: config.space.S400 }} gap="400">
|
||||
<Box grow="Yes" direction="Column" gap="100">
|
||||
<Box gap="200" alignItems="End">
|
||||
<Box grow="Yes">
|
||||
<Text size="L400">State Event</Text>
|
||||
<Text size="L400">{t('RoomSettings.state_event')}</Text>
|
||||
</Box>
|
||||
{onEditContent && (
|
||||
<Box shrink="No" gap="200">
|
||||
|
|
@ -210,7 +213,7 @@ function StateEventView({ content, eventJSONStr, onEditContent }: StateEventView
|
|||
outlined
|
||||
onClick={() => onEditContent(content)}
|
||||
>
|
||||
<Text size="B300">Edit</Text>
|
||||
<Text size="B300">{t('RoomSettings.edit')}</Text>
|
||||
</Chip>
|
||||
</Box>
|
||||
)}
|
||||
|
|
@ -241,6 +244,7 @@ export type StateEventEditorProps = StateEventInfo & {
|
|||
};
|
||||
|
||||
export function StateEventEditor({ type, stateKey, requestClose }: StateEventEditorProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const room = useRoom();
|
||||
const stateEvent = useStateEvent(room, type as unknown as StateEvent, stateKey);
|
||||
|
|
@ -271,7 +275,7 @@ export function StateEventEditor({ type, stateKey, requestClose }: StateEventEdi
|
|||
onClick={requestClose}
|
||||
before={<Icon size="100" src={Icons.ArrowLeft} />}
|
||||
>
|
||||
<Text size="T300">Developer Tools</Text>
|
||||
<Text size="T300">{t('RoomSettings.developer_tools')}</Text>
|
||||
</Chip>
|
||||
</Box>
|
||||
<Box shrink="No">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Box, Icon, IconButton, Icons, Scroll, Text } from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Page, PageContent, PageHeader } from '../../../components/page';
|
||||
import { ImagePack } from '../../../plugins/custom-emoji';
|
||||
import { ImagePackView } from '../../../components/image-pack-view';
|
||||
|
|
@ -9,6 +10,7 @@ type EmojisStickersProps = {
|
|||
requestClose: () => void;
|
||||
};
|
||||
export function EmojisStickers({ requestClose }: EmojisStickersProps) {
|
||||
const { t } = useTranslation();
|
||||
const [imagePack, setImagePack] = useState<ImagePack>();
|
||||
|
||||
const handleImagePackViewClose = () => {
|
||||
|
|
@ -25,7 +27,7 @@ export function EmojisStickers({ requestClose }: EmojisStickersProps) {
|
|||
<Box grow="Yes" gap="200">
|
||||
<Box grow="Yes" alignItems="Center" gap="200">
|
||||
<Text size="H3" truncate>
|
||||
Emojis & Stickers
|
||||
{t('RoomSettings.emojis_stickers')}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box shrink="No">
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import {
|
|||
IconButton,
|
||||
Menu,
|
||||
} from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { MatrixError } from 'matrix-js-sdk';
|
||||
import { SequenceCard } from '../../../components/sequence-card';
|
||||
import {
|
||||
|
|
@ -46,6 +47,7 @@ type CreatePackTileProps = {
|
|||
roomId: string;
|
||||
};
|
||||
function CreatePackTile({ packs, roomId }: CreatePackTileProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const alive = useAlive();
|
||||
|
||||
|
|
@ -97,8 +99,8 @@ function CreatePackTile({ packs, roomId }: CreatePackTileProps) {
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="New Pack"
|
||||
description="Add your own emoji and sticker pack to use in room."
|
||||
title={t('RoomSettings.new_pack')}
|
||||
description={t('RoomSettings.new_pack_desc')}
|
||||
>
|
||||
<Box
|
||||
style={{ marginTop: config.space.S200 }}
|
||||
|
|
@ -108,7 +110,7 @@ function CreatePackTile({ packs, roomId }: CreatePackTileProps) {
|
|||
alignItems="End"
|
||||
>
|
||||
<Box direction="Column" gap="100" grow="Yes">
|
||||
<Text size="L400">Name</Text>
|
||||
<Text size="L400">{t('RoomSettings.name')}</Text>
|
||||
<Input
|
||||
name="nameInput"
|
||||
required
|
||||
|
|
@ -130,7 +132,7 @@ function CreatePackTile({ packs, roomId }: CreatePackTileProps) {
|
|||
disabled={creating}
|
||||
before={creating && <Spinner size="200" variant="Success" fill="Solid" />}
|
||||
>
|
||||
<Text size="B400">Create</Text>
|
||||
<Text size="B400">{t('RoomSettings.create')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</SettingTile>
|
||||
|
|
@ -142,6 +144,7 @@ type RoomPacksProps = {
|
|||
onViewPack: (imagePack: ImagePack) => void;
|
||||
};
|
||||
export function RoomPacks({ onViewPack }: RoomPacksProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const useAuthentication = useMediaAuthentication();
|
||||
const room = useRoom();
|
||||
|
|
@ -255,7 +258,7 @@ export function RoomPacks({ onViewPack }: RoomPacksProps) {
|
|||
outlined
|
||||
onClick={() => onViewPack(pack)}
|
||||
>
|
||||
<Text size="B300">View</Text>
|
||||
<Text size="B300">{t('RoomSettings.view')}</Text>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
|
@ -267,7 +270,7 @@ export function RoomPacks({ onViewPack }: RoomPacksProps) {
|
|||
return (
|
||||
<>
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Packs</Text>
|
||||
<Text size="L400">{t('RoomSettings.packs')}</Text>
|
||||
{canEdit && <CreatePackTile roomId={room.roomId} packs={packs} />}
|
||||
{packs.map(renderPack)}
|
||||
{packs.length === 0 && (
|
||||
|
|
@ -288,10 +291,10 @@ export function RoomPacks({ onViewPack }: RoomPacksProps) {
|
|||
}}
|
||||
>
|
||||
<Text size="H5" align="Center">
|
||||
No Packs
|
||||
{t('RoomSettings.no_packs')}
|
||||
</Text>
|
||||
<Text size="T200" align="Center">
|
||||
There are no emoji or sticker packs to display at the moment.
|
||||
{t('RoomSettings.no_packs_desc')}
|
||||
</Text>
|
||||
</Box>
|
||||
</SequenceCard>
|
||||
|
|
@ -315,11 +318,11 @@ export function RoomPacks({ onViewPack }: RoomPacksProps) {
|
|||
<Box grow="Yes" direction="Column">
|
||||
{applyState.status === AsyncStatus.Error ? (
|
||||
<Text size="T200">
|
||||
<b>Failed to remove packs! Please try again.</b>
|
||||
<b>{t('RoomSettings.failed_to_remove_packs')}</b>
|
||||
</Text>
|
||||
) : (
|
||||
<Text size="T200">
|
||||
<b>Delete selected packs. ({removedPacks.length} selected)</b>
|
||||
<b>{t('RoomSettings.delete_selected_packs', { count: removedPacks.length })}</b>
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
|
|
@ -332,7 +335,7 @@ export function RoomPacks({ onViewPack }: RoomPacksProps) {
|
|||
disabled={applyingChanges}
|
||||
onClick={handleCancelChanges}
|
||||
>
|
||||
<Text size="B300">Cancel</Text>
|
||||
<Text size="B300">{t('RoomSettings.cancel')}</Text>
|
||||
</Button>
|
||||
<Button
|
||||
size="300"
|
||||
|
|
@ -342,7 +345,7 @@ export function RoomPacks({ onViewPack }: RoomPacksProps) {
|
|||
before={applyingChanges && <Spinner variant="Critical" fill="Solid" size="100" />}
|
||||
onClick={handleApplyChanges}
|
||||
>
|
||||
<Text size="B300">Delete</Text>
|
||||
<Text size="B300">{t('RoomSettings.delete')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import {
|
|||
toRem,
|
||||
} from 'folds';
|
||||
import { MatrixError } from 'matrix-js-sdk';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SettingTile } from '../../../components/setting-tile';
|
||||
import { SequenceCard } from '../../../components/sequence-card';
|
||||
import { SequenceCardStyle } from '../../room-settings/styles.css';
|
||||
|
|
@ -39,6 +40,7 @@ type RoomPublishedAddressesProps = {
|
|||
};
|
||||
|
||||
export function RoomPublishedAddresses({ permissions }: RoomPublishedAddressesProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const room = useRoom();
|
||||
|
||||
|
|
@ -61,19 +63,17 @@ export function RoomPublishedAddresses({ permissions }: RoomPublishedAddressesPr
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Published Addresses"
|
||||
title={t('RoomSettings.published_addresses')}
|
||||
description={
|
||||
<span>
|
||||
If access is <b>Public</b>, Published addresses will be used to join by anyone.
|
||||
</span>
|
||||
<span dangerouslySetInnerHTML={{ __html: t('RoomSettings.published_addresses_desc') }} />
|
||||
}
|
||||
/>
|
||||
<CutoutCard variant="Surface" style={{ padding: config.space.S300 }}>
|
||||
{publishedAliases.length === 0 ? (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">No Addresses</Text>
|
||||
<Text size="L400">{t('RoomSettings.no_addresses')}</Text>
|
||||
<Text size="T200">
|
||||
To publish an address, it needs to be set as a local address first
|
||||
{t('RoomSettings.no_addresses_hint')}
|
||||
</Text>
|
||||
</Box>
|
||||
) : (
|
||||
|
|
@ -86,7 +86,7 @@ export function RoomPublishedAddresses({ permissions }: RoomPublishedAddressesPr
|
|||
</Text>
|
||||
{alias === canonicalAlias && (
|
||||
<Badge variant="Success" fill="Solid" size="500">
|
||||
<Text size="L400">Main</Text>
|
||||
<Text size="L400">{t('RoomSettings.main')}</Text>
|
||||
</Badge>
|
||||
)}
|
||||
</Box>
|
||||
|
|
@ -100,7 +100,7 @@ export function RoomPublishedAddresses({ permissions }: RoomPublishedAddressesPr
|
|||
disabled={loading}
|
||||
onClick={() => setMain(undefined)}
|
||||
>
|
||||
<Text size="B300">Unset Main</Text>
|
||||
<Text size="B300">{t('RoomSettings.unset_main')}</Text>
|
||||
</Chip>
|
||||
) : (
|
||||
<Chip
|
||||
|
|
@ -110,7 +110,7 @@ export function RoomPublishedAddresses({ permissions }: RoomPublishedAddressesPr
|
|||
disabled={loading}
|
||||
onClick={() => setMain(alias)}
|
||||
>
|
||||
<Text size="B300">Set Main</Text>
|
||||
<Text size="B300">{t('RoomSettings.set_main')}</Text>
|
||||
</Chip>
|
||||
)}
|
||||
</Box>
|
||||
|
|
@ -131,6 +131,7 @@ export function RoomPublishedAddresses({ permissions }: RoomPublishedAddressesPr
|
|||
}
|
||||
|
||||
function LocalAddressInput({ addLocalAlias }: { addLocalAlias: (alias: string) => Promise<void> }) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const userId = mx.getSafeUserId();
|
||||
const server = getMxIdServer(userId);
|
||||
|
|
@ -183,14 +184,14 @@ function LocalAddressInput({ addLocalAlias }: { addLocalAlias: (alias: string) =
|
|||
disabled={adding}
|
||||
before={adding && <Spinner size="100" variant="Success" fill="Solid" />}
|
||||
>
|
||||
<Text size="B400">Save</Text>
|
||||
<Text size="B400">{t('RoomSettings.save')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
{addState.status === AsyncStatus.Error && (
|
||||
<Text style={{ color: color.Critical.Main }} size="T200">
|
||||
{(addState.error as MatrixError).httpStatus === 409
|
||||
? 'Address is already in use!'
|
||||
? t('RoomSettings.address_in_use')
|
||||
: (addState.error as MatrixError).message}
|
||||
</Text>
|
||||
)}
|
||||
|
|
@ -207,6 +208,7 @@ function LocalAddressesList({
|
|||
removeLocalAlias: (alias: string) => Promise<void>;
|
||||
canEditCanonical?: boolean;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const room = useRoom();
|
||||
const alive = useAlive();
|
||||
|
||||
|
|
@ -271,7 +273,7 @@ function LocalAddressesList({
|
|||
{selectedAliases.length > 0 && (
|
||||
<Box gap="200">
|
||||
<Box grow="Yes">
|
||||
<Text size="L400">{selectedAliases.length} Selected</Text>
|
||||
<Text size="L400">{t('RoomSettings.selected_count', { count: selectedAliases.length })}</Text>
|
||||
</Box>
|
||||
<Box shrink="No" gap="Inherit">
|
||||
{canEditCanonical &&
|
||||
|
|
@ -287,7 +289,7 @@ function LocalAddressesList({
|
|||
)
|
||||
}
|
||||
>
|
||||
<Text size="B300">Unpublish</Text>
|
||||
<Text size="B300">{t('RoomSettings.unpublish')}</Text>
|
||||
</Chip>
|
||||
) : (
|
||||
<Chip
|
||||
|
|
@ -301,7 +303,7 @@ function LocalAddressesList({
|
|||
)
|
||||
}
|
||||
>
|
||||
<Text size="B300">Publish</Text>
|
||||
<Text size="B300">{t('RoomSettings.publish')}</Text>
|
||||
</Chip>
|
||||
))}
|
||||
<Chip
|
||||
|
|
@ -315,7 +317,7 @@ function LocalAddressesList({
|
|||
)
|
||||
}
|
||||
>
|
||||
<Text size="B300">Delete</Text>
|
||||
<Text size="B300">{t('RoomSettings.delete')}</Text>
|
||||
</Chip>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
@ -343,7 +345,7 @@ function LocalAddressesList({
|
|||
<Box shrink="No" gap="100">
|
||||
{published && (
|
||||
<Badge variant="Success" fill="Soft" size="500">
|
||||
<Text size="L400">Published</Text>
|
||||
<Text size="L400">{t('RoomSettings.published')}</Text>
|
||||
</Badge>
|
||||
)}
|
||||
</Box>
|
||||
|
|
@ -360,6 +362,7 @@ function LocalAddressesList({
|
|||
}
|
||||
|
||||
export function RoomLocalAddresses({ permissions }: { permissions: RoomPermissionsAPI }) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const room = useRoom();
|
||||
|
||||
|
|
@ -380,8 +383,8 @@ export function RoomLocalAddresses({ permissions }: { permissions: RoomPermissio
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Local Addresses"
|
||||
description="Set local address so users can join through your homeserver."
|
||||
title={t('RoomSettings.local_addresses')}
|
||||
description={t('RoomSettings.local_addresses_desc')}
|
||||
after={
|
||||
<Button
|
||||
type="button"
|
||||
|
|
@ -396,7 +399,7 @@ export function RoomLocalAddresses({ permissions }: { permissions: RoomPermissio
|
|||
}
|
||||
>
|
||||
<Text as="span" size="B300" truncate>
|
||||
{expand ? 'Collapse' : 'Expand'}
|
||||
{expand ? t('RoomSettings.collapse') : t('RoomSettings.expand')}
|
||||
</Text>
|
||||
</Button>
|
||||
}
|
||||
|
|
@ -406,13 +409,13 @@ export function RoomLocalAddresses({ permissions }: { permissions: RoomPermissio
|
|||
{localAliasesState.status === AsyncStatus.Loading && (
|
||||
<Box gap="100">
|
||||
<Spinner variant="Secondary" size="100" />
|
||||
<Text size="T200">Loading...</Text>
|
||||
<Text size="T200">{t('RoomSettings.loading')}</Text>
|
||||
</Box>
|
||||
)}
|
||||
{localAliasesState.status === AsyncStatus.Success &&
|
||||
(localAliasesState.data.length === 0 ? (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">No Addresses</Text>
|
||||
<Text size="L400">{t('RoomSettings.no_addresses')}</Text>
|
||||
</Box>
|
||||
) : (
|
||||
<LocalAddressesList
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import {
|
|||
import React, { useCallback, useState } from 'react';
|
||||
import { MatrixError } from 'matrix-js-sdk';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SequenceCard } from '../../../components/sequence-card';
|
||||
import { SequenceCardStyle } from '../../room-settings/styles.css';
|
||||
import { SettingTile } from '../../../components/setting-tile';
|
||||
|
|
@ -35,6 +36,7 @@ type RoomEncryptionProps = {
|
|||
permissions: RoomPermissionsAPI;
|
||||
};
|
||||
export function RoomEncryption({ permissions }: RoomEncryptionProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const room = useRoom();
|
||||
|
||||
|
|
@ -69,16 +71,16 @@ export function RoomEncryption({ permissions }: RoomEncryptionProps) {
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Room Encryption"
|
||||
title={t('RoomSettings.room_encryption')}
|
||||
description={
|
||||
enabled
|
||||
? 'Messages in this room are protected by end-to-end encryption.'
|
||||
: 'Once enabled, encryption cannot be disabled!'
|
||||
? t('RoomSettings.encryption_enabled_desc')
|
||||
: t('RoomSettings.encryption_disabled_desc')
|
||||
}
|
||||
after={
|
||||
enabled ? (
|
||||
<Badge size="500" variant="Success" fill="Solid" radii="300">
|
||||
<Text size="L400">Enabled</Text>
|
||||
<Text size="L400">{t('RoomSettings.enabled')}</Text>
|
||||
</Badge>
|
||||
) : (
|
||||
<Button
|
||||
|
|
@ -90,7 +92,7 @@ export function RoomEncryption({ permissions }: RoomEncryptionProps) {
|
|||
onClick={() => setPrompt(true)}
|
||||
before={enabling && <Spinner size="100" variant="Primary" fill="Solid" />}
|
||||
>
|
||||
<Text size="B300">Enable</Text>
|
||||
<Text size="B300">{t('RoomSettings.enable')}</Text>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
|
@ -121,7 +123,7 @@ export function RoomEncryption({ permissions }: RoomEncryptionProps) {
|
|||
size="500"
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="H4">Enable Encryption</Text>
|
||||
<Text size="H4">{t('RoomSettings.enable_encryption')}</Text>
|
||||
</Box>
|
||||
<IconButton size="300" onClick={() => setPrompt(false)} radii="300">
|
||||
<Icon src={Icons.Cross} />
|
||||
|
|
@ -129,10 +131,10 @@ export function RoomEncryption({ permissions }: RoomEncryptionProps) {
|
|||
</Header>
|
||||
<Box style={{ padding: config.space.S400 }} direction="Column" gap="400">
|
||||
<Text priority="400">
|
||||
Are you sure? Once enabled, encryption cannot be disabled!
|
||||
{t('RoomSettings.enable_encryption_confirm')}
|
||||
</Text>
|
||||
<Button type="submit" variant="Primary" onClick={handleEnable}>
|
||||
<Text size="B400">Enable E2E Encryption</Text>
|
||||
<Text size="B400">{t('RoomSettings.enable_e2e_encryption')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</Dialog>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import {
|
|||
import { HistoryVisibility, MatrixError } from 'matrix-js-sdk';
|
||||
import { RoomHistoryVisibilityEventContent } from 'matrix-js-sdk/lib/types';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SequenceCard } from '../../../components/sequence-card';
|
||||
import { SequenceCardStyle } from '../../room-settings/styles.css';
|
||||
import { SettingTile } from '../../../components/setting-tile';
|
||||
|
|
@ -26,16 +27,18 @@ import { useStateEvent } from '../../../hooks/useStateEvent';
|
|||
import { stopPropagation } from '../../../utils/keyboard';
|
||||
import { RoomPermissionsAPI } from '../../../hooks/useRoomPermissions';
|
||||
|
||||
const useVisibilityStr = () =>
|
||||
useMemo(
|
||||
const useVisibilityStr = () => {
|
||||
const { t } = useTranslation();
|
||||
return useMemo(
|
||||
() => ({
|
||||
[HistoryVisibility.Invited]: 'After Invite',
|
||||
[HistoryVisibility.Joined]: 'After Join',
|
||||
[HistoryVisibility.Shared]: 'All Messages',
|
||||
[HistoryVisibility.WorldReadable]: 'All Messages (Guests)',
|
||||
[HistoryVisibility.Invited]: t('RoomSettings.visibility_after_invite'),
|
||||
[HistoryVisibility.Joined]: t('RoomSettings.visibility_after_join'),
|
||||
[HistoryVisibility.Shared]: t('RoomSettings.visibility_all_messages'),
|
||||
[HistoryVisibility.WorldReadable]: t('RoomSettings.visibility_all_messages_guests'),
|
||||
}),
|
||||
[]
|
||||
[t]
|
||||
);
|
||||
};
|
||||
|
||||
const useVisibilityMenu = () =>
|
||||
useMemo(
|
||||
|
|
@ -52,6 +55,7 @@ type RoomHistoryVisibilityProps = {
|
|||
permissions: RoomPermissionsAPI;
|
||||
};
|
||||
export function RoomHistoryVisibility({ permissions }: RoomHistoryVisibilityProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const room = useRoom();
|
||||
|
||||
|
|
@ -96,8 +100,8 @@ export function RoomHistoryVisibility({ permissions }: RoomHistoryVisibilityProp
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Message History Visibility"
|
||||
description="Changes to history visibility will only apply to future messages. The visibility of existing history will have no effect."
|
||||
title={t('RoomSettings.history_visibility')}
|
||||
description={t('RoomSettings.history_visibility_desc')}
|
||||
after={
|
||||
<PopOut
|
||||
anchor={menuAnchor}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React, { useCallback, useMemo } from 'react';
|
||||
import { color, Text } from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { JoinRule, MatrixError, RestrictedAllowType } from 'matrix-js-sdk';
|
||||
import { RoomJoinRulesEventContent } from 'matrix-js-sdk/lib/types';
|
||||
import { useAtomValue } from 'jotai';
|
||||
|
|
@ -41,6 +42,7 @@ type RoomJoinRulesProps = {
|
|||
permissions: RoomPermissionsAPI;
|
||||
};
|
||||
export function RoomJoinRules({ permissions }: RoomJoinRulesProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const room = useRoom();
|
||||
const allowKnockRestricted = knockRestrictedSupported(room.getVersion());
|
||||
|
|
@ -127,11 +129,11 @@ export function RoomJoinRules({ permissions }: RoomJoinRulesProps) {
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title={room.isSpaceRoom() ? 'Space Access' : 'Room Access'}
|
||||
title={room.isSpaceRoom() ? t('RoomSettings.space_access') : t('RoomSettings.room_access')}
|
||||
description={
|
||||
room.isSpaceRoom()
|
||||
? 'Change how people can join the space.'
|
||||
: 'Change how people can join the room.'
|
||||
? t('RoomSettings.space_access_desc')
|
||||
: t('RoomSettings.room_access_desc')
|
||||
}
|
||||
after={
|
||||
<JoinRulesSwitcher
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import {
|
|||
} from 'folds';
|
||||
import React, { FormEventHandler, useCallback, useMemo, useState } from 'react';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Linkify from 'linkify-react';
|
||||
import classNames from 'classnames';
|
||||
import { JoinRule, MatrixError } from 'matrix-js-sdk';
|
||||
|
|
@ -59,6 +60,7 @@ export function RoomProfileEdit({
|
|||
topic,
|
||||
onClose,
|
||||
}: RoomProfileEditProps) {
|
||||
const { t } = useTranslation();
|
||||
const room = useRoom();
|
||||
const mx = useMatrixClient();
|
||||
const alive = useAlive();
|
||||
|
|
@ -140,7 +142,7 @@ export function RoomProfileEdit({
|
|||
<Box as="form" onSubmit={handleSubmit} direction="Column" gap="400">
|
||||
<Box gap="400">
|
||||
<Box grow="Yes" direction="Column" gap="100">
|
||||
<Text size="L400">Avatar</Text>
|
||||
<Text size="L400">{t('RoomSettings.avatar')}</Text>
|
||||
{uploadAtom ? (
|
||||
<Box gap="200" direction="Column">
|
||||
<CompactUploadCardRenderer
|
||||
|
|
@ -160,7 +162,7 @@ export function RoomProfileEdit({
|
|||
disabled={!canEditAvatar || submitting}
|
||||
onClick={() => pickFile('image/*')}
|
||||
>
|
||||
<Text size="B300">Upload</Text>
|
||||
<Text size="B300">{t('RoomSettings.upload')}</Text>
|
||||
</Button>
|
||||
{!roomAvatar && avatar && (
|
||||
<Button
|
||||
|
|
@ -172,7 +174,7 @@ export function RoomProfileEdit({
|
|||
disabled={!canEditAvatar || submitting}
|
||||
onClick={() => setRoomAvatar(avatar)}
|
||||
>
|
||||
<Text size="B300">Reset</Text>
|
||||
<Text size="B300">{t('RoomSettings.reset')}</Text>
|
||||
</Button>
|
||||
)}
|
||||
{roomAvatar && (
|
||||
|
|
@ -185,7 +187,7 @@ export function RoomProfileEdit({
|
|||
disabled={!canEditAvatar || submitting}
|
||||
onClick={() => setRoomAvatar(undefined)}
|
||||
>
|
||||
<Text size="B300">Remove</Text>
|
||||
<Text size="B300">{t('RoomSettings.remove')}</Text>
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
|
|
@ -210,7 +212,7 @@ export function RoomProfileEdit({
|
|||
</Box>
|
||||
</Box>
|
||||
<Box direction="Inherit" gap="100">
|
||||
<Text size="L400">Name</Text>
|
||||
<Text size="L400">{t('RoomSettings.name')}</Text>
|
||||
<Input
|
||||
name="nameInput"
|
||||
defaultValue={name}
|
||||
|
|
@ -220,7 +222,7 @@ export function RoomProfileEdit({
|
|||
/>
|
||||
</Box>
|
||||
<Box direction="Inherit" gap="100">
|
||||
<Text size="L400">Topic</Text>
|
||||
<Text size="L400">{t('RoomSettings.topic')}</Text>
|
||||
<TextArea
|
||||
name="topicTextArea"
|
||||
defaultValue={topic}
|
||||
|
|
@ -243,7 +245,7 @@ export function RoomProfileEdit({
|
|||
disabled={uploadingAvatar || submitting}
|
||||
before={submitting && <Spinner size="100" variant="Success" fill="Solid" />}
|
||||
>
|
||||
<Text size="B300">Save</Text>
|
||||
<Text size="B300">{t('RoomSettings.save')}</Text>
|
||||
</Button>
|
||||
<Button
|
||||
type="reset"
|
||||
|
|
@ -253,7 +255,7 @@ export function RoomProfileEdit({
|
|||
size="300"
|
||||
radii="300"
|
||||
>
|
||||
<Text size="B300">Cancel</Text>
|
||||
<Text size="B300">{t('RoomSettings.cancel')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
@ -264,6 +266,7 @@ type RoomProfileProps = {
|
|||
permissions: RoomPermissionsAPI;
|
||||
};
|
||||
export function RoomProfile({ permissions }: RoomProfileProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const useAuthentication = useMediaAuthentication();
|
||||
const room = useRoom();
|
||||
|
|
@ -289,7 +292,7 @@ export function RoomProfile({ permissions }: RoomProfileProps) {
|
|||
|
||||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Profile</Text>
|
||||
<Text size="L400">{t('RoomSettings.profile')}</Text>
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
|
|
@ -311,7 +314,7 @@ export function RoomProfile({ permissions }: RoomProfileProps) {
|
|||
<Box grow="Yes" direction="Column" gap="300">
|
||||
<Box direction="Column" gap="100">
|
||||
<Text className={BreakWord} size="H5">
|
||||
{name ?? 'Unknown'}
|
||||
{name ?? t('RoomSettings.unknown')}
|
||||
</Text>
|
||||
{topic && (
|
||||
<Text className={classNames(BreakWord, LineClamp3)} size="T200">
|
||||
|
|
@ -329,7 +332,7 @@ export function RoomProfile({ permissions }: RoomProfileProps) {
|
|||
onClick={() => setEdit(true)}
|
||||
outlined
|
||||
>
|
||||
<Text size="B300">Edit</Text>
|
||||
<Text size="B300">{t('RoomSettings.edit')}</Text>
|
||||
</Chip>
|
||||
</Box>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Box, color, Spinner, Switch, Text } from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { JoinRule, MatrixError } from 'matrix-js-sdk';
|
||||
import { RoomJoinRulesEventContent } from 'matrix-js-sdk/lib/types';
|
||||
import { SequenceCard } from '../../../components/sequence-card';
|
||||
|
|
@ -18,6 +19,7 @@ type RoomPublishProps = {
|
|||
permissions: RoomPermissionsAPI;
|
||||
};
|
||||
export function RoomPublish({ permissions }: RoomPublishProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const room = useRoom();
|
||||
|
||||
|
|
@ -46,11 +48,11 @@ export function RoomPublish({ permissions }: RoomPublishProps) {
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Publish to Directory"
|
||||
title={t('RoomSettings.publish_to_directory')}
|
||||
description={
|
||||
room.isSpaceRoom()
|
||||
? 'List the space in the public directory to make it discoverable by others.'
|
||||
: 'List the room in the public directory to make it discoverable by others.'
|
||||
? t('RoomSettings.publish_space_desc')
|
||||
: t('RoomSettings.publish_room_desc')
|
||||
}
|
||||
after={
|
||||
<Box gap="200" alignItems="Center">
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import {
|
|||
Icons,
|
||||
} from 'folds';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { MatrixError, Method } from 'matrix-js-sdk';
|
||||
import { RoomTombstoneEventContent } from 'matrix-js-sdk/lib/types';
|
||||
import { SequenceCard } from '../../../components/sequence-card';
|
||||
|
|
@ -41,6 +42,7 @@ import { useRoomCreators } from '../../../hooks/useRoomCreators';
|
|||
import { BreakWord } from '../../../styles/Text.css';
|
||||
|
||||
function RoomUpgradeDialog({ requestClose }: { requestClose: () => void }) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const room = useRoom();
|
||||
const alive = useAlive();
|
||||
|
|
@ -103,7 +105,7 @@ function RoomUpgradeDialog({ requestClose }: { requestClose: () => void }) {
|
|||
size="500"
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="H4">{room.isSpaceRoom() ? 'Space Upgrade' : 'Room Upgrade'}</Text>
|
||||
<Text size="H4">{room.isSpaceRoom() ? t('RoomSettings.space_upgrade') : t('RoomSettings.room_upgrade')}</Text>
|
||||
</Box>
|
||||
<IconButton size="300" onClick={requestClose} radii="300">
|
||||
<Icon src={Icons.Cross} />
|
||||
|
|
@ -111,10 +113,10 @@ function RoomUpgradeDialog({ requestClose }: { requestClose: () => void }) {
|
|||
</Header>
|
||||
<Box style={{ padding: config.space.S400 }} direction="Column" gap="400">
|
||||
<Text priority="400" style={{ color: color.Critical.Main }}>
|
||||
<b>This action is irreversible!</b>
|
||||
<b>{t('RoomSettings.action_irreversible')}</b>
|
||||
</Text>
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Options</Text>
|
||||
<Text size="L400">{t('RoomSettings.options')}</Text>
|
||||
<RoomVersionSelector
|
||||
versions={roomVersions?.available ? Object.keys(roomVersions.available) : ['1']}
|
||||
value={selectedRoomVersion}
|
||||
|
|
@ -148,7 +150,7 @@ function RoomUpgradeDialog({ requestClose }: { requestClose: () => void }) {
|
|||
disabled={upgrading}
|
||||
before={upgrading && <Spinner size="200" variant="Secondary" fill="Solid" />}
|
||||
>
|
||||
<Text size="B400">{room.isSpaceRoom() ? 'Upgrade Space' : 'Upgrade Room'}</Text>
|
||||
<Text size="B400">{room.isSpaceRoom() ? t('RoomSettings.upgrade_space') : t('RoomSettings.upgrade_room')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</Dialog>
|
||||
|
|
@ -163,6 +165,7 @@ type RoomUpgradeProps = {
|
|||
requestClose: () => void;
|
||||
};
|
||||
export function RoomUpgrade({ permissions, requestClose }: RoomUpgradeProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const room = useRoom();
|
||||
const { navigateRoom, navigateSpace } = useRoomNavigate();
|
||||
|
|
@ -213,12 +216,12 @@ export function RoomUpgrade({ permissions, requestClose }: RoomUpgradeProps) {
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title={room.isSpaceRoom() ? 'Upgrade Space' : 'Upgrade Room'}
|
||||
title={room.isSpaceRoom() ? t('RoomSettings.upgrade_space') : t('RoomSettings.upgrade_room')}
|
||||
description={
|
||||
replacementRoom
|
||||
? tombstoneContent.body ||
|
||||
`This ${room.isSpaceRoom() ? 'space' : 'room'} has been replaced!`
|
||||
: `Current version: ${roomVersion}.`
|
||||
(room.isSpaceRoom() ? t('RoomSettings.space_replaced') : t('RoomSettings.room_replaced'))
|
||||
: t('RoomSettings.current_version', { version: roomVersion })
|
||||
}
|
||||
after={
|
||||
<Box alignItems="Center" gap="200">
|
||||
|
|
@ -231,7 +234,7 @@ export function RoomUpgrade({ permissions, requestClose }: RoomUpgradeProps) {
|
|||
radii="300"
|
||||
onClick={handleOpenOldRoom}
|
||||
>
|
||||
<Text size="B300">{room.isSpaceRoom() ? 'Old Space' : 'Old Room'}</Text>
|
||||
<Text size="B300">{room.isSpaceRoom() ? t('RoomSettings.old_space') : t('RoomSettings.old_room')}</Text>
|
||||
</Button>
|
||||
)}
|
||||
{replacementRoom ? (
|
||||
|
|
@ -242,7 +245,7 @@ export function RoomUpgrade({ permissions, requestClose }: RoomUpgradeProps) {
|
|||
radii="300"
|
||||
onClick={handleOpenRoom}
|
||||
>
|
||||
<Text size="B300">{room.isSpaceRoom() ? 'Open New Space' : 'Open New Room'}</Text>
|
||||
<Text size="B300">{room.isSpaceRoom() ? t('RoomSettings.open_new_space') : t('RoomSettings.open_new_room')}</Text>
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
|
|
@ -253,7 +256,7 @@ export function RoomUpgrade({ permissions, requestClose }: RoomUpgradeProps) {
|
|||
disabled={!canUpgrade}
|
||||
onClick={() => setPrompt(true)}
|
||||
>
|
||||
<Text size="B300">Upgrade</Text>
|
||||
<Text size="B300">{t('RoomSettings.upgrade')}</Text>
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import {
|
|||
Text,
|
||||
toRem,
|
||||
} from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useVirtualizer } from '@tanstack/react-virtual';
|
||||
import { RoomMember } from 'matrix-js-sdk';
|
||||
import { Page, PageContent, PageHeader } from '../../../components/page';
|
||||
|
|
@ -75,6 +76,7 @@ type MembersProps = {
|
|||
requestClose: () => void;
|
||||
};
|
||||
export function Members({ requestClose }: MembersProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const useAuthentication = useMediaAuthentication();
|
||||
const room = useRoom();
|
||||
|
|
@ -157,7 +159,7 @@ export function Members({ requestClose }: MembersProps) {
|
|||
<Box grow="Yes" gap="200">
|
||||
<Box grow="Yes" alignItems="Center" gap="200">
|
||||
<Text size="H3" truncate>
|
||||
{room.getJoinedMemberCount()} Members
|
||||
{t('RoomSettings.members_count', { count: room.getJoinedMemberCount() })}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box shrink="No">
|
||||
|
|
@ -182,7 +184,7 @@ export function Members({ requestClose }: MembersProps) {
|
|||
before={<Icon size="200" src={Icons.Search} />}
|
||||
variant="SurfaceVariant"
|
||||
size="500"
|
||||
placeholder="Search"
|
||||
placeholder={t('RoomSettings.search')}
|
||||
outlined
|
||||
after={
|
||||
result && (
|
||||
|
|
@ -197,8 +199,8 @@ export function Members({ requestClose }: MembersProps) {
|
|||
>
|
||||
<Text size="B300">
|
||||
{result.items.length === 0
|
||||
? 'No Results'
|
||||
: `${result.items.length} Results`}
|
||||
? t('RoomSettings.no_results')
|
||||
: t('RoomSettings.results_count', { count: result.items.length })}
|
||||
</Text>
|
||||
</Chip>
|
||||
)
|
||||
|
|
@ -282,7 +284,7 @@ export function Members({ requestClose }: MembersProps) {
|
|||
radii="Pill"
|
||||
outlined
|
||||
size="300"
|
||||
aria-label="Scroll to Top"
|
||||
aria-label={t('RoomSettings.scroll_to_top')}
|
||||
>
|
||||
<Icon src={Icons.ChevronTop} size="300" />
|
||||
</IconButton>
|
||||
|
|
@ -295,7 +297,7 @@ export function Members({ requestClose }: MembersProps) {
|
|||
|
||||
{!fetchingMembers && !result && flattenTagMembers.length === 0 && (
|
||||
<Text style={{ padding: config.space.S300 }} align="Center">
|
||||
{`No "${membershipFilter.name}" Members`}
|
||||
{t('RoomSettings.no_membership_members', { filter: membershipFilter.name })}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* eslint-disable react/no-array-index-key */
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Badge, Box, Button, Chip, config, Icon, Icons, Menu, Spinner, Text } from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import produce from 'immer';
|
||||
import { SequenceCard } from '../../../components/sequence-card';
|
||||
import { SequenceCardStyle } from '../styles.css';
|
||||
|
|
@ -34,6 +35,7 @@ export function PermissionGroups({
|
|||
permissionGroups,
|
||||
canEdit,
|
||||
}: PermissionGroupsProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const room = useRoom();
|
||||
const alive = useAlive();
|
||||
|
|
@ -114,7 +116,7 @@ export function PermissionGroups({
|
|||
|
||||
return (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Users</Text>
|
||||
<Text size="L400">{t('RoomSettings.users')}</Text>
|
||||
<SequenceCard
|
||||
variant="SurfaceVariant"
|
||||
className={SequenceCardStyle}
|
||||
|
|
@ -122,8 +124,8 @@ export function PermissionGroups({
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Default Power"
|
||||
description="Default power level for all users."
|
||||
title={t('RoomSettings.default_power')}
|
||||
description={t('RoomSettings.default_power_desc')}
|
||||
after={
|
||||
<PowerSwitcher
|
||||
powerLevelTags={powerLevelTags}
|
||||
|
|
@ -220,7 +222,7 @@ export function PermissionGroups({
|
|||
<Text size="B300" truncate>
|
||||
{tag.name}
|
||||
</Text>
|
||||
{value < maxPower && <Text size="T200">& Above</Text>}
|
||||
{value < maxPower && <Text size="T200">{t('RoomSettings.and_above')}</Text>}
|
||||
</Chip>
|
||||
)}
|
||||
</PowerSwitcher>
|
||||
|
|
@ -249,11 +251,11 @@ export function PermissionGroups({
|
|||
<Box grow="Yes" direction="Column">
|
||||
{applyState.status === AsyncStatus.Error ? (
|
||||
<Text size="T200">
|
||||
<b>Failed to apply changes! Please try again.</b>
|
||||
<b>{t('RoomSettings.failed_to_apply')}</b>
|
||||
</Text>
|
||||
) : (
|
||||
<Text size="T200">
|
||||
<b>Changes saved! Apply when ready.</b>
|
||||
<b>{t('RoomSettings.changes_saved')}</b>
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
|
|
@ -266,7 +268,7 @@ export function PermissionGroups({
|
|||
disabled={applyingChanges}
|
||||
onClick={resetChanges}
|
||||
>
|
||||
<Text size="B300">Reset</Text>
|
||||
<Text size="B300">{t('RoomSettings.reset')}</Text>
|
||||
</Button>
|
||||
<Button
|
||||
size="300"
|
||||
|
|
@ -276,7 +278,7 @@ export function PermissionGroups({
|
|||
before={applyingChanges && <Spinner variant="Success" fill="Solid" size="100" />}
|
||||
onClick={handleApplyChanges}
|
||||
>
|
||||
<Text size="B300">Apply Changes</Text>
|
||||
<Text size="B300">{t('RoomSettings.apply_changes')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* eslint-disable react/no-array-index-key */
|
||||
import React, { useState, MouseEventHandler, ReactNode } from 'react';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
|
|
@ -108,6 +109,7 @@ type PowersProps = {
|
|||
onEdit?: () => void;
|
||||
};
|
||||
export function Powers({ powerLevels, permissionGroups, onEdit }: PowersProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const useAuthentication = useMediaAuthentication();
|
||||
const room = useRoom();
|
||||
|
|
@ -127,8 +129,8 @@ export function Powers({ powerLevels, permissionGroups, onEdit }: PowersProps) {
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Founders"
|
||||
description="Founding members has all permissions and can only be changed during upgrade."
|
||||
title={t('RoomSettings.founders')}
|
||||
description={t('RoomSettings.founders_desc')}
|
||||
/>
|
||||
|
||||
<SettingTile>
|
||||
|
|
@ -155,8 +157,8 @@ export function Powers({ powerLevels, permissionGroups, onEdit }: PowersProps) {
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="Power Levels"
|
||||
description="Manage and customize incremental power levels for users."
|
||||
title={t('RoomSettings.power_levels')}
|
||||
description={t('RoomSettings.power_levels_desc')}
|
||||
after={
|
||||
onEdit && (
|
||||
<Box gap="200">
|
||||
|
|
@ -168,7 +170,7 @@ export function Powers({ powerLevels, permissionGroups, onEdit }: PowersProps) {
|
|||
outlined
|
||||
onClick={onEdit}
|
||||
>
|
||||
<Text size="B300">Edit</Text>
|
||||
<Text size="B300">{t('RoomSettings.edit')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import {
|
|||
Tooltip,
|
||||
} from 'folds';
|
||||
import { HexColorPicker } from 'react-colorful';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { Page, PageContent, PageHeader } from '../../../components/page';
|
||||
import { IPowerLevels } from '../../../hooks/usePowerLevels';
|
||||
|
|
@ -58,6 +59,7 @@ type EditPowerProps = {
|
|||
onClose: () => void;
|
||||
};
|
||||
function EditPower({ maxPower, power, tag, onSave, onClose }: EditPowerProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const room = useRoom();
|
||||
const roomToParents = useAtomValue(roomToParentsAtom);
|
||||
|
|
@ -120,7 +122,7 @@ function EditPower({ maxPower, power, tag, onSave, onClose }: EditPowerProps) {
|
|||
<Box direction="Column" gap="300">
|
||||
<Box gap="200">
|
||||
<Box shrink="No" direction="Column" gap="100">
|
||||
<Text size="L400">Color</Text>
|
||||
<Text size="L400">{t('RoomSettings.color')}</Text>
|
||||
<Box gap="200">
|
||||
<HexColorPickerPopOut
|
||||
picker={<HexColorPicker color={tagColor} onChange={setTagColor} />}
|
||||
|
|
@ -137,18 +139,18 @@ function EditPower({ maxPower, power, tag, onSave, onClose }: EditPowerProps) {
|
|||
radii="300"
|
||||
before={<PowerColorBadge color={tagColor} />}
|
||||
>
|
||||
<Text size="B300">Pick</Text>
|
||||
<Text size="B300">{t('RoomSettings.pick')}</Text>
|
||||
</Button>
|
||||
)}
|
||||
</HexColorPickerPopOut>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box grow="Yes" direction="Column" gap="100">
|
||||
<Text size="L400">Name</Text>
|
||||
<Text size="L400">{t('RoomSettings.name')}</Text>
|
||||
<Input
|
||||
name="nameInput"
|
||||
defaultValue={tag?.name}
|
||||
placeholder="Bot"
|
||||
placeholder={t('RoomSettings.power_level_placeholder')}
|
||||
size="300"
|
||||
variant="Secondary"
|
||||
radii="300"
|
||||
|
|
@ -156,7 +158,7 @@ function EditPower({ maxPower, power, tag, onSave, onClose }: EditPowerProps) {
|
|||
/>
|
||||
</Box>
|
||||
<Box style={{ maxWidth: toRem(74) }} grow="Yes" direction="Column" gap="100">
|
||||
<Text size="L400">Power</Text>
|
||||
<Text size="L400">{t('RoomSettings.power')}</Text>
|
||||
<Input
|
||||
defaultValue={power}
|
||||
name="powerInput"
|
||||
|
|
@ -174,7 +176,7 @@ function EditPower({ maxPower, power, tag, onSave, onClose }: EditPowerProps) {
|
|||
</Box>
|
||||
</Box>
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Icon</Text>
|
||||
<Text size="L400">{t('RoomSettings.icon')}</Text>
|
||||
{iconUploadAtom && !tagIconSrc ? (
|
||||
<CompactUploadCardRenderer
|
||||
uploadAtom={iconUploadAtom}
|
||||
|
|
@ -194,7 +196,7 @@ function EditPower({ maxPower, power, tag, onSave, onClose }: EditPowerProps) {
|
|||
fill="None"
|
||||
radii="300"
|
||||
>
|
||||
<Text size="B300">Remove</Text>
|
||||
<Text size="B300">{t('RoomSettings.remove')}</Text>
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
|
|
@ -238,7 +240,7 @@ function EditPower({ maxPower, power, tag, onSave, onClose }: EditPowerProps) {
|
|||
radii="300"
|
||||
before={<Icon size="50" src={Icons.SmilePlus} />}
|
||||
>
|
||||
<Text size="B300">Pick</Text>
|
||||
<Text size="B300">{t('RoomSettings.pick')}</Text>
|
||||
</Button>
|
||||
</PopOut>
|
||||
)}
|
||||
|
|
@ -251,7 +253,7 @@ function EditPower({ maxPower, power, tag, onSave, onClose }: EditPowerProps) {
|
|||
fill="None"
|
||||
radii="300"
|
||||
>
|
||||
<Text size="B300">Import</Text>
|
||||
<Text size="B300">{t('RoomSettings.import')}</Text>
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
|
|
@ -267,7 +269,7 @@ function EditPower({ maxPower, power, tag, onSave, onClose }: EditPowerProps) {
|
|||
radii="300"
|
||||
disabled={uploadingIcon}
|
||||
>
|
||||
<Text size="B300">Save</Text>
|
||||
<Text size="B300">{t('RoomSettings.save')}</Text>
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
|
|
@ -277,7 +279,7 @@ function EditPower({ maxPower, power, tag, onSave, onClose }: EditPowerProps) {
|
|||
radii="300"
|
||||
onClick={onClose}
|
||||
>
|
||||
<Text size="B300">Cancel</Text>
|
||||
<Text size="B300">{t('RoomSettings.cancel')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
@ -289,6 +291,7 @@ type PowersEditorProps = {
|
|||
requestClose: () => void;
|
||||
};
|
||||
export function PowersEditor({ powerLevels, requestClose }: PowersEditorProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const useAuthentication = useMediaAuthentication();
|
||||
const room = useRoom();
|
||||
|
|
@ -365,7 +368,7 @@ export function PowersEditor({ powerLevels, requestClose }: PowersEditorProps) {
|
|||
onClick={requestClose}
|
||||
before={<Icon size="100" src={Icons.ArrowLeft} />}
|
||||
>
|
||||
<Text size="T300">Permissions</Text>
|
||||
<Text size="T300">{t('RoomSettings.permissions')}</Text>
|
||||
</Chip>
|
||||
</Box>
|
||||
<Box shrink="No">
|
||||
|
|
@ -381,7 +384,7 @@ export function PowersEditor({ powerLevels, requestClose }: PowersEditorProps) {
|
|||
<Box direction="Column" gap="700">
|
||||
<Box direction="Column" gap="100">
|
||||
<Box alignItems="Baseline" gap="200" justifyContent="SpaceBetween">
|
||||
<Text size="L400">Power Levels</Text>
|
||||
<Text size="L400">{t('RoomSettings.power_levels')}</Text>
|
||||
<BetaNoticeBadge />
|
||||
</Box>
|
||||
<SequenceCard
|
||||
|
|
@ -391,8 +394,8 @@ export function PowersEditor({ powerLevels, requestClose }: PowersEditorProps) {
|
|||
gap="400"
|
||||
>
|
||||
<SettingTile
|
||||
title="New Power Level"
|
||||
description="Create a new power level."
|
||||
title={t('RoomSettings.new_power_level')}
|
||||
description={t('RoomSettings.new_power_level_desc')}
|
||||
after={
|
||||
!createTag && (
|
||||
<Button
|
||||
|
|
@ -404,7 +407,7 @@ export function PowersEditor({ powerLevels, requestClose }: PowersEditorProps) {
|
|||
outlined
|
||||
disabled={applyingChanges}
|
||||
>
|
||||
<Text size="B300">Create</Text>
|
||||
<Text size="B300">{t('RoomSettings.create')}</Text>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
|
@ -462,7 +465,7 @@ export function PowersEditor({ powerLevels, requestClose }: PowersEditorProps) {
|
|||
disabled={applyingChanges}
|
||||
onClick={() => handleToggleDelete(power)}
|
||||
>
|
||||
<Text size="B300">Undo</Text>
|
||||
<Text size="B300">{t('RoomSettings.undo')}</Text>
|
||||
</Chip>
|
||||
) : (
|
||||
<Box shrink="No" alignItems="Center" gap="200">
|
||||
|
|
@ -471,13 +474,13 @@ export function PowersEditor({ powerLevels, requestClose }: PowersEditorProps) {
|
|||
<Tooltip style={{ maxWidth: toRem(200) }}>
|
||||
{usedPowers.has(power) ? (
|
||||
<Box direction="Column">
|
||||
<Text size="L400">Used Power Level</Text>
|
||||
<Text size="L400">{t('RoomSettings.used_power_level')}</Text>
|
||||
<Text size="T200">
|
||||
You have to remove its use before you can delete it.
|
||||
{t('RoomSettings.used_power_level_desc')}
|
||||
</Text>
|
||||
</Box>
|
||||
) : (
|
||||
<Text>Delete</Text>
|
||||
<Text>{t('RoomSettings.delete')}</Text>
|
||||
)}
|
||||
</Tooltip>
|
||||
}
|
||||
|
|
@ -506,7 +509,7 @@ export function PowersEditor({ powerLevels, requestClose }: PowersEditorProps) {
|
|||
disabled={applyingChanges}
|
||||
onClick={() => setEdit(true)}
|
||||
>
|
||||
<Text size="B300">Edit</Text>
|
||||
<Text size="B300">{t('RoomSettings.edit')}</Text>
|
||||
</Chip>
|
||||
</Box>
|
||||
)
|
||||
|
|
@ -536,11 +539,11 @@ export function PowersEditor({ powerLevels, requestClose }: PowersEditorProps) {
|
|||
<Box grow="Yes" direction="Column">
|
||||
{applyState.status === AsyncStatus.Error ? (
|
||||
<Text size="T200">
|
||||
<b>Failed to apply changes! Please try again.</b>
|
||||
<b>{t('RoomSettings.failed_to_apply')}</b>
|
||||
</Text>
|
||||
) : (
|
||||
<Text size="T200">
|
||||
<b>Changes saved! Apply when ready.</b>
|
||||
<b>{t('RoomSettings.changes_saved')}</b>
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
|
|
@ -553,7 +556,7 @@ export function PowersEditor({ powerLevels, requestClose }: PowersEditorProps) {
|
|||
disabled={applyingChanges}
|
||||
onClick={resetChanges}
|
||||
>
|
||||
<Text size="B300">Reset</Text>
|
||||
<Text size="B300">{t('RoomSettings.reset')}</Text>
|
||||
</Button>
|
||||
<Button
|
||||
size="300"
|
||||
|
|
@ -565,7 +568,7 @@ export function PowersEditor({ powerLevels, requestClose }: PowersEditorProps) {
|
|||
}
|
||||
onClick={handleApplyChanges}
|
||||
>
|
||||
<Text size="B300">Apply Changes</Text>
|
||||
<Text size="B300">{t('RoomSettings.apply_changes')}</Text>
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useMemo, useState } from 'react';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { Avatar, Box, config, Icon, IconButton, Icons, IconSrc, MenuItem, Text } from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { JoinRule } from 'matrix-js-sdk';
|
||||
import { PageNav, PageNavContent, PageNavHeader, PageRoot } from '../../components/page';
|
||||
import { ScreenSize, useScreenSizeContext } from '../../hooks/useScreenSize';
|
||||
|
|
@ -24,37 +25,39 @@ type RoomSettingsMenuItem = {
|
|||
icon: IconSrc;
|
||||
};
|
||||
|
||||
const useRoomSettingsMenuItems = (): RoomSettingsMenuItem[] =>
|
||||
useMemo(
|
||||
const useRoomSettingsMenuItems = (): RoomSettingsMenuItem[] => {
|
||||
const { t } = useTranslation();
|
||||
return useMemo(
|
||||
() => [
|
||||
{
|
||||
page: RoomSettingsPage.GeneralPage,
|
||||
name: 'General',
|
||||
name: t('RoomSettings.general'),
|
||||
icon: Icons.Setting,
|
||||
},
|
||||
{
|
||||
page: RoomSettingsPage.MembersPage,
|
||||
name: 'Members',
|
||||
name: t('RoomSettings.members'),
|
||||
icon: Icons.User,
|
||||
},
|
||||
{
|
||||
page: RoomSettingsPage.PermissionsPage,
|
||||
name: 'Permissions',
|
||||
name: t('RoomSettings.permissions'),
|
||||
icon: Icons.Lock,
|
||||
},
|
||||
{
|
||||
page: RoomSettingsPage.EmojisStickersPage,
|
||||
name: 'Emojis & Stickers',
|
||||
name: t('RoomSettings.emojis_stickers'),
|
||||
icon: Icons.Smile,
|
||||
},
|
||||
{
|
||||
page: RoomSettingsPage.DeveloperToolsPage,
|
||||
name: 'Developer Tools',
|
||||
name: t('RoomSettings.developer_tools'),
|
||||
icon: Icons.Terminal,
|
||||
},
|
||||
],
|
||||
[]
|
||||
[t]
|
||||
);
|
||||
};
|
||||
|
||||
type RoomSettingsProps = {
|
||||
initialPage?: RoomSettingsPage;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Box, Icon, IconButton, Icons, Scroll, Text } from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Page, PageContent, PageHeader } from '../../../components/page';
|
||||
import { usePowerLevels } from '../../../hooks/usePowerLevels';
|
||||
import { useRoom } from '../../../hooks/useRoom';
|
||||
|
|
@ -20,6 +21,7 @@ type GeneralProps = {
|
|||
requestClose: () => void;
|
||||
};
|
||||
export function General({ requestClose }: GeneralProps) {
|
||||
const { t } = useTranslation();
|
||||
const room = useRoom();
|
||||
const powerLevels = usePowerLevels(room);
|
||||
const creators = useRoomCreators(room);
|
||||
|
|
@ -31,7 +33,7 @@ export function General({ requestClose }: GeneralProps) {
|
|||
<Box grow="Yes" gap="200">
|
||||
<Box grow="Yes" alignItems="Center" gap="200">
|
||||
<Text size="H3" truncate>
|
||||
General
|
||||
{t('RoomSettings.general')}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box shrink="No">
|
||||
|
|
@ -47,19 +49,19 @@ export function General({ requestClose }: GeneralProps) {
|
|||
<Box direction="Column" gap="700">
|
||||
<RoomProfile permissions={permissions} />
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Options</Text>
|
||||
<Text size="L400">{t('RoomSettings.options')}</Text>
|
||||
<RoomJoinRules permissions={permissions} />
|
||||
<RoomHistoryVisibility permissions={permissions} />
|
||||
<RoomEncryption permissions={permissions} />
|
||||
<RoomPublish permissions={permissions} />
|
||||
</Box>
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Addresses</Text>
|
||||
<Text size="L400">{t('RoomSettings.addresses')}</Text>
|
||||
<RoomPublishedAddresses permissions={permissions} />
|
||||
<RoomLocalAddresses permissions={permissions} />
|
||||
</Box>
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Advanced Options</Text>
|
||||
<Text size="L400">{t('RoomSettings.advanced_options')}</Text>
|
||||
<RoomUpgrade permissions={permissions} requestClose={requestClose} />
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Box, Icon, IconButton, Icons, Scroll, Text } from 'folds';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Page, PageContent, PageHeader } from '../../../components/page';
|
||||
import { useRoom } from '../../../hooks/useRoom';
|
||||
import { usePowerLevels } from '../../../hooks/usePowerLevels';
|
||||
|
|
@ -14,6 +15,7 @@ type PermissionsProps = {
|
|||
requestClose: () => void;
|
||||
};
|
||||
export function Permissions({ requestClose }: PermissionsProps) {
|
||||
const { t } = useTranslation();
|
||||
const mx = useMatrixClient();
|
||||
const room = useRoom();
|
||||
const powerLevels = usePowerLevels(room);
|
||||
|
|
@ -41,7 +43,7 @@ export function Permissions({ requestClose }: PermissionsProps) {
|
|||
<Box grow="Yes" gap="200">
|
||||
<Box grow="Yes" alignItems="Center" gap="200">
|
||||
<Text size="H3" truncate>
|
||||
Permissions
|
||||
{t('RoomSettings.permissions')}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box shrink="No">
|
||||
|
|
|
|||
|
|
@ -1,215 +1,217 @@
|
|||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { MessageEvent, StateEvent } from '../../../../types/matrix/room';
|
||||
import { PermissionGroup } from '../../common-settings/permissions';
|
||||
|
||||
export const usePermissionGroups = (isCallRoom: boolean): PermissionGroup[] => {
|
||||
const { t } = useTranslation();
|
||||
const groups: PermissionGroup[] = useMemo(() => {
|
||||
const messagesGroup: PermissionGroup = {
|
||||
name: 'Messages',
|
||||
name: t('RoomSettings.perm_messages'),
|
||||
items: [
|
||||
{
|
||||
location: {
|
||||
key: MessageEvent.RoomMessage,
|
||||
},
|
||||
name: 'Send Messages',
|
||||
name: t('RoomSettings.perm_send_messages'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
key: MessageEvent.Sticker,
|
||||
},
|
||||
name: 'Send Stickers',
|
||||
name: t('RoomSettings.perm_send_stickers'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
key: MessageEvent.Reaction,
|
||||
},
|
||||
name: 'Send Reactions',
|
||||
name: t('RoomSettings.perm_send_reactions'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
notification: true,
|
||||
key: 'room',
|
||||
},
|
||||
name: 'Ping @room',
|
||||
name: t('RoomSettings.perm_ping_room'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
state: true,
|
||||
key: StateEvent.RoomPinnedEvents,
|
||||
},
|
||||
name: 'Pin Messages',
|
||||
name: t('RoomSettings.perm_pin_messages'),
|
||||
},
|
||||
{
|
||||
location: {},
|
||||
name: 'Other Message Events',
|
||||
name: t('RoomSettings.perm_other_message_events'),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const callSettingsGroup: PermissionGroup = {
|
||||
name: 'Calls',
|
||||
name: t('RoomSettings.perm_calls'),
|
||||
items: [
|
||||
{
|
||||
location: {
|
||||
state: true,
|
||||
key: StateEvent.GroupCallMemberPrefix,
|
||||
},
|
||||
name: 'Join Call',
|
||||
name: t('RoomSettings.perm_join_call'),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const moderationGroup: PermissionGroup = {
|
||||
name: 'Moderation',
|
||||
name: t('RoomSettings.perm_moderation'),
|
||||
items: [
|
||||
{
|
||||
location: {
|
||||
action: true,
|
||||
key: 'invite',
|
||||
},
|
||||
name: 'Invite',
|
||||
name: t('RoomSettings.perm_invite'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
action: true,
|
||||
key: 'kick',
|
||||
},
|
||||
name: 'Kick',
|
||||
name: t('RoomSettings.perm_kick'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
action: true,
|
||||
key: 'ban',
|
||||
},
|
||||
name: 'Ban',
|
||||
name: t('RoomSettings.perm_ban'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
action: true,
|
||||
key: 'redact',
|
||||
},
|
||||
name: 'Delete Others Messages',
|
||||
name: t('RoomSettings.perm_delete_others_messages'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
key: MessageEvent.RoomRedaction,
|
||||
},
|
||||
name: 'Delete Self Messages',
|
||||
name: t('RoomSettings.perm_delete_self_messages'),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const roomOverviewGroup: PermissionGroup = {
|
||||
name: 'Room Overview',
|
||||
name: t('RoomSettings.perm_room_overview'),
|
||||
items: [
|
||||
{
|
||||
location: {
|
||||
state: true,
|
||||
key: StateEvent.RoomAvatar,
|
||||
},
|
||||
name: 'Room Avatar',
|
||||
name: t('RoomSettings.perm_room_avatar'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
state: true,
|
||||
key: StateEvent.RoomName,
|
||||
},
|
||||
name: 'Room Name',
|
||||
name: t('RoomSettings.perm_room_name'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
state: true,
|
||||
key: StateEvent.RoomTopic,
|
||||
},
|
||||
name: 'Room Topic',
|
||||
name: t('RoomSettings.perm_room_topic'),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const roomSettingsGroup: PermissionGroup = {
|
||||
name: 'Settings',
|
||||
name: t('RoomSettings.perm_settings'),
|
||||
items: [
|
||||
{
|
||||
location: {
|
||||
state: true,
|
||||
key: StateEvent.RoomJoinRules,
|
||||
},
|
||||
name: 'Change Room Access',
|
||||
name: t('RoomSettings.perm_change_room_access'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
state: true,
|
||||
key: StateEvent.RoomCanonicalAlias,
|
||||
},
|
||||
name: 'Publish Address',
|
||||
name: t('RoomSettings.perm_publish_address'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
state: true,
|
||||
key: StateEvent.RoomPowerLevels,
|
||||
},
|
||||
name: 'Change All Permission',
|
||||
name: t('RoomSettings.perm_change_all_permission'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
state: true,
|
||||
key: StateEvent.PowerLevelTags,
|
||||
},
|
||||
name: 'Edit Power Levels',
|
||||
name: t('RoomSettings.perm_edit_power_levels'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
state: true,
|
||||
key: StateEvent.RoomEncryption,
|
||||
},
|
||||
name: 'Enable Encryption',
|
||||
name: t('RoomSettings.perm_enable_encryption'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
state: true,
|
||||
key: StateEvent.RoomHistoryVisibility,
|
||||
},
|
||||
name: 'History Visibility',
|
||||
name: t('RoomSettings.perm_history_visibility'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
state: true,
|
||||
key: StateEvent.RoomTombstone,
|
||||
},
|
||||
name: 'Upgrade Room',
|
||||
name: t('RoomSettings.perm_upgrade_room'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
state: true,
|
||||
},
|
||||
name: 'Other Settings',
|
||||
name: t('RoomSettings.perm_other_settings'),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const otherSettingsGroup: PermissionGroup = {
|
||||
name: 'Other',
|
||||
name: t('RoomSettings.perm_other'),
|
||||
items: [
|
||||
{
|
||||
location: {
|
||||
state: true,
|
||||
key: StateEvent.PoniesRoomEmotes,
|
||||
},
|
||||
name: 'Manage Emojis & Stickers',
|
||||
name: t('RoomSettings.perm_manage_emojis_stickers'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
state: true,
|
||||
key: StateEvent.RoomServerAcl,
|
||||
},
|
||||
name: 'Change Server ACLs',
|
||||
name: t('RoomSettings.perm_change_server_acls'),
|
||||
},
|
||||
{
|
||||
location: {
|
||||
state: true,
|
||||
key: 'im.vector.modular.widgets',
|
||||
},
|
||||
name: 'Modify Widgets',
|
||||
name: t('RoomSettings.perm_modify_widgets'),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
@ -222,7 +224,7 @@ export const usePermissionGroups = (isCallRoom: boolean): PermissionGroup[] => {
|
|||
roomSettingsGroup,
|
||||
otherSettingsGroup,
|
||||
];
|
||||
}, [isCallRoom]);
|
||||
}, [isCallRoom, t]);
|
||||
|
||||
return groups;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { RoomMember } from 'matrix-js-sdk';
|
||||
import { Membership } from '../../types/matrix/room';
|
||||
|
||||
|
|
@ -21,32 +22,34 @@ export type MembershipFilterItem = {
|
|||
filterFn: MembershipFilterFn;
|
||||
};
|
||||
|
||||
export const useMembershipFilterMenu = (): MembershipFilterItem[] =>
|
||||
useMemo(
|
||||
export const useMembershipFilterMenu = (): MembershipFilterItem[] => {
|
||||
const { t } = useTranslation();
|
||||
return useMemo(
|
||||
() => [
|
||||
{
|
||||
name: 'Joined',
|
||||
name: t('RoomSettings.filter_joined'),
|
||||
filterFn: MembershipFilter.filterJoined,
|
||||
},
|
||||
{
|
||||
name: 'Invited',
|
||||
name: t('RoomSettings.filter_invited'),
|
||||
filterFn: MembershipFilter.filterInvited,
|
||||
},
|
||||
{
|
||||
name: 'Left',
|
||||
name: t('RoomSettings.filter_left'),
|
||||
filterFn: MembershipFilter.filterLeaved,
|
||||
},
|
||||
{
|
||||
name: 'Kicked',
|
||||
name: t('RoomSettings.filter_kicked'),
|
||||
filterFn: MembershipFilter.filterKicked,
|
||||
},
|
||||
{
|
||||
name: 'Banned',
|
||||
name: t('RoomSettings.filter_banned'),
|
||||
filterFn: MembershipFilter.filterBanned,
|
||||
},
|
||||
],
|
||||
[]
|
||||
[t]
|
||||
);
|
||||
};
|
||||
|
||||
export const useMembershipFilter = (
|
||||
index: number,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { RoomMember } from 'matrix-js-sdk';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const MemberSort = {
|
||||
Ascending: (a: RoomMember, b: RoomMember) =>
|
||||
|
|
@ -19,28 +20,30 @@ export type MemberSortItem = {
|
|||
sortFn: MemberSortFn;
|
||||
};
|
||||
|
||||
export const useMemberSortMenu = (): MemberSortItem[] =>
|
||||
useMemo(
|
||||
export const useMemberSortMenu = (): MemberSortItem[] => {
|
||||
const { t } = useTranslation();
|
||||
return useMemo(
|
||||
() => [
|
||||
{
|
||||
name: 'A to Z',
|
||||
name: t('RoomSettings.sort_a_to_z'),
|
||||
sortFn: MemberSort.Ascending,
|
||||
},
|
||||
{
|
||||
name: 'Z to A',
|
||||
name: t('RoomSettings.sort_z_to_a'),
|
||||
sortFn: MemberSort.Descending,
|
||||
},
|
||||
{
|
||||
name: 'Newest',
|
||||
name: t('RoomSettings.sort_newest'),
|
||||
sortFn: MemberSort.NewestFirst,
|
||||
},
|
||||
{
|
||||
name: 'Oldest',
|
||||
name: t('RoomSettings.sort_oldest'),
|
||||
sortFn: MemberSort.Oldest,
|
||||
},
|
||||
],
|
||||
[]
|
||||
[t]
|
||||
);
|
||||
};
|
||||
|
||||
export const useMemberSort = (index: number, memberSort: MemberSortItem[]): MemberSortItem => {
|
||||
const item = memberSort[index] ?? memberSort[0];
|
||||
|
|
@ -61,7 +64,7 @@ export const useMemberPowerSort = (
|
|||
|
||||
return getPowerLevel(b.userId) - getPowerLevel(a.userId);
|
||||
},
|
||||
[creators]
|
||||
[creators, getPowerLevel]
|
||||
);
|
||||
|
||||
return sort;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Room } from 'matrix-js-sdk';
|
||||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { IPowerLevels } from './usePowerLevels';
|
||||
import { useStateEvent } from './useStateEvent';
|
||||
import { MemberPowerTag, StateEvent } from '../../types/matrix/room';
|
||||
|
|
@ -45,76 +46,91 @@ export const getUsedPowers = (powerLevels: IPowerLevels): Set<number> => {
|
|||
return powers;
|
||||
};
|
||||
|
||||
const DEFAULT_TAGS: PowerLevelTags = {
|
||||
type TFunction = (key: string) => string;
|
||||
|
||||
const getDefaultTags = (t: TFunction): PowerLevelTags => ({
|
||||
9001: {
|
||||
name: 'Goku',
|
||||
name: t('RoomSettings.power_goku'),
|
||||
color: '#ff6a00',
|
||||
},
|
||||
150: {
|
||||
name: 'Manager',
|
||||
name: t('RoomSettings.power_manager'),
|
||||
color: '#ff6a7f',
|
||||
},
|
||||
101: {
|
||||
name: 'Founder',
|
||||
name: t('RoomSettings.power_founder'),
|
||||
color: '#0000ff',
|
||||
},
|
||||
100: {
|
||||
name: 'Admin',
|
||||
name: t('RoomSettings.power_admin'),
|
||||
color: '#0088ff',
|
||||
},
|
||||
50: {
|
||||
name: 'Moderator',
|
||||
name: t('RoomSettings.power_moderator'),
|
||||
color: '#1fd81f',
|
||||
},
|
||||
0: {
|
||||
name: 'Member',
|
||||
name: t('RoomSettings.power_member'),
|
||||
color: '#91cfdf',
|
||||
},
|
||||
[-1]: {
|
||||
name: 'Muted',
|
||||
name: t('RoomSettings.power_muted'),
|
||||
color: '#888888',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const generateFallbackTag = (powerLevelTags: PowerLevelTags, power: number): MemberPowerTag => {
|
||||
const generateFallbackTag = (powerLevelTags: PowerLevelTags, power: number, t: TFunction): MemberPowerTag => {
|
||||
const highToLow = sortPowers(getPowers(powerLevelTags));
|
||||
|
||||
const tagPower = highToLow.find((p) => p < power);
|
||||
const tag = typeof tagPower === 'number' ? powerLevelTags[tagPower] : undefined;
|
||||
|
||||
return {
|
||||
name: tag ? `${tag.name} ${power}` : `Team ${power}`,
|
||||
name: tag ? `${tag.name} ${power}` : `${t('RoomSettings.power_team')} ${power}`,
|
||||
};
|
||||
};
|
||||
|
||||
const LEGACY_CINNY_POWER_LEVEL_TAGS = 'in.cinny.room.power_level_tags' as StateEvent;
|
||||
|
||||
export const usePowerLevelTags = (room: Room, powerLevels: IPowerLevels): PowerLevelTags => {
|
||||
const { t } = useTranslation();
|
||||
const tagsEvent = useStateEvent(room, StateEvent.PowerLevelTags);
|
||||
const legacyTagsEvent = useStateEvent(room, LEGACY_CINNY_POWER_LEVEL_TAGS);
|
||||
const activeTagsEvent = tagsEvent ?? legacyTagsEvent;
|
||||
|
||||
const powerLevelTags: PowerLevelTags = useMemo(() => {
|
||||
const defaultTags = getDefaultTags(t);
|
||||
const content = activeTagsEvent?.getContent<PowerLevelTags>();
|
||||
const powerToTags: PowerLevelTags = { ...content };
|
||||
|
||||
const powers = getUsedPowers(powerLevels);
|
||||
Array.from(powers).forEach((power) => {
|
||||
if (powerToTags[power]?.name === undefined) {
|
||||
powerToTags[power] = DEFAULT_TAGS[power] ?? generateFallbackTag(DEFAULT_TAGS, power);
|
||||
powerToTags[power] = defaultTags[power] ?? generateFallbackTag(defaultTags, power, t);
|
||||
}
|
||||
});
|
||||
|
||||
return powerToTags;
|
||||
}, [powerLevels, activeTagsEvent]);
|
||||
}, [powerLevels, activeTagsEvent, t]);
|
||||
|
||||
return powerLevelTags;
|
||||
};
|
||||
|
||||
const generateFallbackTagSimple = (powerLevelTags: PowerLevelTags, power: number): MemberPowerTag => {
|
||||
const highToLow = sortPowers(getPowers(powerLevelTags));
|
||||
|
||||
const tagPower = highToLow.find((p) => p < power);
|
||||
const tag = typeof tagPower === 'number' ? powerLevelTags[tagPower] : undefined;
|
||||
|
||||
return {
|
||||
name: tag ? `${tag.name} ${power}` : `#${power}`,
|
||||
};
|
||||
};
|
||||
|
||||
export const getPowerLevelTag = (
|
||||
powerLevelTags: PowerLevelTags,
|
||||
powerLevel: number
|
||||
): MemberPowerTag => {
|
||||
const tag: MemberPowerTag | undefined = powerLevelTags[powerLevel];
|
||||
return tag ?? generateFallbackTag(powerLevelTags, powerLevel);
|
||||
return tag ?? generateFallbackTagSimple(powerLevelTags, powerLevel);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { MemberPowerTag } from '../../types/matrix/room';
|
||||
|
||||
const DEFAULT_TAG: MemberPowerTag = {
|
||||
name: 'Founder',
|
||||
color: '#0000ff',
|
||||
export const useRoomCreatorsTag = (): MemberPowerTag => {
|
||||
const { t } = useTranslation();
|
||||
return useMemo(
|
||||
() => ({
|
||||
name: t('RoomSettings.power_founder'),
|
||||
color: '#0000ff',
|
||||
}),
|
||||
[t]
|
||||
);
|
||||
};
|
||||
|
||||
export const useRoomCreatorsTag = (): MemberPowerTag => DEFAULT_TAG;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue