Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2e537e618c | ||
![]() |
fe3b7a2ad3 | ||
![]() |
90db793fd0 | ||
![]() |
7bd2a6ad61 | ||
![]() |
745f4d2439 | ||
![]() |
254cfaea28 | ||
![]() |
d4da5a1eea | ||
![]() |
c0f8297414 |
@@ -593,6 +593,10 @@ fillAbuseReportDescription: "通報理由の詳細を記入してください。
|
||||
abuseReported: "内容が送信されました。ご報告ありがとうございました。"
|
||||
send: "送信"
|
||||
abuseMarkAsResolved: "対応済みにする"
|
||||
openInNewTab: "新しいタブで開く"
|
||||
openInSideView: "サイドビューで開く"
|
||||
defaultNavigationBehaviour: "デフォルトのナビゲーション"
|
||||
editTheseSettingsMayBreakAccount: "これらの設定を編集するとアカウントが破損する可能性があります。"
|
||||
|
||||
_serverDisconnectedBehavior:
|
||||
reload: "自動でリロード"
|
||||
|
@@ -1,27 +1,27 @@
|
||||
---
|
||||
_lang_: "Русский"
|
||||
introMisskey: "Добро пожаловать! Misskey - это децентрализованный сервис микроблогов с открытым исходным кодом.\nСоздавайте «записи», чтобы поделиться происходящим или рассказать всем о себе 📡\nТакже Вы можете добавить быструю реакцию на все записи с помощью функции «реакция» 👍\nОткройте для себя новый мир 🚀"
|
||||
introMisskey: "Добро пожаловать! Misskey — это децентрализованный сервис микроблогов с открытым исходным кодом.\nПишите «заметки» — делитесь со всеми происходящим вокруг или рассказывайте о себе 📡\nСтавьте «реакции» — выражайте свои чувства и эмоции от заметок других 👍\nОткройте для себя новый мир 🚀"
|
||||
monthAndDay: "{day}.{month}"
|
||||
search: "Поиск"
|
||||
notifications: "Уведомления"
|
||||
username: "Имя пользователя"
|
||||
password: "Пароль"
|
||||
fetchingAsApObject: "Запрос на федерацию"
|
||||
ok: "Окей"
|
||||
gotIt: "Отлично"
|
||||
fetchingAsApObject: "Приём с других сайтов…"
|
||||
ok: "Согласен"
|
||||
gotIt: "Понятно!"
|
||||
cancel: "Отмена"
|
||||
enterUsername: "Введите имя пользователя"
|
||||
renotedBy: "{user} репостнул(а)"
|
||||
noNotes: "Нет постов"
|
||||
noNotifications: "Нет уведомлений"
|
||||
instance: "Узел"
|
||||
renotedBy: "{user} передаёт…"
|
||||
noNotes: "Нет ни одной заметки"
|
||||
noNotifications: "Нет ни одного уведомления"
|
||||
instance: "Инстанс"
|
||||
settings: "Настройки"
|
||||
basicSettings: "Основное"
|
||||
otherSettings: "Прочee"
|
||||
basicSettings: "Основные настройки"
|
||||
otherSettings: "Прочие настройки"
|
||||
openInWindow: "Открыть в окне"
|
||||
profile: "Профиль"
|
||||
timeline: "Лента"
|
||||
noAccountDescription: "Описание отсутствует"
|
||||
noAccountDescription: "Пользователь ничего не написал про себя"
|
||||
login: "Войти"
|
||||
loggingIn: "Выполняется вход"
|
||||
logout: "Выйти"
|
||||
@@ -32,14 +32,14 @@ users: "Пользователи"
|
||||
addUser: "Добавить пользователя"
|
||||
favorite: "Избранное"
|
||||
favorites: "Избранное"
|
||||
unfavorite: "Удалить из избранных"
|
||||
pin: "Закрепить"
|
||||
unpin: "Открепить"
|
||||
unfavorite: "Убрать из избранных"
|
||||
pin: "Закрепить в профиле"
|
||||
unpin: "Открепить от профиля"
|
||||
copyContent: "Скопировать содержимое"
|
||||
copyLink: "Скопировать ссылку"
|
||||
delete: "Удалить"
|
||||
deleteAndEdit: "Удалить и отредактировать"
|
||||
deleteAndEditConfirm: "Удалить этот пост и отредактировать заново? Все реакции, репосты и ответы на него также будут удалены."
|
||||
deleteAndEditConfirm: "Удалить этот пост и создать отредактированный? Все реакции, ссылки и ответы на существующий будут будут потеряны."
|
||||
addToList: "Добавить в список"
|
||||
sendMessage: "Отправить сообщение"
|
||||
copyUsername: "Скопировать имя пользователя"
|
||||
@@ -47,7 +47,7 @@ searchUser: "Поиск людей"
|
||||
reply: "Ответить"
|
||||
loadMore: "Показать еще"
|
||||
youGotNewFollower: "Новый подписчик"
|
||||
receiveFollowRequest: "Запрос на подписку"
|
||||
receiveFollowRequest: "Получен запрос на подписку"
|
||||
followRequestAccepted: "Запрос на подписку принят"
|
||||
mention: "Упоминание"
|
||||
mentions: "Упоминания"
|
||||
@@ -59,189 +59,190 @@ files: "Файлы"
|
||||
download: "Скачать"
|
||||
driveFileDeleteConfirm: "Удалить файл {name} ? Посты с ним также будут удалены"
|
||||
unfollowConfirm: "Удалить из подписок {name}?"
|
||||
exportRequested: "Вы запросили экспорт. Это может занять некоторое время. По завершению результат будет добавлен на «Диск»."
|
||||
exportRequested: "Вы запросили экспорт. Это может занять некоторое время. Результат будет добавлен на «Диск»."
|
||||
importRequested: "Вы запросили импорт. Это может занять некоторое время."
|
||||
lists: "Списки"
|
||||
noLists: "Нет списков"
|
||||
noLists: "Нет ни одного списка"
|
||||
note: "Пост"
|
||||
notes: "Посты"
|
||||
notes: "Заметки"
|
||||
following: "Подписки"
|
||||
followers: "Подписчики"
|
||||
followsYou: "Подписчики"
|
||||
followsYou: "Читает вас"
|
||||
createList: "Создать список"
|
||||
manageLists: "Управление списками"
|
||||
error: "Ошибка"
|
||||
somethingHappened: "Что-то пошло не так"
|
||||
retry: "Повторить попытку"
|
||||
pageLoadError: "Ошибка загрузки страницы"
|
||||
pageLoadErrorDescription: "Обычно это вызвано сетевыми ошибками или кэшем браузера. Попробуйте очистить кэш, а затем попробуйте еще раз, немного подождав."
|
||||
pageLoadError: "Не удалось загрузить страницу"
|
||||
pageLoadErrorDescription: "Обычно это случается из-за сбоев в сети или кэша браузера. Попробуйте очистить кэш, или подождать пару минут, а потом попытаться загрузить страницу снова."
|
||||
enterListName: "Введите имя списка"
|
||||
privacy: "Приватность"
|
||||
makeFollowManuallyApprove: "Подтверждать подписчиков вручную"
|
||||
privacy: "Конфиденциальность"
|
||||
makeFollowManuallyApprove: "Принимать подписчиков вручную"
|
||||
defaultNoteVisibility: "Видимость постов по умолчанию"
|
||||
follow: "Подписки"
|
||||
follow: "Подписка"
|
||||
followRequest: "Запрос на подписку"
|
||||
followRequests: "Запросы на подписку"
|
||||
unfollow: "Отписаться"
|
||||
followRequestPending: "Ожидающие запросы на подписку"
|
||||
followRequestPending: "Нерассмотренный запрос на подписку"
|
||||
enterEmoji: "Введите эмодзи"
|
||||
renote: "Репост"
|
||||
unrenote: "Отмена репоста"
|
||||
quote: "Цитата"
|
||||
pinnedNote: "Закреплённый пост"
|
||||
pinnedNote: "Закреплённая заметка"
|
||||
you: "Вы"
|
||||
clickToShow: "Нажмите для просмотра"
|
||||
sensitive: "NSFW"
|
||||
sensitive: "Содержимое не для всех"
|
||||
add: "Добавить"
|
||||
reaction: "Реакции"
|
||||
reactionSettingDescription: "Выберите реакции для показа в селекторе реакций"
|
||||
reactionSettingDescription: "Выберите, что показывать в палитре реакций"
|
||||
rememberNoteVisibility: "Запоминать видимость поста"
|
||||
attachCancel: "Удалить вложение"
|
||||
markAsSensitive: "Отметить как NSFW"
|
||||
unmarkAsSensitive: "Снять отметку NSFW"
|
||||
markAsSensitive: "Отметить как «не для всех»"
|
||||
unmarkAsSensitive: "Снять отметку «не для всех»"
|
||||
enterFileName: "Введите имя файла"
|
||||
mute: "Скрыть"
|
||||
unmute: "Показывать"
|
||||
unmute: "Отменить скрытие"
|
||||
block: "Заблокировать"
|
||||
unblock: "Разблокировать"
|
||||
suspend: "Приостановить"
|
||||
unsuspend: "Возобновить"
|
||||
blockConfirm: "Заблокировать?"
|
||||
unblockConfirm: "Разблокировать?"
|
||||
suspendConfirm: "Приостановить?"
|
||||
unsuspendConfirm: "Возобновить?"
|
||||
suspend: "Заморозить"
|
||||
unsuspend: "Разморозить"
|
||||
blockConfirm: "Заблокировать этот аккаунт?"
|
||||
unblockConfirm: "Разблокировать этот аккаунт?"
|
||||
suspendConfirm: "Заморозить этот аккаунт?"
|
||||
unsuspendConfirm: "Разморозить этот аккаунт?"
|
||||
selectList: "Выберите список"
|
||||
selectAntenna: "Выберите антенну"
|
||||
selectWidget: "Выберите виджет"
|
||||
editWidgets: "Редактировать виджет"
|
||||
editWidgetsExit: "Завершить"
|
||||
customEmojis: "Кастомные эмодзи"
|
||||
editWidgetsExit: "Готово"
|
||||
customEmojis: "Эмодзи пользователя"
|
||||
emoji: "Эмодзи"
|
||||
emojiName: "Название эмодзи"
|
||||
emojiUrl: "URL изображения"
|
||||
emojiUrl: "URL эмодзи"
|
||||
addEmoji: "Добавить эмодзи"
|
||||
settingGuide: "Рекомендуемые настройки"
|
||||
cacheRemoteFiles: "Кешировать внешние файлы"
|
||||
cacheRemoteFilesDescription: "Когда эта настройка отключена, удаленные файлы загружаются непосредственно из удаленного экземпляра. Отключение этого параметра уменьшит использование хранилища, но увеличит трафик, так как эскизы не будут генерироваться."
|
||||
flagAsBot: "Учётка бота"
|
||||
flagAsCat: "Учётка кота"
|
||||
autoAcceptFollowed: "Принимать подписки автоматически"
|
||||
addAcount: "Добавить учётку"
|
||||
loginFailed: "Ошибка входа"
|
||||
showOnRemote: "Посмотреть оригинал"
|
||||
cacheRemoteFilesDescription: "Когда эта настройка отключена, файлы с других сайтов будут загружаться прямо оттуда. Это сэкономит место на сервере, но увеличит трафик, так как не будут создаваться эскизы."
|
||||
flagAsBot: "Аккаунт бота"
|
||||
flagAsCat: "Аккаунт кота"
|
||||
autoAcceptFollowed: "Принимать подписчиков автоматически"
|
||||
addAcount: "Добавить аккаунт"
|
||||
loginFailed: "Неудачная попытка входа"
|
||||
showOnRemote: "Перейти к оригиналу на его сайт"
|
||||
general: "Общее"
|
||||
wallpaper: "Обои"
|
||||
setWallpaper: "Установить обои"
|
||||
removeWallpaper: "Удалить обои"
|
||||
searchWith: "Искать в {q}"
|
||||
youHaveNoLists: "Нет списков"
|
||||
youHaveNoLists: "У вас нет списков"
|
||||
followConfirm: "Подписаться на {name}?"
|
||||
proxyAccount: "Прокси аккаунт"
|
||||
proxyAccountDescription: "Учетная запись прокси - это учетная запись, которая при определенных условиях действует в качестве удаленного последователя для пользователей. Например, когда пользователь добавляет удаленного пользователя в список, действия удаленного пользователя не будут доставляться экземпляру, если ни один локальный пользователь не следует за этим пользователем, поэтому вместо него будет действовать учетная запись прокси."
|
||||
proxyAccount: "Учётная запись прокси"
|
||||
proxyAccountDescription: "Учетная запись прокси предназначена служить подписчиком на пользователей с других сайтов. Например, если пользователь добавит кого-то с другого сайта а список, деятельность того не отобразится, пока никто с этого же сайта не подписан на него. Чтобы это стало возможным, на него подписывается прокси."
|
||||
host: "Хост"
|
||||
selectUser: "Выбор пользователя"
|
||||
selectUser: "Выберите пользователя"
|
||||
recipient: "Кому"
|
||||
annotation: "Описание"
|
||||
federation: "Федиверс"
|
||||
instances: "Узел"
|
||||
registeredAt: "Присоединился(ась)"
|
||||
latestRequestSentAt: "Последний запрос отправлен"
|
||||
latestRequestReceivedAt: "Последний запрос, поступивший по адресу"
|
||||
federation: "Федерация"
|
||||
instances: "Инстанс"
|
||||
registeredAt: "Первое наблюдение"
|
||||
latestRequestSentAt: "Последний отправленный запрос"
|
||||
latestRequestReceivedAt: "Последний полученный запрос"
|
||||
latestStatus: "Последний статус"
|
||||
storageUsage: "Использовано"
|
||||
charts: "Диаграммы"
|
||||
perHour: "Каждый час"
|
||||
perDay: "Каждый день"
|
||||
stopActivityDelivery: "Остановить отправку обновлений активности"
|
||||
blockThisInstance: "Блокировать этот инстанс"
|
||||
operations: "Операции"
|
||||
software: "Программы"
|
||||
version: "Версия"
|
||||
metadata: "Метаданные"
|
||||
withNFiles: "{n} файлов"
|
||||
withNFiles: "файлов: {n}"
|
||||
monitor: "Монитор"
|
||||
jobQueue: "Очередь заданий"
|
||||
cpuAndMemory: "CPU и память"
|
||||
cpuAndMemory: "Процессор и память"
|
||||
network: "Сеть"
|
||||
disk: "Диск"
|
||||
instanceInfo: "Информация об узле"
|
||||
instanceInfo: "Информация об инстансе"
|
||||
statistics: "Статистика"
|
||||
clearQueue: "Очистить очередь"
|
||||
clearQueueConfirmTitle: "Очистить очередь?"
|
||||
clearQueueConfirmText: "Любые недоставленные записи, оставшиеся в очереди, не будут переданы. Обычно эта операция НЕ нужна."
|
||||
clearQueueConfirmText: "Всё, что осталось в очереди, не будет доставлено. Обычно эта операция НЕ нужна."
|
||||
clearCachedFiles: "Очистить кэш"
|
||||
clearCachedFilesConfirm: "Хотите удалить все кешированные файлы?"
|
||||
blockedInstances: "Заблокированные узлы"
|
||||
blockedInstancesDescription: "Введите список узлов, которые хотите заблокировать. Они не смогут взаимодействовать с этим."
|
||||
clearCachedFilesConfirm: "Удалить все закэшированные файлы с других сайтов?"
|
||||
blockedInstances: "Заблокированные инстансы"
|
||||
blockedInstancesDescription: "Введите список инстансов, которые хотите заблокировать. Они больше не смогут обмениваться с вашим инстансом."
|
||||
muteAndBlock: "Скрытие и блокировка"
|
||||
mutedUsers: "Скрытые пользователи"
|
||||
blockedUsers: "Заблокированные Пользователи"
|
||||
noUsers: "Нет пользователей"
|
||||
editProfile: "Изменить профиль"
|
||||
noteDeleteConfirm: "Вы хотите удалить эту запись?"
|
||||
pinLimitExceeded: "Превышен лимит"
|
||||
intro: "Misskey установлен! Создайте учетную запись администратора"
|
||||
done: "Завершено"
|
||||
blockedUsers: "Заблокированные пользователи"
|
||||
noUsers: "Нет ни одного пользователя"
|
||||
editProfile: "Редактировать профиль"
|
||||
noteDeleteConfirm: "Вы хотите удалить эту заметку?"
|
||||
pinLimitExceeded: "Нельзя закрепить ещё больше заметок"
|
||||
intro: "Установка Misskey завершена! А теперь создайте учетную запись администратора."
|
||||
done: "Готово"
|
||||
processing: "Обработка"
|
||||
preview: "Превью"
|
||||
preview: "Предпросмотр"
|
||||
default: "По умолчанию"
|
||||
noCustomEmojis: "Нет эмодзи"
|
||||
noCustomEmojis: "Эмодзи пользователя отсутствуют"
|
||||
noJobs: "Нет заданий"
|
||||
federating: "федеративный"
|
||||
federating: "Федерируется"
|
||||
blocked: "Заблокировано"
|
||||
suspended: "Приостановленный"
|
||||
all: "Все"
|
||||
all: "Всё"
|
||||
subscribing: "Подписка"
|
||||
publishing: "Публикация"
|
||||
notResponding: "Нет ответа"
|
||||
instanceFollowing: "Подписаться на инстанс"
|
||||
instanceFollowing: "Подписанные на инстансе"
|
||||
instanceFollowers: "Подписчики инстанса"
|
||||
instanceUsers: "Пользователи инстанса"
|
||||
changePassword: "Изменить пароль"
|
||||
security: "Безопасность"
|
||||
retypedNotMatch: "Нет совпадений"
|
||||
retypedNotMatch: "Не совпадают"
|
||||
currentPassword: "Текущий пароль"
|
||||
newPassword: "Новый пароль"
|
||||
newPasswordRetype: "Новый пароль (повторно):"
|
||||
newPasswordRetype: "Новый пароль (повторно)"
|
||||
attachFile: "Прикрепить файлы"
|
||||
more: "Ещё!"
|
||||
featured: "Рекомендуемые"
|
||||
usernameOrUserId: "Имя пользователя или ID"
|
||||
noSuchUser: "Пользователь не найден"
|
||||
lookup: "Подписка"
|
||||
announcements: "Уведомление"
|
||||
imageUrl: "URL-адрес изображения"
|
||||
featured: "Подборка"
|
||||
usernameOrUserId: "Имя или идентификатор пользователя"
|
||||
noSuchUser: "Таких пользователей не найдено"
|
||||
lookup: "Запрос"
|
||||
announcements: "Оповещения"
|
||||
imageUrl: "Ссылка на изображение"
|
||||
remove: "Удалить"
|
||||
removed: "Удалено"
|
||||
removeAreYouSure: "Хочешь удалить \"{x}\"?"
|
||||
removeAreYouSure: "Хотите удалить «{x}»?"
|
||||
saved: "Сохранено"
|
||||
messaging: "Сообщения"
|
||||
upload: "Загрузить"
|
||||
fromDrive: "С диска"
|
||||
fromUrl: "URL-адрес"
|
||||
fromDrive: "С «диска»"
|
||||
fromUrl: "По ссылке"
|
||||
uploadFromUrl: "Загрузить по ссылке"
|
||||
uploadFromUrlDescription: "URL-адрес файла, который вы хотите загрузить"
|
||||
uploadFromUrlRequested: "Загрузить запрос"
|
||||
uploadFromUrlDescription: "Ссылка на файл, который хотите загрузить"
|
||||
uploadFromUrlRequested: "Загрузка выбранного"
|
||||
uploadFromUrlMayTakeTime: "Загрузка может занять некоторое время."
|
||||
explore: "Обзор"
|
||||
games: "Игры Misskey"
|
||||
messageRead: "Прочитанных"
|
||||
noMoreHistory: "Истории больше нет"
|
||||
noMoreHistory: "История закончилась"
|
||||
startMessaging: "Отправить сообщение"
|
||||
nUsersRead: "прочитано {n}"
|
||||
agreeTo: "Я согласен с {0}"
|
||||
nUsersRead: "Прочитали {n}"
|
||||
agreeTo: "Я соглашаюсь с {0}"
|
||||
tos: "Пользовательское соглашение"
|
||||
start: "Начать"
|
||||
home: "Главная"
|
||||
remoteUserCaution: "Эта информация может быть неактуальной, так как пользователь является удаленным пользователем."
|
||||
remoteUserCaution: "Это пользователь с другого сайта, поэтому информация может быть неточной."
|
||||
activity: "Активность"
|
||||
images: "Изображение"
|
||||
images: "Изображения"
|
||||
birthday: "День рождения"
|
||||
yearsOld: "{age} лет"
|
||||
registeredDate: "Дата регистрации"
|
||||
location: "Местоположение"
|
||||
theme: "Тема"
|
||||
themeForLightMode: "Темы для использования в световом режиме"
|
||||
themeForDarkMode: "Темы для использования в темном режиме"
|
||||
themeForLightMode: "Тема для светлого режима"
|
||||
themeForDarkMode: "Тема для тёмного режима"
|
||||
light: "Светлый"
|
||||
dark: "Тёмный"
|
||||
lightThemes: "Светлые темы"
|
||||
@@ -270,7 +271,7 @@ copyUrl: "Копировать URL"
|
||||
rename: "Переименовать"
|
||||
avatar: "Иконка"
|
||||
banner: "Баннер"
|
||||
nsfw: "NSFW"
|
||||
nsfw: "Содержимое не для всех"
|
||||
whenServerDisconnected: "Когда соединение с сервером потеряно"
|
||||
disconnectedFromServer: "Разорвано соединение с сервером"
|
||||
reload: "Перезагрузить"
|
||||
@@ -350,7 +351,7 @@ userList: "Списки"
|
||||
about: "Описание"
|
||||
aboutMisskey: "О Misskey"
|
||||
aboutMisskeyText: "Misskey - это программное обеспечение с открытым исходным кодом, разрабатываемое syuilo с 2014 года."
|
||||
misskeyMembers: "В настоящее время он разрабатывается и поддерживается следующими членами:"
|
||||
misskeyMembers: "В настоящее время он разрабатывается и поддерживается следующими участниками:"
|
||||
misskeySource: "Исходный код доступен здесь:"
|
||||
misskeyTranslation: "Помогите нам перевести Misskey:"
|
||||
misskeyDonate: "Вы можете поддержать развитие, пожертвовав Misskey:"
|
||||
@@ -366,6 +367,7 @@ securityKeyName: "Имя ключа"
|
||||
registerSecurityKey: "Зарегистрировать защитный ключ"
|
||||
lastUsed: "Последнее использование"
|
||||
unregister: "Отписаться"
|
||||
passwordLessLogin: "Настроить вход без пароля"
|
||||
resetPassword: "Сброс пароля:"
|
||||
newPasswordIs: "Новый пароль - \"{пароль}\"."
|
||||
autoNoteWatch: "Автоматически просматривать записи"
|
||||
@@ -396,11 +398,12 @@ messagingWithGroup: "Чат в группе"
|
||||
title: "Заголовок."
|
||||
text: "Текст"
|
||||
enable: "Включить."
|
||||
next: "Следующий"
|
||||
next: "Дальше"
|
||||
retype: "Введите повторно"
|
||||
noteOf: "Посты {user}"
|
||||
inviteToGroup: "Пригласить в группу"
|
||||
maxNoteTextLength: "Максимальная длина текста"
|
||||
quoteAttached: "Цитата"
|
||||
quoteQuestion: "Хочешь добавить цитату?"
|
||||
noMessagesYet: "Сообщений нет"
|
||||
newMessageExists: "Новое сообщение"
|
||||
@@ -457,9 +460,14 @@ useObjectStorage: "Занято в хранилище"
|
||||
objectStorageBaseUrl: "Базовый URL-адрес"
|
||||
objectStorageBucket: "Bucket"
|
||||
objectStoragePrefix: "Префикс"
|
||||
objectStorageEndpoint: "Конечная точка"
|
||||
objectStorageRegion: "Регион"
|
||||
objectStorageUseSSL: "Использовать SSL"
|
||||
objectStorageUseProxy: "Использовать прокси"
|
||||
serverLogs: "Журнал сервера"
|
||||
deleteAll: "Удалить всё"
|
||||
showFixedPostForm: "Показывать поле для ввода новой заметки наверху ленты."
|
||||
newNoteRecived: "Есть новые посты"
|
||||
sounds: "Звуки"
|
||||
listen: "Слушать"
|
||||
none: "Ничего"
|
||||
@@ -488,6 +496,7 @@ disablePagesScript: "Отключение скриптов в Pages"
|
||||
deleteAllFiles: "Удалить все файлы"
|
||||
deleteAllFilesConfirm: "Вы хотите удалить все файлы?"
|
||||
removeAllFollowing: "Удалить всех подписчиков"
|
||||
removeAllFollowingDescription: "Отменить все подписки с домена {host}? Пожалуйста, применяйте это действие, если инстанс больше не существует."
|
||||
userSuspended: "Этот пользователь был заморожен"
|
||||
userSilenced: "Этот пользователь был заглушен"
|
||||
sidebar: "Боковая панель"
|
||||
@@ -506,6 +515,8 @@ themeEditor: "Редактор темы"
|
||||
description: "Описание"
|
||||
author: "Автор"
|
||||
plugins: "Плагины"
|
||||
deck: "Панель"
|
||||
undeck: "Покинуть панель"
|
||||
permission: "Разрешения"
|
||||
enableAll: "Включить все"
|
||||
disableAll: "Выключить всё"
|
||||
@@ -563,6 +574,7 @@ _channel:
|
||||
removeBanner: "Удалить баннер"
|
||||
featured: "В тренде"
|
||||
owned: "Владелец"
|
||||
following: "Читаю"
|
||||
usersCount: "{n} Участники"
|
||||
notesCount: "{n} Записи"
|
||||
_sidebar:
|
||||
@@ -608,34 +620,54 @@ _theme:
|
||||
link: "Ссылка"
|
||||
hashtag: "Хэштеги"
|
||||
mention: "Упоминание"
|
||||
mentionMe: "Упоминания вас"
|
||||
renote: "Репост"
|
||||
divider: "Разделительная полоса"
|
||||
infoBg: "Справочная информация"
|
||||
infoFg: "Текст информации"
|
||||
_sfx:
|
||||
note: "Посты"
|
||||
note: "Заметки"
|
||||
notification: "Уведомления"
|
||||
chat: "Сообщения"
|
||||
_ago:
|
||||
secondsAgo: "{} секунд назад"
|
||||
minutesAgo: "{} минут назад"
|
||||
unknown: "Когда-то"
|
||||
future: "Из будущего"
|
||||
justNow: "Только что"
|
||||
secondsAgo: "{n} с назад"
|
||||
minutesAgo: "{n} мин назад"
|
||||
hoursAgo: "{} часов назад"
|
||||
daysAgo: "{} дней назад"
|
||||
weeksAgo: "{} недель назад"
|
||||
monthsAgo: "{} месяцев назад"
|
||||
yearsAgo: "{} лет назад"
|
||||
daysAgo: "{n} сут назад"
|
||||
weeksAgo: "{n} нед. назад"
|
||||
monthsAgo: "{n} мес. назад"
|
||||
yearsAgo: "{n} г. назад"
|
||||
_time:
|
||||
second: "сек"
|
||||
minute: "Мин."
|
||||
second: "с"
|
||||
minute: "мин"
|
||||
hour: "ч"
|
||||
day: "сут"
|
||||
_tutorial:
|
||||
title: "Как пользоваться Misskey"
|
||||
step1_1: "Добро пожаловать!"
|
||||
step2_1: "Прежде чем создать заметку или следовать за кем-либо, сначала заполните свой профиль."
|
||||
step3_1: "Вы хорошо подготовили свой профиль?"
|
||||
step6_2: "Вы можете добавлять \"реакции\" к записям других людей, что облегчает общение с ними."
|
||||
step6_3: "Чтобы добавить реакцию, нажмите на знак \"+\" в записке и выберите нужную реакцию."
|
||||
step7_1: "На этом мы завершаем основные инструкции по использованию Misskey. Спасибо за вашу тяжёлую работу."
|
||||
step7_2: "Если вы хотите узнать больше о Misskey, посмотрите в {хелп}."
|
||||
step1_2: "Эта страница называется «лента». Здесь будут появляться ваши «заметки» и тех, на кого вы «подписаны», и располагаться в порядке времени их появления."
|
||||
step1_3: "Правда, ваша лента пока пуста. Она начнёт заполняться, когда вы будете писать свои заметки и подписываться на других."
|
||||
step2_1: "Давайте, сначала заполним профиль, прежде чем начать писать заметки и подписываться на других."
|
||||
step2_2: "То, что вы расскажете в профиле, поможет многим лучше вас узнать, а значит, им будет легче присоединиться к вам — подписаться и читать заметки."
|
||||
step3_1: "Успешно заполнили профиль?"
|
||||
step3_2: "Что ж, теперь самое время опубликуовать заметку. Если нажать вверху страницы на изображение карандаша, появится форма для текста."
|
||||
step3_3: "Напишите в неё, что хотите, и нажмите на кнопку в правом верхнем углу."
|
||||
step3_4: "Ничего не приходит в голову? Как насчёт: «я новенький, пока осваиваюсь в Misskey»?"
|
||||
step4_1: "С написанием первой заметки покончено?"
|
||||
step4_2: "Отлично, теперь она должна появиться в вашей ленте."
|
||||
step5_1: "А теперь самое время немного оживить ленту, подписавшись на других."
|
||||
step5_2: "На странице «{featured}» собраны популярные сегодня заметки, читая которые, вы можете найти кого-то вам интересного, а на «{explore}» можно посмотреть, кто популярен у остальных."
|
||||
step5_3: "Чтобы подписаться на кого-нибудь, щёлкните по его аватару и в открывшемся профиле нажмите кнопку «Подписаться»."
|
||||
step5_4: "Некоторые пользователи (около их имени «висит замок») вручную подтверждают чужие подписки. Так что иногда подписка начинает работать не сразу.\n"
|
||||
step6_1: "Если теперь в ленте видны и чужие заметки, значит у вас получилось."
|
||||
step6_2: "Можете ставить «реакции» чужим заметкам, чтобы непринуждённо выразить свои чувства к ним."
|
||||
step6_3: "Отмечайте реакции, нажмая на символ «+» под заметкой и выбирая значок по душе."
|
||||
step7_1: "На этом вводный урок по использованию Misskey закончен. Спасибо, что прошли его до конца!"
|
||||
step7_2: "Хотите изучить Misskey глубже — добро пожаловать в раздел «{help}»."
|
||||
step7_3: "Приятно вам провести время с Misskey🚀"
|
||||
_2fa:
|
||||
alreadyRegistered: "Настройка завершена"
|
||||
registerDevice: "Зарегистрируйте ваше устройство"
|
||||
@@ -645,32 +677,56 @@ _2fa:
|
||||
step4: "Когда вы войдете в систему, вы можете ввести свой токен тем же способом."
|
||||
securityKeyInfo: "Вы можете настроить вход с помощью аппаратного ключа безопасности, поддерживающего FIDO2, или отпечатка пальца или PIN-кода на устройстве."
|
||||
_permissions:
|
||||
"read:account": "Просмотр информации об аккаунте"
|
||||
"write:account": "Изменить информацию о вашем аккаунте"
|
||||
"write:blocks": "Отредактируйте список людей, которых вы заблокировали"
|
||||
"read:drive": "Доступ к файлам и папкам диска"
|
||||
"write:drive": "Редактирование или удаление файлов и папок диска"
|
||||
"read:favorites": "Просмотреть список избранных"
|
||||
"write:favorites": "Редактирование списка избранных"
|
||||
"read:messaging": "Просмотр сообщений"
|
||||
"read:mutes": "Просмотр скрытых пользователей"
|
||||
"write:mutes": "Изменение списка скрытых"
|
||||
"read:notifications": "Просмотреть уведомления"
|
||||
"write:reactions": "Редактировать реакции"
|
||||
"read:account": "Просматривать данные учётной записи"
|
||||
"write:account": "Изменять данные учётной записи"
|
||||
"read:blocks": "Смотреть список блокировок"
|
||||
"write:blocks": "Изменять список блокировок"
|
||||
"read:drive": "Смотреть содержимое «диска»"
|
||||
"write:drive": "Изменять содержимое «диска»"
|
||||
"read:favorites": "Смотреть список избранного"
|
||||
"write:favorites": "Изменять список избранного"
|
||||
"read:following": "Смотреть спискок подписок"
|
||||
"write:following": "Изменять спискок подписок"
|
||||
"read:messaging": "Смотреть сообщения"
|
||||
"write:messaging": "Писать и удалять сообщения"
|
||||
"read:mutes": "Смотреть спискок скрытых пользователей"
|
||||
"write:mutes": "Изменять список скрытых пользователей"
|
||||
"write:notes": "Писать и удалять заметки"
|
||||
"read:notifications": "Смотреть уведомления"
|
||||
"write:notifications": "Изменять уведомления"
|
||||
"read:reactions": "Смотреть реакции"
|
||||
"write:reactions": "Изменять реакции"
|
||||
"write:votes": "Голосовать"
|
||||
"read:pages": "Смотреть страницы"
|
||||
"write:pages": "Изменять и удалять страницы"
|
||||
"read:page-likes": "Смотреть добавления страниц в избранное"
|
||||
"write:page-likes": "Изменять добавления страниц в избранное"
|
||||
"read:user-groups": "Смотреть группы пользователей"
|
||||
"write:user-groups": "Изменять и удалять группы пользователей"
|
||||
"read:channels": "Смотреть каналы"
|
||||
"write:channels": "Изменять каналы"
|
||||
_auth:
|
||||
denied: "Доступ закрыт"
|
||||
_weekday:
|
||||
sunday: "Воскресенье"
|
||||
monday: "Понедельник"
|
||||
tuesday: "Вторник"
|
||||
wednesday: "Среда"
|
||||
thursday: "Четверг"
|
||||
friday: "Пятница"
|
||||
saturday: "Суббота"
|
||||
_widgets:
|
||||
memo: "Заметка"
|
||||
memo: "Напоминания"
|
||||
notifications: "Уведомления"
|
||||
timeline: "Лента"
|
||||
calendar: "Календарь"
|
||||
trends: "В тренде"
|
||||
trends: "Популярное"
|
||||
clock: "Часы"
|
||||
rss: "Ридер RSS"
|
||||
rss: "Просмотр RSS"
|
||||
activity: "Активность"
|
||||
photos: "Фото"
|
||||
digitalClock: "Цифровые Часы"
|
||||
federation: "Федиверс"
|
||||
digitalClock: "Цифровые часы"
|
||||
federation: "Федерация"
|
||||
postForm: "Форма отправки"
|
||||
_cw:
|
||||
hide: "Спрятать"
|
||||
@@ -678,43 +734,74 @@ _cw:
|
||||
chars: "{count} символов"
|
||||
files: "{count} файлов"
|
||||
_poll:
|
||||
noOnlyOneChoice: "Нужно как минимум два варианта."
|
||||
choiceN: "Выбрать{n}"
|
||||
canMultipleVote: "Возможны несколько вариантов ответов"
|
||||
expiration: "Истечение срока действия"
|
||||
infinite: "Неограниченное количество"
|
||||
deadlineDate: "Срок исполнения"
|
||||
deadlineTime: "Длительность"
|
||||
duration: "Продожительность"
|
||||
totalVotes: "Всего {n} голосов"
|
||||
noOnlyOneChoice: "Нужно хотя бы два варианта."
|
||||
choiceN: "Выбор {n}"
|
||||
noMore: "Больше вариантов добавить нельзя"
|
||||
canMultipleVote: "Можно выбрать несколько вариантов"
|
||||
expiration: "Опрос длится"
|
||||
infinite: "вечно"
|
||||
at: "до указанной даты"
|
||||
after: "заданное время"
|
||||
deadlineDate: "Дата окончания"
|
||||
deadlineTime: "Время"
|
||||
duration: "Длительность"
|
||||
votesCount: "Голосов: {n}"
|
||||
totalVotes: "Голосов всего: {n}"
|
||||
vote: "Проголосовать"
|
||||
showResult: "Смотреть результаты"
|
||||
voted: "Проголосовали"
|
||||
closed: "Завершено"
|
||||
remainingDays: "Осталось {d} сут {h} ч"
|
||||
remainingHours: "Осталось {h} ч {m} мин"
|
||||
remainingMinutes: "Осталось {m} мин {s} с"
|
||||
remainingSeconds: "Осталось {s} с"
|
||||
_visibility:
|
||||
public: "Публичный"
|
||||
publicDescription: "Открыт для всех пользователей"
|
||||
home: "Главная"
|
||||
followers: "Подписчики"
|
||||
specifiedDescription: "Отправлять сообщения только указанным пользователям"
|
||||
localOnly: "Только локально"
|
||||
localOnlyDescription: "Не видно удаленным пользователям"
|
||||
public: "Общедоступно"
|
||||
publicDescription: "Открыто для всех"
|
||||
home: "Домашняя"
|
||||
homeDescription: "Не появится в общих лентах (локальной и глобальной)"
|
||||
followers: "Для подписчиков"
|
||||
followersDescription: "Увидят только ваши подписчики"
|
||||
specified: "Личное"
|
||||
specifiedDescription: "Только для тех, кого укажете"
|
||||
localOnly: "Локально"
|
||||
localOnlyDescription: "Увидят только пользователи этого сайта"
|
||||
_postForm:
|
||||
replyPlaceholder: "Ответьте на эту запись..."
|
||||
quotePlaceholder: "Процитировать эту запись..."
|
||||
replyPlaceholder: "Ответ на заметку..."
|
||||
quotePlaceholder: "Пояснение к цитате..."
|
||||
channelPlaceholder: "Отправить в канал"
|
||||
_placeholders:
|
||||
a: "Что происходит?"
|
||||
a: "Как дела?"
|
||||
b: "Что интересного вокруг?"
|
||||
c: "Что грызёт тебя, дружище?"
|
||||
d: "Есть что сказать?.."
|
||||
e: "Напишите что-нибудь…"
|
||||
f: "В ожидании, когда вы напишете…"
|
||||
_profile:
|
||||
name: "Имя"
|
||||
username: "Имя пользователя"
|
||||
metadataContent: "Содержание"
|
||||
description: "О себе"
|
||||
youCanIncludeHashtags: "Можете использовать здесь хэштеги"
|
||||
metadata: "Всякое"
|
||||
metadataLabel: "Метка"
|
||||
metadataContent: "Содержимое"
|
||||
_exportOrImport:
|
||||
allNotes: "Все записи\n"
|
||||
followingList: "Подписки"
|
||||
muteList: "Скрыть"
|
||||
blockingList: "Заблокировать"
|
||||
muteList: "Скрытые"
|
||||
blockingList: "Заблокированные"
|
||||
userLists: "Списки"
|
||||
_charts:
|
||||
federationInstancesIncDec: "Изменение внешних связей"
|
||||
federationInstancesTotal: "Количество внешних связей"
|
||||
usersIncDec: "Изменение числа пользователей"
|
||||
usersTotal: "Количество пользователей"
|
||||
activeUsers: "Активные пользователи"
|
||||
notesIncDec: "Изменение числа заметок"
|
||||
localNotesIncDec: "Изменения числа локальных заметок"
|
||||
_instanceCharts:
|
||||
users: "Изменение числа пользователей"
|
||||
notes: "Изменение числа заметок"
|
||||
_timelines:
|
||||
home: "Главная"
|
||||
_rooms:
|
||||
@@ -727,20 +814,21 @@ _rooms:
|
||||
server: "Сервер"
|
||||
monitor: "Монитор"
|
||||
_pages:
|
||||
viewPage: "Смотреть страницы"
|
||||
title: "Заголовок."
|
||||
url: "URL страницы"
|
||||
hideTitleWhenPinned: "Скрыть заголовок страницы при привязке к профилю"
|
||||
font: "Шрифт"
|
||||
blocks:
|
||||
section: "Раздел"
|
||||
image: "Изображение"
|
||||
image: "Изображения"
|
||||
button: "Кнопка"
|
||||
if: "Если"
|
||||
_if:
|
||||
variable: "Переменная"
|
||||
post: "Форма отправки"
|
||||
_post:
|
||||
text: "Содержание"
|
||||
text: "Содержимое"
|
||||
textInput: "Ввод текста"
|
||||
_textInput:
|
||||
name: "Имя переменной"
|
||||
@@ -766,7 +854,7 @@ _pages:
|
||||
text: "Заголовок."
|
||||
_action:
|
||||
_dialog:
|
||||
content: "Содержание"
|
||||
content: "Содержимое"
|
||||
_pushEvent:
|
||||
no-variable: "Не найдено"
|
||||
callAiScript: "Справка AiScript"
|
||||
@@ -867,8 +955,9 @@ _pages:
|
||||
types:
|
||||
array: "Списки"
|
||||
_notification:
|
||||
youWereFollowed: "Новый подписчик"
|
||||
youReceivedFollowRequest: "Запрос на подписку"
|
||||
youWereFollowed: "У вас новый подписчик"
|
||||
youReceivedFollowRequest: "У вас новый запрос на подписку"
|
||||
yourFollowRequestAccepted: "Ваш запрос на подписку одобрен"
|
||||
youWereInvitedToGroup: "Приглашение в группу"
|
||||
_types:
|
||||
follow: "Подписки"
|
||||
@@ -876,6 +965,8 @@ _notification:
|
||||
renote: "Репост"
|
||||
quote: "Цитата"
|
||||
reaction: "Реакции"
|
||||
receiveFollowRequest: "Получен запрос на подписку"
|
||||
followRequestAccepted: "Запрос на подписку одобрен"
|
||||
app: "Уведомления из приложений"
|
||||
_deck:
|
||||
alwaysShowMainColumn: "Всегда показывать главную колонку"
|
||||
@@ -892,3 +983,4 @@ _deck:
|
||||
antenna: "Антенны"
|
||||
list: "Списки"
|
||||
mentions: "Упоминания"
|
||||
direct: "Личное"
|
||||
|
@@ -11,7 +11,7 @@ export class refineAbuseUserReport1603094348345 implements MigrationInterface {
|
||||
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD "assigneeId" character varying(32)`);
|
||||
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD "resolved" boolean NOT NULL DEFAULT false`);
|
||||
await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP COLUMN "comment"`);
|
||||
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD "comment" character varying(2048) NOT NULL`);
|
||||
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD "comment" character varying(2048) NOT NULL DEFAULT '{}'::varchar[]`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_2b15aaf4a0dc5be3499af7ab6a" ON "abuse_user_report" ("resolved") `);
|
||||
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD CONSTRAINT "FK_08b883dd5fdd6f9c4c1572b36de" FOREIGN KEY ("assigneeId") REFERENCES "user"("id") ON DELETE SET NULL ON UPDATE NO ACTION`);
|
||||
}
|
||||
@@ -20,7 +20,7 @@ export class refineAbuseUserReport1603094348345 implements MigrationInterface {
|
||||
await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP CONSTRAINT "FK_08b883dd5fdd6f9c4c1572b36de"`);
|
||||
await queryRunner.query(`DROP INDEX "IDX_2b15aaf4a0dc5be3499af7ab6a"`);
|
||||
await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP COLUMN "comment"`);
|
||||
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD "comment" character varying(512) NOT NULL`);
|
||||
await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD "comment" character varying(512) NOT NULL DEFAULT '{}'::varchar[]`);
|
||||
await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP COLUMN "resolved"`);
|
||||
await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP COLUMN "assigneeId"`);
|
||||
await queryRunner.query(`ALTER TABLE "abuse_user_report" RENAME COLUMN "targetUserId" TO "userId"`);
|
||||
|
10
package.json
10
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"author": "syuilo <syuilotan@yahoo.co.jp>",
|
||||
"version": "12.49.1",
|
||||
"version": "12.50.0",
|
||||
"codename": "indigo",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -190,7 +190,7 @@
|
||||
"parsimmon": "1.16.0",
|
||||
"pg": "8.4.1",
|
||||
"portscanner": "2.2.0",
|
||||
"postcss": "8.1.2",
|
||||
"postcss": "8.1.3",
|
||||
"postcss-loader": "4.0.4",
|
||||
"prismjs": "1.22.0",
|
||||
"probe-image-size": "5.0.0",
|
||||
@@ -216,7 +216,7 @@
|
||||
"rndstr": "1.0.0",
|
||||
"s-age": "1.1.2",
|
||||
"sass": "1.27.0",
|
||||
"sass-loader": "10.0.3",
|
||||
"sass-loader": "10.0.4",
|
||||
"seedrandom": "3.0.5",
|
||||
"sharp": "0.26.2",
|
||||
"speakeasy": "2.0.0",
|
||||
@@ -224,7 +224,7 @@
|
||||
"style-loader": "2.0.0",
|
||||
"summaly": "2.4.0",
|
||||
"syslog-pro": "1.0.0",
|
||||
"systeminformation": "4.27.8",
|
||||
"systeminformation": "4.27.10",
|
||||
"syuilo-password-strength": "0.0.1",
|
||||
"textarea-caret": "3.1.0",
|
||||
"three": "0.117.1",
|
||||
@@ -253,7 +253,7 @@
|
||||
"vuex": "4.0.0-beta.4",
|
||||
"vuex-persistedstate": "3.1.0",
|
||||
"web-push": "3.4.4",
|
||||
"webpack": "5.1.3",
|
||||
"webpack": "5.2.0",
|
||||
"webpack-cli": "4.1.0",
|
||||
"websocket": "1.0.32",
|
||||
"ws": "7.3.1",
|
||||
|
@@ -2,9 +2,9 @@
|
||||
<span class="eiwwqkts" :class="{ cat }" :title="acct(user)" v-if="disableLink" v-user-preview="disablePreview ? undefined : user.id" @click="onClick">
|
||||
<img class="inner" :src="url"/>
|
||||
</span>
|
||||
<router-link class="eiwwqkts" :class="{ cat }" :to="userPage(user)" :title="acct(user)" :target="target" v-else v-user-preview="disablePreview ? undefined : user.id">
|
||||
<MkA class="eiwwqkts" :class="{ cat }" :to="userPage(user)" :title="acct(user)" :target="target" v-else v-user-preview="disablePreview ? undefined : user.id">
|
||||
<img class="inner" :src="url"/>
|
||||
</router-link>
|
||||
</MkA>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<router-link :to="`/channels/${channel.id}`" class="eftoefju _panel" tabindex="-1">
|
||||
<MkA :to="`/channels/${channel.id}`" class="eftoefju _panel" tabindex="-1">
|
||||
<div class="banner" v-if="channel.bannerUrl" :style="`background-image: url('${channel.bannerUrl}')`">
|
||||
<div class="fade"></div>
|
||||
<div class="name"><Fa :icon="faSatelliteDish"/> {{ channel.name }}</div>
|
||||
@@ -30,7 +30,7 @@
|
||||
{{ $t('updatedAt') }}: <MkTime :time="channel.lastNotedAt"/>
|
||||
</span>
|
||||
</footer>
|
||||
</router-link>
|
||||
</MkA>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import { App } from 'vue';
|
||||
|
||||
import mfm from './misskey-flavored-markdown.vue';
|
||||
import a from './ui/a.vue';
|
||||
import acct from './acct.vue';
|
||||
import avatar from './avatar.vue';
|
||||
import emoji from './emoji.vue';
|
||||
@@ -10,10 +11,10 @@ import time from './time.vue';
|
||||
import url from './url.vue';
|
||||
import loading from './loading.vue';
|
||||
import error from './error.vue';
|
||||
import streamIndicator from './stream-indicator.vue';
|
||||
|
||||
export default function(app: App) {
|
||||
app.component('Mfm', mfm);
|
||||
app.component('MkA', a);
|
||||
app.component('MkAcct', acct);
|
||||
app.component('MkAvatar', avatar);
|
||||
app.component('MkEmoji', emoji);
|
||||
@@ -23,5 +24,4 @@ export default function(app: App) {
|
||||
app.component('MkUrl', url);
|
||||
app.component('MkLoading', loading);
|
||||
app.component('MkError', error);
|
||||
app.component('StreamIndicator', streamIndicator);
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<component :is="self ? 'router-link' : 'a'" class="xlcxczvw _link" :[attr]="self ? url.substr(local.length) : url" :rel="rel" :target="target"
|
||||
<component :is="self ? 'MkA' : 'a'" class="xlcxczvw _link" :[attr]="self ? url.substr(local.length) : url" :rel="rel" :target="target"
|
||||
@mouseover="onMouseover"
|
||||
@mouseleave="onMouseleave"
|
||||
:title="url"
|
||||
|
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<router-link class="ldlomzub" :class="{ isMe }" :to="url" v-user-preview="canonical" v-if="url.startsWith('/')">
|
||||
<MkA class="ldlomzub" :class="{ isMe }" :to="url" v-user-preview="canonical" v-if="url.startsWith('/')">
|
||||
<span class="me" v-if="isMe">{{ $t('you') }}</span>
|
||||
<span class="main">
|
||||
<span class="username">@{{ username }}</span>
|
||||
<span class="host" v-if="(host != localHost) || $store.state.settings.showFullAcct">@{{ toUnicode(host) }}</span>
|
||||
</span>
|
||||
</router-link>
|
||||
</MkA>
|
||||
<a class="ldlomzub" :href="url" target="_blank" rel="noopener" v-else>
|
||||
<span class="main">
|
||||
<span class="username">@{{ username }}</span>
|
||||
|
@@ -9,8 +9,8 @@ import { concat } from '../../prelude/array';
|
||||
import MkFormula from './formula.vue';
|
||||
import MkCode from './code.vue';
|
||||
import MkGoogle from './google.vue';
|
||||
import MkA from './ui/a.vue';
|
||||
import { host } from '@/config';
|
||||
import { RouterLink } from 'vue-router';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
@@ -150,7 +150,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
case 'hashtag': {
|
||||
return [h(RouterLink, {
|
||||
return [h(MkA, {
|
||||
key: Math.random(),
|
||||
to: this.isNote ? `/tags/${encodeURIComponent(token.node.props.hashtag)}` : `/explore/tags/${encodeURIComponent(token.node.props.hashtag)}`,
|
||||
style: 'color:var(--hashtag);'
|
||||
|
@@ -1,17 +1,17 @@
|
||||
<template>
|
||||
<header class="kkwtjztg">
|
||||
<router-link class="name" :to="userPage(note.user)" v-user-preview="note.user.id">
|
||||
<MkA class="name" :to="userPage(note.user)" v-user-preview="note.user.id">
|
||||
<MkUserName :user="note.user"/>
|
||||
</router-link>
|
||||
</MkA>
|
||||
<span class="is-bot" v-if="note.user.isBot">bot</span>
|
||||
<span class="username"><MkAcct :user="note.user"/></span>
|
||||
<span class="admin" v-if="note.user.isAdmin"><Fa :icon="faBookmark"/></span>
|
||||
<span class="moderator" v-if="!note.user.isAdmin && note.user.isModerator"><Fa :icon="farBookmark"/></span>
|
||||
<div class="info">
|
||||
<span class="mobile" v-if="note.viaMobile"><Fa :icon="faMobileAlt"/></span>
|
||||
<router-link class="created-at" :to="notePage(note)">
|
||||
<MkA class="created-at" :to="notePage(note)">
|
||||
<MkTime :time="note.createdAt"/>
|
||||
</router-link>
|
||||
</MkA>
|
||||
<span class="visibility" v-if="note.visibility !== 'public'">
|
||||
<Fa v-if="note.visibility === 'home'" :icon="faHome"/>
|
||||
<Fa v-if="note.visibility === 'followers'" :icon="faUnlock"/>
|
||||
|
@@ -18,9 +18,9 @@
|
||||
<Fa :icon="faRetweet"/>
|
||||
<i18n-t keypath="renotedBy" tag="span">
|
||||
<template #user>
|
||||
<router-link class="name" :to="userPage(note.user)" v-user-preview="note.userId">
|
||||
<MkA class="name" :to="userPage(note.user)" v-user-preview="note.userId">
|
||||
<MkUserName :user="note.user"/>
|
||||
</router-link>
|
||||
</MkA>
|
||||
</template>
|
||||
</i18n-t>
|
||||
<div class="info">
|
||||
@@ -48,7 +48,7 @@
|
||||
<div class="content" v-show="appearNote.cw == null || showContent">
|
||||
<div class="text">
|
||||
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ $t('private') }})</span>
|
||||
<router-link class="reply" v-if="appearNote.replyId" :to="`/notes/${appearNote.replyId}`"><Fa :icon="faReply"/></router-link>
|
||||
<MkA class="reply" v-if="appearNote.replyId" :to="`/notes/${appearNote.replyId}`"><Fa :icon="faReply"/></MkA>
|
||||
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$store.state.i" :custom-emojis="appearNote.emojis"/>
|
||||
<a class="rp" v-if="appearNote.renote != null">RN:</a>
|
||||
</div>
|
||||
@@ -59,7 +59,7 @@
|
||||
<MkUrlPreview v-for="url in urls" :url="url" :key="url" :compact="true" :detail="detail" class="url-preview"/>
|
||||
<div class="renote" v-if="appearNote.renote"><XNotePreview :note="appearNote.renote"/></div>
|
||||
</div>
|
||||
<router-link v-if="appearNote.channel && !inChannel" class="channel" :to="`/channels/${appearNote.channel.id}`"><Fa :icon="faSatelliteDish"/> {{ appearNote.channel.name }}</router-link>
|
||||
<MkA v-if="appearNote.channel && !inChannel" class="channel" :to="`/channels/${appearNote.channel.id}`"><Fa :icon="faSatelliteDish"/> {{ appearNote.channel.name }}</MkA>
|
||||
</div>
|
||||
<footer class="footer">
|
||||
<XReactionsViewer :note="appearNote" ref="reactionsViewer"/>
|
||||
@@ -91,9 +91,9 @@
|
||||
<div v-else class="_panel muted" @click="muted = false">
|
||||
<i18n-t keypath="userSaysSomething" tag="small">
|
||||
<template #name>
|
||||
<router-link class="name" :to="userPage(appearNote.user)" v-user-preview="appearNote.userId">
|
||||
<MkA class="name" :to="userPage(appearNote.user)" v-user-preview="appearNote.userId">
|
||||
<MkUserName :user="appearNote.user"/>
|
||||
</router-link>
|
||||
</MkA>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</div>
|
||||
@@ -144,7 +144,7 @@ export default defineComponent({
|
||||
inject: {
|
||||
inChannel: {
|
||||
default: null
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
props: {
|
||||
@@ -581,11 +581,6 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
menu = [{
|
||||
type: 'link',
|
||||
icon: faInfoCircle,
|
||||
text: this.$t('details'),
|
||||
to: '/notes/' + this.appearNote.id
|
||||
}, null, {
|
||||
icon: faCopy,
|
||||
text: this.$t('copyContent'),
|
||||
action: this.copyContent
|
||||
|
@@ -18,34 +18,34 @@
|
||||
</div>
|
||||
<div class="tail">
|
||||
<header>
|
||||
<router-link v-if="notification.user" class="name" :to="userPage(notification.user)" v-user-preview="notification.user.id"><MkUserName :user="notification.user"/></router-link>
|
||||
<MkA v-if="notification.user" class="name" :to="userPage(notification.user)" v-user-preview="notification.user.id"><MkUserName :user="notification.user"/></MkA>
|
||||
<span v-else>{{ notification.header }}</span>
|
||||
<MkTime :time="notification.createdAt" v-if="withTime"/>
|
||||
</header>
|
||||
<router-link v-if="notification.type === 'reaction'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||
<MkA v-if="notification.type === 'reaction'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||
<Fa :icon="faQuoteLeft"/>
|
||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.emojis"/>
|
||||
<Fa :icon="faQuoteRight"/>
|
||||
</router-link>
|
||||
<router-link v-if="notification.type === 'renote'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note.renote)">
|
||||
</MkA>
|
||||
<MkA v-if="notification.type === 'renote'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note.renote)">
|
||||
<Fa :icon="faQuoteLeft"/>
|
||||
<Mfm :text="getNoteSummary(notification.note.renote)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.renote.emojis"/>
|
||||
<Fa :icon="faQuoteRight"/>
|
||||
</router-link>
|
||||
<router-link v-if="notification.type === 'reply'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||
</MkA>
|
||||
<MkA v-if="notification.type === 'reply'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.emojis"/>
|
||||
</router-link>
|
||||
<router-link v-if="notification.type === 'mention'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||
</MkA>
|
||||
<MkA v-if="notification.type === 'mention'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.emojis"/>
|
||||
</router-link>
|
||||
<router-link v-if="notification.type === 'quote'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||
</MkA>
|
||||
<MkA v-if="notification.type === 'quote'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.emojis"/>
|
||||
</router-link>
|
||||
<router-link v-if="notification.type === 'pollVote'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||
</MkA>
|
||||
<MkA v-if="notification.type === 'pollVote'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||
<Fa :icon="faQuoteLeft"/>
|
||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.emojis"/>
|
||||
<Fa :icon="faQuoteRight"/>
|
||||
</router-link>
|
||||
</MkA>
|
||||
<span v-if="notification.type === 'follow'" class="text" style="opacity: 0.6;">{{ $t('youGotNewFollower') }}<div v-if="full"><MkFollowButton :user="notification.user" :full="true"/></div></span>
|
||||
<span v-if="notification.type === 'followRequestAccepted'" class="text" style="opacity: 0.6;">{{ $t('followRequestAccepted') }}</span>
|
||||
<span v-if="notification.type === 'receiveFollowRequest'" class="text" style="opacity: 0.6;">{{ $t('receiveFollowRequest') }}<div v-if="full && !followRequestDone"><button class="_textButton" @click="acceptFollowRequest()">{{ $t('accept') }}</button> | <button class="_textButton" @click="rejectFollowRequest()">{{ $t('reject') }}</button></div></span>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<router-link :to="`/@${page.user.username}/pages/${page.name}`" class="vhpxefrj" tabindex="-1">
|
||||
<MkA :to="`/@${page.user.username}/pages/${page.name}`" class="vhpxefrj" tabindex="-1">
|
||||
<div class="thumbnail" v-if="page.eyeCatchingImage" :style="`background-image: url('${page.eyeCatchingImage.thumbnailUrl}')`"></div>
|
||||
<article>
|
||||
<header>
|
||||
@@ -11,7 +11,7 @@
|
||||
<p>{{ userName(page.user) }}</p>
|
||||
</footer>
|
||||
</article>
|
||||
</router-link>
|
||||
</MkA>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@@ -1,11 +1,18 @@
|
||||
<template>
|
||||
<XWindow ref="window" :initial-width="400" :initial-height="500" :can-resize="true" @closed="$emit('closed')">
|
||||
<XWindow ref="window"
|
||||
:initial-width="400"
|
||||
:initial-height="500"
|
||||
:can-resize="true"
|
||||
:close-right="true"
|
||||
:contextmenu="contextmenu"
|
||||
@closed="$emit('closed')"
|
||||
>
|
||||
<template #header>
|
||||
<XHeader :info="pageInfo" :with-back="false"/>
|
||||
</template>
|
||||
<template #buttons>
|
||||
<button class="_button" @click="expand" v-tooltip="$t('showInPage')"><Fa :icon="faExpandAlt"/></button>
|
||||
<button class="_button" @click="popout" v-tooltip="$t('popout')"><Fa :icon="faExternalLinkAlt"/></button>
|
||||
<button class="_button" @click="back()" v-if="history.length > 0"><Fa :icon="faChevronLeft"/></button>
|
||||
<button class="_button" style="pointer-events: none;" v-else><!-- マージンのバランスを取るためのダミー --></button>
|
||||
</template>
|
||||
<div class="yrolvcoq" style="min-height: 100%; background: var(--bg);">
|
||||
<component :is="component" v-bind="props" :ref="changePage"/>
|
||||
@@ -14,11 +21,13 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, markRaw } from 'vue';
|
||||
import { faExternalLinkAlt, faExpandAlt } from '@fortawesome/free-solid-svg-icons';
|
||||
import { defineComponent } from 'vue';
|
||||
import { faExternalLinkAlt, faExpandAlt, faLink, faChevronLeft } from '@fortawesome/free-solid-svg-icons';
|
||||
import XWindow from '@/components/ui/window.vue';
|
||||
import XHeader from '@/ui/_common_/header.vue';
|
||||
import { popout } from '@/scripts/popout';
|
||||
import copyToClipboard from '@/scripts/copy-to-clipboard';
|
||||
import { resolve } from '@/router';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@@ -26,6 +35,14 @@ export default defineComponent({
|
||||
XHeader,
|
||||
},
|
||||
|
||||
provide() {
|
||||
return {
|
||||
navHook: (url) => {
|
||||
this.navigate(url);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
props: {
|
||||
initialUrl: {
|
||||
type: String,
|
||||
@@ -38,7 +55,7 @@ export default defineComponent({
|
||||
initialProps: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: {},
|
||||
default: () => {},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -50,18 +67,39 @@ export default defineComponent({
|
||||
url: this.initialUrl,
|
||||
component: this.initialComponent,
|
||||
props: this.initialProps,
|
||||
faExternalLinkAlt, faExpandAlt,
|
||||
history: [],
|
||||
faChevronLeft,
|
||||
};
|
||||
},
|
||||
|
||||
provide() {
|
||||
return {
|
||||
navHook: (url, component, props) => {
|
||||
this.url = url;
|
||||
this.component = markRaw(component);
|
||||
this.props = props;
|
||||
}
|
||||
};
|
||||
computed: {
|
||||
contextmenu() {
|
||||
return [{
|
||||
type: 'label',
|
||||
text: this.url,
|
||||
}, {
|
||||
icon: faExpandAlt,
|
||||
text: this.$t('showInPage'),
|
||||
action: this.expand
|
||||
}, {
|
||||
icon: faExternalLinkAlt,
|
||||
text: this.$t('popout'),
|
||||
action: this.popout
|
||||
}, null, {
|
||||
icon: faExternalLinkAlt,
|
||||
text: this.$t('openInNewTab'),
|
||||
action: () => {
|
||||
window.open(this.url, '_blank');
|
||||
this.$refs.window.close();
|
||||
}
|
||||
}, {
|
||||
icon: faLink,
|
||||
text: this.$t('copyLink'),
|
||||
action: () => {
|
||||
copyToClipboard(this.url);
|
||||
}
|
||||
}];
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
@@ -72,6 +110,18 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
|
||||
navigate(url, record = true) {
|
||||
if (record) this.history.push(this.url);
|
||||
this.url = url;
|
||||
const { component, props } = resolve(url);
|
||||
this.component = component;
|
||||
this.props = props;
|
||||
},
|
||||
|
||||
back() {
|
||||
this.navigate(this.history.pop(), false);
|
||||
},
|
||||
|
||||
expand() {
|
||||
this.$router.push(this.url);
|
||||
this.$refs.window.close();
|
||||
|
@@ -17,12 +17,12 @@
|
||||
<button class="item _button index active" @click="top()" v-if="$route.name === 'index'">
|
||||
<Fa :icon="faHome" fixed-width/><span class="text">{{ $store.getters.isSignedIn ? $t('timeline') : $t('home') }}</span>
|
||||
</button>
|
||||
<router-link class="item index" active-class="active" to="/" exact v-else>
|
||||
<MkA class="item index" active-class="active" to="/" exact v-else>
|
||||
<Fa :icon="faHome" fixed-width/><span class="text">{{ $store.getters.isSignedIn ? $t('timeline') : $t('home') }}</span>
|
||||
</router-link>
|
||||
</MkA>
|
||||
<template v-for="item in menu">
|
||||
<div v-if="item === '-'" class="divider"></div>
|
||||
<component v-else-if="menuDef[item] && (menuDef[item].show !== false)" :is="menuDef[item].to ? 'router-link' : 'button'" class="item _button" :class="item" active-class="active" v-on="menuDef[item].action ? { click: menuDef[item].action } : {}" :to="menuDef[item].to">
|
||||
<component v-else-if="menuDef[item] && (menuDef[item].show !== false)" :is="menuDef[item].to ? 'MkA' : 'button'" class="item _button" :class="item" active-class="active" v-on="menuDef[item].action ? { click: menuDef[item].action } : {}" :to="menuDef[item].to">
|
||||
<Fa :icon="menuDef[item].icon" fixed-width/><span class="text">{{ $t(menuDef[item].title) }}</span>
|
||||
<i v-if="menuDef[item].indicated"><Fa :icon="faCircle"/></i>
|
||||
</component>
|
||||
@@ -35,9 +35,9 @@
|
||||
<Fa :icon="faEllipsisH" fixed-width/><span class="text">{{ $t('more') }}</span>
|
||||
<i v-if="otherNavItemIndicated"><Fa :icon="faCircle"/></i>
|
||||
</button>
|
||||
<router-link class="item" active-class="active" to="/settings">
|
||||
<MkA class="item" active-class="active" to="/settings">
|
||||
<Fa :icon="faCog" fixed-width/><span class="text">{{ $t('settings') }}</span>
|
||||
</router-link>
|
||||
</MkA>
|
||||
</div>
|
||||
</nav>
|
||||
</transition>
|
||||
|
@@ -3,9 +3,9 @@
|
||||
<div class="body">
|
||||
<span v-if="note.isHidden" style="opacity: 0.5">({{ $t('private') }})</span>
|
||||
<span v-if="note.deletedAt" style="opacity: 0.5">({{ $t('deleted') }})</span>
|
||||
<router-link class="reply" v-if="note.replyId" :to="`/notes/${note.replyId}`"><Fa :icon="faReply"/></router-link>
|
||||
<MkA class="reply" v-if="note.replyId" :to="`/notes/${note.replyId}`"><Fa :icon="faReply"/></MkA>
|
||||
<Mfm v-if="note.text" :text="note.text" :author="note.user" :i="$store.state.i" :custom-emojis="note.emojis"/>
|
||||
<router-link class="rp" v-if="note.renoteId" :to="`/notes/${note.renoteId}`">RN: ...</router-link>
|
||||
<MkA class="rp" v-if="note.renoteId" :to="`/notes/${note.renoteId}`">RN: ...</MkA>
|
||||
</div>
|
||||
<details v-if="note.files.length > 0">
|
||||
<summary>({{ $t('withNFiles', { n: note.files.length }) }})</summary>
|
||||
|
104
src/client/components/ui/a.vue
Normal file
104
src/client/components/ui/a.vue
Normal file
@@ -0,0 +1,104 @@
|
||||
<template>
|
||||
<a :href="to" :class="active ? activeClass : null" @click.prevent="nav" @contextmenu.prevent.stop="onContextmenu">
|
||||
<slot></slot>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { faExpandAlt, faColumns, faExternalLinkAlt, faLink, faWindowMaximize } from '@fortawesome/free-solid-svg-icons';
|
||||
import * as os from '@/os';
|
||||
import copyToClipboard from '@/scripts/copy-to-clipboard';
|
||||
import { router } from '@/router';
|
||||
import { deckmode } from '@/config';
|
||||
|
||||
export default defineComponent({
|
||||
inject: {
|
||||
navHook: {
|
||||
default: null
|
||||
},
|
||||
sideViewHook: {
|
||||
default: null
|
||||
}
|
||||
},
|
||||
|
||||
props: {
|
||||
to: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
activeClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
active() {
|
||||
if (this.activeClass == null) return false;
|
||||
const resolved = router.resolve(this.to);
|
||||
if (resolved.path == this.$route.path) return true;
|
||||
if (resolved.name == null) return false;
|
||||
if (this.$route.name == null) return false;
|
||||
return resolved.name == this.$route.name;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onContextmenu(e) {
|
||||
if (window.getSelection().toString() !== '') return;
|
||||
os.contextMenu([{
|
||||
type: 'label',
|
||||
text: this.to,
|
||||
}, {
|
||||
icon: faWindowMaximize,
|
||||
text: this.$t('openInWindow'),
|
||||
action: () => {
|
||||
os.pageWindow(this.to);
|
||||
}
|
||||
}, !this.navHook && this.sideViewHook ? {
|
||||
icon: faColumns,
|
||||
text: this.$t('openInSideView'),
|
||||
action: () => {
|
||||
this.sideViewHook(this.to);
|
||||
}
|
||||
} : undefined, {
|
||||
icon: faExpandAlt,
|
||||
text: this.$t('showInPage'),
|
||||
action: () => {
|
||||
this.$router.push(this.to);
|
||||
}
|
||||
}, null, {
|
||||
icon: faExternalLinkAlt,
|
||||
text: this.$t('openInNewTab'),
|
||||
action: () => {
|
||||
window.open(this.to, '_blank');
|
||||
}
|
||||
}, {
|
||||
icon: faLink,
|
||||
text: this.$t('copyLink'),
|
||||
action: () => {
|
||||
copyToClipboard(this.to);
|
||||
}
|
||||
}], e);
|
||||
},
|
||||
|
||||
nav() {
|
||||
if (this.navHook) {
|
||||
this.navHook(this.to);
|
||||
} else {
|
||||
if (this.$store.state.device.defaultSideView && this.sideViewHook && this.to !== '/') {
|
||||
this.sideViewHook(this.to);
|
||||
return;
|
||||
}
|
||||
if (this.$store.state.device.deckNavWindow && deckmode && this.to !== '/') {
|
||||
os.pageWindow(this.to);
|
||||
return;
|
||||
}
|
||||
|
||||
this.$router.push(this.to);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="nvlagfpb">
|
||||
<div class="nvlagfpb" @contextmenu.prevent.stop="() => {}">
|
||||
<MkMenu :items="items" @close="$emit('closed')" class="_popup _shadow" :align="'left'"/>
|
||||
</div>
|
||||
</template>
|
||||
|
@@ -12,12 +12,12 @@
|
||||
<span v-else-if="item.type === 'pending'" :tabindex="i" class="pending item">
|
||||
<span><MkEllipsis/></span>
|
||||
</span>
|
||||
<router-link v-else-if="item.type === 'link'" :to="item.to" @click.passive="close()" :tabindex="i" class="_button item">
|
||||
<MkA v-else-if="item.type === 'link'" :to="item.to" @click.passive="close()" :tabindex="i" class="_button item">
|
||||
<Fa v-if="item.icon" :icon="item.icon" fixed-width/>
|
||||
<MkAvatar v-if="item.avatar" :user="item.avatar" class="avatar"/>
|
||||
<span>{{ item.text }}</span>
|
||||
<i v-if="item.indicate"><Fa :icon="faCircle"/></i>
|
||||
</router-link>
|
||||
</MkA>
|
||||
<a v-else-if="item.type === 'a'" :href="item.href" :target="item.target" :download="item.download" @click="close()" :tabindex="i" class="_button item">
|
||||
<Fa v-if="item.icon" :icon="item.icon" fixed-width/>
|
||||
<span>{{ item.text }}</span>
|
||||
|
@@ -51,7 +51,7 @@ export default defineComponent({
|
||||
.novjtctn {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin: 0 32px 0 0;
|
||||
margin: 16px 32px 0 0;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
|
||||
|
@@ -2,12 +2,13 @@
|
||||
<div class="adhpbeos" :class="{ focused, filled, tall, pre }">
|
||||
<div class="input">
|
||||
<span class="label" ref="label"><slot></slot></span>
|
||||
<textarea ref="input"
|
||||
<textarea ref="input" :class="{ code }"
|
||||
:value="value"
|
||||
:required="required"
|
||||
:readonly="readonly"
|
||||
:pattern="pattern"
|
||||
:autocomplete="autocomplete"
|
||||
:spellcheck="!code"
|
||||
@input="onInput"
|
||||
@focus="focused = true"
|
||||
@blur="focused = false"
|
||||
@@ -20,7 +21,6 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import * as os from '@/os';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
@@ -43,6 +43,10 @@ export default defineComponent({
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
code: {
|
||||
type: Boolean,
|
||||
required: false
|
||||
},
|
||||
tall: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
@@ -159,6 +163,11 @@ export default defineComponent({
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
color: var(--fg);
|
||||
|
||||
&.code {
|
||||
tab-size: 2;
|
||||
font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -2,14 +2,16 @@
|
||||
<transition :name="$store.state.device.animation ? 'window' : ''" appear @after-leave="$emit('closed')">
|
||||
<div class="ebkgocck" v-if="showing">
|
||||
<div class="body _popup _shadow _narrow_" @mousedown="onBodyMousedown" @keydown="onKeydown">
|
||||
<div class="header">
|
||||
<button class="_button" @click="close()"><Fa :icon="faTimes"/></button>
|
||||
<div class="header" @contextmenu.prevent.stop="onContextmenu">
|
||||
<slot v-if="closeRight" name="buttons"><button class="_button" style="pointer-events: none;"></button></slot>
|
||||
<button v-else class="_button" @click="close()"><Fa :icon="faTimes"/></button>
|
||||
|
||||
<span class="title" @mousedown.prevent="onHeaderMousedown" @touchstart.prevent="onHeaderMousedown">
|
||||
<slot name="header"></slot>
|
||||
</span>
|
||||
<slot name="buttons">
|
||||
<button class="_button" style="pointer-events: none;"></button>
|
||||
</slot>
|
||||
|
||||
<button v-if="closeRight" class="_button" @click="close()"><Fa :icon="faTimes"/></button>
|
||||
<slot v-else name="buttons"><button class="_button" style="pointer-events: none;"></button></slot>
|
||||
</div>
|
||||
<div class="body" v-if="padding">
|
||||
<div class="_section">
|
||||
@@ -85,6 +87,15 @@ export default defineComponent({
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
closeRight: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
contextmenu: {
|
||||
type: Array,
|
||||
required: false,
|
||||
}
|
||||
},
|
||||
|
||||
emits: ['closed'],
|
||||
@@ -129,6 +140,12 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
|
||||
onContextmenu(e) {
|
||||
if (this.contextmenu) {
|
||||
os.contextMenu(this.contextmenu, e);
|
||||
}
|
||||
},
|
||||
|
||||
// 最前面へ移動
|
||||
top() {
|
||||
let z = 0;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
</div>
|
||||
<div v-else class="mk-url-preview" v-size="{ max: [400, 350] }">
|
||||
<transition name="zoom" mode="out-in">
|
||||
<component :is="self ? 'router-link' : 'a'" :class="{ compact }" :[attr]="self ? url.substr(local.length) : url" rel="nofollow noopener" :target="target" :title="url" v-if="!fetching">
|
||||
<component :is="self ? 'MkA' : 'a'" :class="{ compact }" :[attr]="self ? url.substr(local.length) : url" rel="nofollow noopener" :target="target" :title="url" v-if="!fetching">
|
||||
<div class="thumbnail" v-if="thumbnail" :style="`background-image: url('${thumbnail}')`">
|
||||
<button class="_button" v-if="!playerEnabled && player.url" @click.prevent="playerEnabled = true" :title="$t('enablePlayer')"><Fa :icon="faPlayCircle"/></button>
|
||||
</div>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<component :is="self ? 'router-link' : 'a'" class="ieqqeuvs _link" :[attr]="self ? url.substr(local.length) : url" :rel="rel" :target="target"
|
||||
<component :is="self ? 'MkA' : 'a'" class="ieqqeuvs _link" :[attr]="self ? url.substr(local.length) : url" :rel="rel" :target="target"
|
||||
@mouseover="onMouseover"
|
||||
@mouseleave="onMouseleave"
|
||||
>
|
||||
|
@@ -3,7 +3,7 @@
|
||||
<div class="banner" :style="user.bannerUrl ? `background-image: url(${user.bannerUrl})` : ''"></div>
|
||||
<MkAvatar class="avatar" :user="user" :disable-preview="true"/>
|
||||
<div class="title">
|
||||
<router-link class="name" :to="userPage(user)"><MkUserName :user="user" :nowrap="false"/></router-link>
|
||||
<MkA class="name" :to="userPage(user)"><MkUserName :user="user" :nowrap="false"/></MkA>
|
||||
<p class="username"><MkAcct :user="user"/></p>
|
||||
</div>
|
||||
<div class="description">
|
||||
|
@@ -5,7 +5,7 @@
|
||||
<div class="banner" :style="user.bannerUrl ? `background-image: url(${user.bannerUrl})` : ''"></div>
|
||||
<MkAvatar class="avatar" :user="user" :disable-preview="true"/>
|
||||
<div class="title">
|
||||
<router-link class="name" :to="userPage(user)"><MkUserName :user="user" :nowrap="false"/></router-link>
|
||||
<MkA class="name" :to="userPage(user)"><MkUserName :user="user" :nowrap="false"/></MkA>
|
||||
<p class="username"><MkAcct :user="user"/></p>
|
||||
</div>
|
||||
<div class="description">
|
||||
|
@@ -6,13 +6,13 @@
|
||||
</div>
|
||||
|
||||
<div class="users">
|
||||
<router-link v-for="item in items" class="user" :key="item.id" :to="userPage(extract ? extract(item) : item)">
|
||||
<MkA v-for="item in items" class="user" :key="item.id" :to="userPage(extract ? extract(item) : item)">
|
||||
<MkAvatar :user="extract ? extract(item) : item" class="avatar" :disable-link="true"/>
|
||||
<div class="body">
|
||||
<MkUserName :user="extract ? extract(item) : item" class="name"/>
|
||||
<MkAcct :user="extract ? extract(item) : item" class="acct"/>
|
||||
</div>
|
||||
</router-link>
|
||||
</MkA>
|
||||
</div>
|
||||
<button class="more _button" v-appear="$store.state.device.enableInfiniteScroll ? fetchMore : null" @click="fetchMore" v-show="more" :disabled="moreFetching">
|
||||
<template v-if="!moreFetching">{{ $t('loadMore') }}</template>
|
||||
|
@@ -4,14 +4,13 @@
|
||||
|
||||
import '@/style.scss';
|
||||
|
||||
import { createApp } from 'vue';
|
||||
import { createApp, defineAsyncComponent } from 'vue';
|
||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
|
||||
|
||||
import Root from './root.vue';
|
||||
import widgets from './widgets';
|
||||
import directives from './directives';
|
||||
import components from '@/components';
|
||||
import { version, apiUrl } from '@/config';
|
||||
import { version, apiUrl, deckmode } from '@/config';
|
||||
import { store } from './store';
|
||||
import { router } from './router';
|
||||
import { applyTheme } from '@/scripts/theme';
|
||||
@@ -152,7 +151,12 @@ store.dispatch('instance/fetch').then(() => {
|
||||
|
||||
stream.init(store.state.i);
|
||||
|
||||
const app = createApp(Root);
|
||||
const app = createApp(await (
|
||||
window.location.search === '?zen' ? import('@/ui/zen.vue') :
|
||||
!store.getters.isSignedIn ? import('@/ui/visitor.vue') :
|
||||
deckmode ? import('@/ui/deck.vue') :
|
||||
import('@/ui/default.vue')
|
||||
).then(x => x.default));
|
||||
|
||||
if (_DEV_) {
|
||||
app.config.performance = true;
|
||||
|
@@ -5,6 +5,7 @@ import { store } from '@/store';
|
||||
import { apiUrl } from '@/config';
|
||||
import MkPostFormDialog from '@/components/post-form-dialog.vue';
|
||||
import MkWaitingDialog from '@/components/waiting-dialog.vue';
|
||||
import { resolve } from '@/router';
|
||||
|
||||
const ua = navigator.userAgent.toLowerCase();
|
||||
export const isMobile = /mobile|iphone|ipad|android/.test(ua);
|
||||
@@ -162,7 +163,8 @@ export function popup(component: Component | typeof import('*.vue'), props: Reco
|
||||
};
|
||||
}
|
||||
|
||||
export function pageWindow(url: string, component: Component | typeof import('*.vue'), props: Record<string, any>) {
|
||||
export function pageWindow(url: string) {
|
||||
const { component, props } = resolve(url);
|
||||
popup(defineAsyncComponent(() => import('@/components/page-window.vue')), {
|
||||
initialUrl: url,
|
||||
initialComponent: markRaw(component),
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<div class="_content">
|
||||
<ul>
|
||||
<li v-for="doc in docs" :key="doc.path">
|
||||
<router-link :to="`/docs/${doc.path}`">{{ doc.title }}</router-link>
|
||||
<MkA :to="`/docs/${doc.path}`">{{ doc.title }}</MkA>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@@ -38,8 +38,8 @@
|
||||
<template #header><Fa :icon="faHashtag" fixed-width style="margin-right: 0.5em;"/>{{ $t('popularTags') }}</template>
|
||||
|
||||
<div class="vxjfqztj">
|
||||
<router-link v-for="tag in tagsLocal" :to="`/explore/tags/${tag.tag}`" :key="'local:' + tag.tag" class="local">{{ tag.tag }}</router-link>
|
||||
<router-link v-for="tag in tagsRemote" :to="`/explore/tags/${tag.tag}`" :key="'remote:' + tag.tag">{{ tag.tag }}</router-link>
|
||||
<MkA v-for="tag in tagsLocal" :to="`/explore/tags/${tag.tag}`" :key="'local:' + tag.tag" class="local">{{ tag.tag }}</MkA>
|
||||
<MkA v-for="tag in tagsRemote" :to="`/explore/tags/${tag.tag}`" :key="'remote:' + tag.tag">{{ tag.tag }}</MkA>
|
||||
</div>
|
||||
</MkFolder>
|
||||
|
||||
|
@@ -12,7 +12,7 @@
|
||||
<MkAvatar class="avatar" :user="req.follower"/>
|
||||
<div class="body">
|
||||
<div class="name">
|
||||
<router-link class="name" :to="userPage(req.follower)" v-user-preview="req.follower.id"><MkUserName :user="req.follower"/></router-link>
|
||||
<MkA class="name" :to="userPage(req.follower)" v-user-preview="req.follower.id"><MkUserName :user="req.follower"/></MkA>
|
||||
<p class="acct">@{{ acct(req.follower) }}</p>
|
||||
</div>
|
||||
<div class="description" v-if="req.follower.description" :title="req.follower.description">
|
||||
|
@@ -4,13 +4,12 @@
|
||||
<MkButton @click="start" primary class="start"><Fa :icon="faPlus"/> {{ $t('startMessaging') }}</MkButton>
|
||||
|
||||
<div class="history" v-if="messages.length > 0">
|
||||
<router-link v-for="(message, i) in messages"
|
||||
<MkA v-for="(message, i) in messages"
|
||||
class="message _panel"
|
||||
:class="{ isMe: isMe(message), isRead: message.groupId ? message.reads.includes($store.state.i.id) : message.isRead }"
|
||||
:to="message.groupId ? `/my/messaging/group/${message.groupId}` : `/my/messaging/${getAcct(isMe(message) ? message.recipient : message.user)}`"
|
||||
:data-index="i"
|
||||
:key="message.id"
|
||||
@click.prevent="go(message)"
|
||||
>
|
||||
<div>
|
||||
<MkAvatar class="avatar" :user="message.groupId ? message.user : isMe(message) ? message.recipient : message.user"/>
|
||||
@@ -27,7 +26,7 @@
|
||||
<p class="text"><span class="me" v-if="isMe(message)">{{ $t('you') }}:</span>{{ message.text }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</router-link>
|
||||
</MkA>
|
||||
</div>
|
||||
<div class="_fullinfo" v-if="!fetching && messages.length == 0">
|
||||
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
|
||||
@@ -90,18 +89,6 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
methods: {
|
||||
go(message) {
|
||||
const url = message.groupId ? `/my/messaging/group/${message.groupId}` : `/my/messaging/${getAcct(this.isMe(message) ? message.recipient : message.user)}`;
|
||||
if (this.navHook) {
|
||||
this.navHook(url, defineAsyncComponent(() => import('@/pages/messaging/messaging-room.vue')), {
|
||||
userAcct: message.groupId ? null : getAcct(this.isMe(message) ? message.recipient : message.user),
|
||||
groupId: message.groupId
|
||||
});
|
||||
} else {
|
||||
this.$router.push(url);
|
||||
}
|
||||
},
|
||||
|
||||
getAcct,
|
||||
|
||||
isMe(message) {
|
||||
|
@@ -317,7 +317,7 @@ const Component = defineComponent({
|
||||
text: this.$t('openInWindow'),
|
||||
icon: faWindowMaximize,
|
||||
action: () => {
|
||||
os.pageWindow(url, Component, this.$props);
|
||||
os.pageWindow(url);
|
||||
this.$router.back();
|
||||
},
|
||||
}, this.inWindow ? undefined : {
|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
<MkPagination :pagination="ownedPagination" #default="{items}" ref="owned">
|
||||
<div class="_card" v-for="group in items" :key="group.id">
|
||||
<div class="_title"><router-link :to="`/my/groups/${ group.id }`" class="_link">{{ group.name }}</router-link></div>
|
||||
<div class="_title"><MkA :to="`/my/groups/${ group.id }`" class="_link">{{ group.name }}</MkA></div>
|
||||
<div class="_content"><MkAvatars :user-ids="group.userIds"/></div>
|
||||
</div>
|
||||
</MkPagination>
|
||||
|
@@ -4,7 +4,7 @@
|
||||
|
||||
<MkPagination :pagination="pagination" #default="{items}" class="lists _content" ref="list">
|
||||
<div class="list _panel" v-for="(list, i) in items" :key="list.id">
|
||||
<router-link :to="`/my/lists/${ list.id }`">{{ list.name }}</router-link>
|
||||
<MkA :to="`/my/lists/${ list.id }`">{{ list.name }}</MkA>
|
||||
</div>
|
||||
</MkPagination>
|
||||
</div>
|
||||
|
@@ -42,6 +42,12 @@ export default defineComponent({
|
||||
MkRemoteCaution,
|
||||
MkButton,
|
||||
},
|
||||
props: {
|
||||
noteId: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
INFO: computed(() => this.note ? {
|
||||
@@ -77,7 +83,7 @@ export default defineComponent({
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
$route: 'fetch'
|
||||
noteId: 'fetch'
|
||||
},
|
||||
created() {
|
||||
this.fetch();
|
||||
@@ -86,7 +92,7 @@ export default defineComponent({
|
||||
fetch() {
|
||||
Progress.start();
|
||||
os.api('notes/show', {
|
||||
noteId: this.$route.params.note
|
||||
noteId: this.noteId
|
||||
}).then(note => {
|
||||
Promise.all([
|
||||
os.api('users/notes', {
|
||||
|
@@ -12,7 +12,7 @@
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<router-link class="view" v-if="pageId" :to="`/@${ author.username }/pages/${ currentName }`"><Fa :icon="faExternalLinkSquareAlt"/> {{ $t('_pages.viewPage') }}</router-link>
|
||||
<MkA class="view" v-if="pageId" :to="`/@${ author.username }/pages/${ currentName }`"><Fa :icon="faExternalLinkSquareAlt"/> {{ $t('_pages.viewPage') }}</MkA>
|
||||
|
||||
<MkInput v-model:value="title">
|
||||
<span>{{ $t('_pages.title') }}</span>
|
||||
|
@@ -20,9 +20,9 @@
|
||||
</div>
|
||||
<div class="_section links">
|
||||
<div class="_content">
|
||||
<router-link :to="`./${page.name}/view-source`" class="link">{{ $t('_pages.viewSource') }}</router-link>
|
||||
<MkA :to="`./${page.name}/view-source`" class="link">{{ $t('_pages.viewSource') }}</MkA>
|
||||
<template v-if="$store.getters.isSignedIn && $store.state.i.id === page.userId">
|
||||
<router-link :to="`/my/pages/edit/${page.id}`" class="link">{{ $t('_pages.editThisPage') }}</router-link>
|
||||
<MkA :to="`/my/pages/edit/${page.id}`" class="link">{{ $t('_pages.editThisPage') }}</MkA>
|
||||
<button v-if="$store.state.i.pinnedPageId === page.id" @click="pin(false)" class="link _textButton">{{ $t('unpin') }}</button>
|
||||
<button v-else @click="pin(true)" class="link _textButton">{{ $t('pin') }}</button>
|
||||
</template>
|
||||
|
@@ -2,6 +2,10 @@
|
||||
<div class="_section">
|
||||
<section class="_card _vMargin">
|
||||
<div class="_title"><Fa :icon="faCog"/> {{ $t('general') }}</div>
|
||||
<div class="_content">
|
||||
<div>{{ $t('defaultNavigationBehaviour') }}</div>
|
||||
<MkSwitch v-model:value="defaultSideView">{{ $t('openInSideView') }}</MkSwitch>
|
||||
</div>
|
||||
<div class="_content">
|
||||
<div>{{ $t('whenServerDisconnected') }}</div>
|
||||
<MkRadio v-model="serverDisconnectedBehavior" value="reload">{{ $t('_serverDisconnectedBehavior.reload') }}</MkRadio>
|
||||
@@ -51,6 +55,10 @@
|
||||
|
||||
<section class="_card _vMargin">
|
||||
<div class="_title"><Fa :icon="faColumns"/> {{ $t('deck') }}</div>
|
||||
<div class="_content">
|
||||
<div>{{ $t('defaultNavigationBehaviour') }}</div>
|
||||
<MkSwitch v-model:value="deckNavWindow">{{ $t('openInWindow') }}</MkSwitch>
|
||||
</div>
|
||||
<div class="_content">
|
||||
<MkSwitch v-model:value="deckAlwaysShowMainColumn">
|
||||
{{ $t('_deck.alwaysShowMainColumn') }}
|
||||
@@ -146,6 +154,16 @@ export default defineComponent({
|
||||
set(value) { this.$store.commit('device/set', { key: 'showFixedPostForm', value }); }
|
||||
},
|
||||
|
||||
defaultSideView: {
|
||||
get() { return this.$store.state.device.defaultSideView; },
|
||||
set(value) { this.$store.commit('device/set', { key: 'defaultSideView', value }); }
|
||||
},
|
||||
|
||||
deckNavWindow: {
|
||||
get() { return this.$store.state.device.deckNavWindow; },
|
||||
set(value) { this.$store.commit('device/set', { key: 'deckNavWindow', value }); }
|
||||
},
|
||||
|
||||
chatOpenBehavior: {
|
||||
get() { return this.$store.state.device.chatOpenBehavior; },
|
||||
set(value) { this.$store.commit('device/set', { key: 'chatOpenBehavior', value }); }
|
||||
|
@@ -1,52 +1,57 @@
|
||||
<template>
|
||||
<div class="vvcocwet" :class="{ wide: !narrow }" ref="el">
|
||||
<div class="nav" v-if="!narrow || $route.name === 'settings'">
|
||||
<div class="nav" v-if="!narrow || page == null">
|
||||
<div class="menu">
|
||||
<div class="label">{{ $t('basicSettings') }}</div>
|
||||
<router-link class="item" replace to="/settings/profile"><Fa :icon="faUser" fixed-width class="icon"/>{{ $t('profile') }}</router-link>
|
||||
<router-link class="item" replace to="/settings/privacy"><Fa :icon="faLockOpen" fixed-width class="icon"/>{{ $t('privacy') }}</router-link>
|
||||
<router-link class="item" replace to="/settings/reaction"><Fa :icon="faLaugh" fixed-width class="icon"/>{{ $t('reaction') }}</router-link>
|
||||
<router-link class="item" replace to="/settings/notifications"><Fa :icon="faBell" fixed-width class="icon"/>{{ $t('notifications') }}</router-link>
|
||||
<router-link class="item" replace to="/settings/integration"><Fa :icon="faShareAlt" fixed-width class="icon"/>{{ $t('integration') }}</router-link>
|
||||
<router-link class="item" replace to="/settings/security"><Fa :icon="faLock" fixed-width class="icon"/>{{ $t('security') }}</router-link>
|
||||
<MkA class="item" :class="{ active: page === 'profile' }" replace to="/settings/profile"><Fa :icon="faUser" fixed-width class="icon"/>{{ $t('profile') }}</MkA>
|
||||
<MkA class="item" :class="{ active: page === 'privacy' }" replace to="/settings/privacy"><Fa :icon="faLockOpen" fixed-width class="icon"/>{{ $t('privacy') }}</MkA>
|
||||
<MkA class="item" :class="{ active: page === 'reaction' }" replace to="/settings/reaction"><Fa :icon="faLaugh" fixed-width class="icon"/>{{ $t('reaction') }}</MkA>
|
||||
<MkA class="item" :class="{ active: page === 'notifications' }" replace to="/settings/notifications"><Fa :icon="faBell" fixed-width class="icon"/>{{ $t('notifications') }}</MkA>
|
||||
<MkA class="item" :class="{ active: page === 'integration' }" replace to="/settings/integration"><Fa :icon="faShareAlt" fixed-width class="icon"/>{{ $t('integration') }}</MkA>
|
||||
<MkA class="item" :class="{ active: page === 'security' }" replace to="/settings/security"><Fa :icon="faLock" fixed-width class="icon"/>{{ $t('security') }}</MkA>
|
||||
</div>
|
||||
<div class="menu">
|
||||
<div class="label">{{ $t('clientSettings') }}</div>
|
||||
<router-link class="item" replace to="/settings/general"><Fa :icon="faCogs" fixed-width class="icon"/>{{ $t('general') }}</router-link>
|
||||
<router-link class="item" replace to="/settings/theme"><Fa :icon="faPalette" fixed-width class="icon"/>{{ $t('theme') }}</router-link>
|
||||
<router-link class="item" replace to="/settings/sidebar"><Fa :icon="faListUl" fixed-width class="icon"/>{{ $t('sidebar') }}</router-link>
|
||||
<router-link class="item" replace to="/settings/sounds"><Fa :icon="faMusic" fixed-width class="icon"/>{{ $t('sounds') }}</router-link>
|
||||
<router-link class="item" replace to="/settings/plugins"><Fa :icon="faPlug" fixed-width class="icon"/>{{ $t('plugins') }}</router-link>
|
||||
<MkA class="item" :class="{ active: page === 'general' }" replace to="/settings/general"><Fa :icon="faCogs" fixed-width class="icon"/>{{ $t('general') }}</MkA>
|
||||
<MkA class="item" :class="{ active: page === 'theme' }" replace to="/settings/theme"><Fa :icon="faPalette" fixed-width class="icon"/>{{ $t('theme') }}</MkA>
|
||||
<MkA class="item" :class="{ active: page === 'sidebar' }" replace to="/settings/sidebar"><Fa :icon="faListUl" fixed-width class="icon"/>{{ $t('sidebar') }}</MkA>
|
||||
<MkA class="item" :class="{ active: page === 'sounds' }" replace to="/settings/sounds"><Fa :icon="faMusic" fixed-width class="icon"/>{{ $t('sounds') }}</MkA>
|
||||
<MkA class="item" :class="{ active: page === 'plugins' }" replace to="/settings/plugins"><Fa :icon="faPlug" fixed-width class="icon"/>{{ $t('plugins') }}</MkA>
|
||||
</div>
|
||||
<div class="menu">
|
||||
<div class="label">{{ $t('otherSettings') }}</div>
|
||||
<router-link class="item" replace to="/settings/mute-block"><Fa :icon="faBan" fixed-width class="icon"/>{{ $t('muteAndBlock') }}</router-link>
|
||||
<router-link class="item" replace to="/settings/word-mute"><Fa :icon="faCommentSlash" fixed-width class="icon"/>{{ $t('wordMute') }}</router-link>
|
||||
<router-link class="item" replace to="/settings/api"><Fa :icon="faKey" fixed-width class="icon"/>API</router-link>
|
||||
<router-link class="item" replace to="/settings/other"><Fa :icon="faEllipsisH" fixed-width class="icon"/>{{ $t('other') }}</router-link>
|
||||
<MkA class="item" :class="{ active: page === 'mute-block' }" replace to="/settings/mute-block"><Fa :icon="faBan" fixed-width class="icon"/>{{ $t('muteAndBlock') }}</MkA>
|
||||
<MkA class="item" :class="{ active: page === 'word-mute' }" replace to="/settings/word-mute"><Fa :icon="faCommentSlash" fixed-width class="icon"/>{{ $t('wordMute') }}</MkA>
|
||||
<MkA class="item" :class="{ active: page === 'api' }" replace to="/settings/api"><Fa :icon="faKey" fixed-width class="icon"/>API</MkA>
|
||||
<MkA class="item" :class="{ active: page === 'other' }" replace to="/settings/other"><Fa :icon="faEllipsisH" fixed-width class="icon"/>{{ $t('other') }}</MkA>
|
||||
</div>
|
||||
<div class="menu">
|
||||
<button class="_button item" @click="logout">{{ $t('logout') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main">
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition :name="($store.state.device.animation && !narrow) ? 'view-slide' : ''" appear mode="out-in">
|
||||
<component :is="Component" @info="onInfo"/>
|
||||
</transition>
|
||||
</router-view>
|
||||
<transition :name="($store.state.device.animation && !narrow) ? 'view-slide' : ''" appear mode="out-in">
|
||||
<component :is="component" @info="onInfo"/>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted, ref } from 'vue';
|
||||
import { computed, defineAsyncComponent, defineComponent, onMounted, ref } from 'vue';
|
||||
import { faCog, faPalette, faPlug, faUser, faListUl, faLock, faCommentSlash, faMusic, faCogs, faEllipsisH, faBan, faShareAlt, faLockOpen, faKey } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faLaugh, faBell } from '@fortawesome/free-regular-svg-icons';
|
||||
import { store } from '@/store';
|
||||
import { i18n } from '@/i18n';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
page: {
|
||||
type: String,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
|
||||
setup(props, context) {
|
||||
const INFO = ref({
|
||||
header: [{
|
||||
@@ -60,6 +65,28 @@ export default defineComponent({
|
||||
const onInfo = (viewInfo) => {
|
||||
INFO.value = viewInfo;
|
||||
};
|
||||
const component = computed(() => {
|
||||
switch (props.page) {
|
||||
case 'profile': return defineAsyncComponent(() => import('./profile.vue'));
|
||||
case 'privacy': return defineAsyncComponent(() => import('./privacy.vue'));
|
||||
case 'reaction': return defineAsyncComponent(() => import('./reaction.vue'));
|
||||
case 'notifications': return defineAsyncComponent(() => import('./notifications.vue'));
|
||||
case 'mute-block': return defineAsyncComponent(() => import('./mute-block.vue'));
|
||||
case 'word-mute': return defineAsyncComponent(() => import('./word-mute.vue'));
|
||||
case 'integration': return defineAsyncComponent(() => import('./integration.vue'));
|
||||
case 'security': return defineAsyncComponent(() => import('./security.vue'));
|
||||
case 'api': return defineAsyncComponent(() => import('./api.vue'));
|
||||
case 'other': return defineAsyncComponent(() => import('./other.vue'));
|
||||
case 'general': return defineAsyncComponent(() => import('./general.vue'));
|
||||
case 'theme': return defineAsyncComponent(() => import('./theme.vue'));
|
||||
case 'sidebar': return defineAsyncComponent(() => import('./sidebar.vue'));
|
||||
case 'sounds': return defineAsyncComponent(() => import('./sounds.vue'));
|
||||
case 'plugins': return defineAsyncComponent(() => import('./plugins.vue'));
|
||||
case 'import-export': return defineAsyncComponent(() => import('./import-export.vue'));
|
||||
case 'regedit': return defineAsyncComponent(() => import('./regedit.vue'));
|
||||
default: return null;
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
narrow.value = el.value.offsetWidth < 650;
|
||||
@@ -71,6 +98,7 @@ export default defineComponent({
|
||||
view,
|
||||
el,
|
||||
onInfo,
|
||||
component,
|
||||
logout: () => {
|
||||
store.dispatch('logout');
|
||||
location.href = '/';
|
||||
@@ -121,7 +149,7 @@ export default defineComponent({
|
||||
//border-top: solid 1px var(--divider);
|
||||
}
|
||||
|
||||
&.router-link-active {
|
||||
&.active {
|
||||
color: var(--accent);
|
||||
padding-left: 42px;
|
||||
}
|
||||
|
@@ -6,9 +6,9 @@
|
||||
<template #empty><MkInfo>{{ $t('noUsers') }}</MkInfo></template>
|
||||
<template #default="{items}">
|
||||
<div class="user" v-for="mute in items" :key="mute.id">
|
||||
<router-link class="name" :to="userPage(mute.mutee)">
|
||||
<MkA class="name" :to="userPage(mute.mutee)">
|
||||
<MkAcct :user="mute.mutee"/>
|
||||
</router-link>
|
||||
</MkA>
|
||||
</div>
|
||||
</template>
|
||||
</MkPagination>
|
||||
@@ -18,9 +18,9 @@
|
||||
<template #empty><MkInfo>{{ $t('noUsers') }}</MkInfo></template>
|
||||
<template #default="{items}">
|
||||
<div class="user" v-for="block in items" :key="block.id">
|
||||
<router-link class="name" :to="userPage(block.blockee)">
|
||||
<MkA class="name" :to="userPage(block.blockee)">
|
||||
<MkAcct :user="block.blockee"/>
|
||||
</router-link>
|
||||
</MkA>
|
||||
</div>
|
||||
</template>
|
||||
</MkPagination>
|
||||
|
@@ -1,12 +1,17 @@
|
||||
<template>
|
||||
<div class="_section">
|
||||
<div class="_card">
|
||||
<div class="_content">
|
||||
<MkSwitch v-model:value="$store.state.i.injectFeaturedNote" @update:value="onChangeInjectFeaturedNote">
|
||||
{{ $t('showFeaturedNotesInTimeline') }}
|
||||
</MkSwitch>
|
||||
<div>
|
||||
<div class="_section">
|
||||
<div class="_card">
|
||||
<div class="_content">
|
||||
<MkSwitch v-model:value="$store.state.i.injectFeaturedNote" @update:value="onChangeInjectFeaturedNote">
|
||||
{{ $t('showFeaturedNotesInTimeline') }}
|
||||
</MkSwitch>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="_section">
|
||||
<MkA to="/settings/regedit">RegEdit</MkA>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
77
src/client/pages/settings/regedit.vue
Normal file
77
src/client/pages/settings/regedit.vue
Normal file
@@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="_section">
|
||||
<MkInfo warn>{{ $t('editTheseSettingsMayBreakAccount') }}</MkInfo>
|
||||
</div>
|
||||
<div class="_section">
|
||||
<div class="_title">Account</div>
|
||||
<div class="_content">
|
||||
<MkTextarea v-model:value="settings" code tall></MkTextarea>
|
||||
<!--<MkButton @click="saveSettings">Save</MkButton>-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="_section">
|
||||
<div class="_title">Device</div>
|
||||
<div class="_content">
|
||||
<MkTextarea v-model:value="deviceSettings" code tall></MkTextarea>
|
||||
<MkButton @click="saveDeviceSettings">Save</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
<div class="_section">
|
||||
<div class="_title">Device (per account)</div>
|
||||
<div class="_content">
|
||||
<MkTextarea v-model:value="deviceUserSettings" code tall></MkTextarea>
|
||||
<MkButton @click="saveDeviceUserSettings">Save</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { faCode } from '@fortawesome/free-solid-svg-icons';
|
||||
import * as JSON5 from 'json5';
|
||||
import MkInfo from '@/components/ui/info.vue';
|
||||
import MkButton from '@/components/ui/button.vue';
|
||||
import MkTextarea from '@/components/ui/textarea.vue';
|
||||
import * as os from '@/os';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
MkInfo, MkButton, MkTextarea
|
||||
},
|
||||
|
||||
emits: ['info'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
INFO: {
|
||||
header: [{
|
||||
title: 'RegEdit',
|
||||
icon: faCode
|
||||
}]
|
||||
},
|
||||
|
||||
settings: JSON5.stringify(this.$store.state.settings, null, '\t'),
|
||||
deviceSettings: JSON5.stringify(this.$store.state.device, null, '\t'),
|
||||
deviceUserSettings: JSON5.stringify(this.$store.state.deviceUser, null, '\t'),
|
||||
};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$emit('info', this.INFO);
|
||||
},
|
||||
|
||||
methods: {
|
||||
saveDeviceSettings() {
|
||||
const obj = JSON5.parse(this.deviceSettings);
|
||||
this.$store.commit('device/overwrite', obj);
|
||||
},
|
||||
|
||||
saveDeviceUserSettings() {
|
||||
const obj = JSON5.parse(this.deviceUserSettings);
|
||||
this.$store.commit('deviceUser/overwrite', obj);
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
@@ -43,7 +43,7 @@
|
||||
<option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
|
||||
</optgroup>
|
||||
</MkSelect>
|
||||
<a href="https://assets.msky.cafe/theme/list" rel="noopener" target="_blank" class="_link">{{ $t('_theme.explore') }}</a>・<router-link to="/theme-editor" class="_link">{{ $t('_theme.make') }}</router-link>
|
||||
<a href="https://assets.msky.cafe/theme/list" rel="noopener" target="_blank" class="_link">{{ $t('_theme.explore') }}</a>・<MkA to="/theme-editor" class="_link">{{ $t('_theme.make') }}</MkA>
|
||||
</div>
|
||||
<div class="_content">
|
||||
<MkButton primary v-if="wallpaper == null" @click="setWallpaper">{{ $t('setWallpaper') }}</MkButton>
|
||||
|
@@ -15,11 +15,18 @@ export default defineComponent({
|
||||
XNotes
|
||||
},
|
||||
|
||||
props: {
|
||||
tag: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
INFO: {
|
||||
header: [{
|
||||
title: this.$route.params.tag,
|
||||
title: this.tag,
|
||||
icon: faHashtag
|
||||
}],
|
||||
},
|
||||
@@ -27,7 +34,7 @@ export default defineComponent({
|
||||
endpoint: 'notes/search-by-tag',
|
||||
limit: 10,
|
||||
params: () => ({
|
||||
tag: this.$route.params.tag,
|
||||
tag: this.tag,
|
||||
})
|
||||
},
|
||||
faHashtag
|
||||
@@ -35,7 +42,7 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
watch: {
|
||||
$route() {
|
||||
tag() {
|
||||
(this.$refs.notes as any).reload();
|
||||
}
|
||||
},
|
||||
|
@@ -229,7 +229,7 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
messagingWindowOpen() {
|
||||
os.pageWindow('/my/messaging', defineAsyncComponent(() => import('@/pages/messaging/index.vue')));
|
||||
os.pageWindow('/my/messaging');
|
||||
},
|
||||
|
||||
openWaitingDialog(text?) {
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<div class="_content" v-else-if="tutorial === 1">
|
||||
<div>{{ $t('_tutorial.step2_1') }}</div>
|
||||
<div>{{ $t('_tutorial.step2_2') }}</div>
|
||||
<router-link class="_link" to="/settings/profile">{{ $t('editProfile') }}</router-link>
|
||||
<MkA class="_link" to="/settings/profile">{{ $t('editProfile') }}</MkA>
|
||||
</div>
|
||||
<div class="_content" v-else-if="tutorial === 2">
|
||||
<div>{{ $t('_tutorial.step3_1') }}</div>
|
||||
@@ -25,10 +25,10 @@
|
||||
<div>{{ $t('_tutorial.step5_1') }}</div>
|
||||
<i18n-t keypath="_tutorial.step5_2" tag="div">
|
||||
<template #featured>
|
||||
<router-link class="_link" to="/featured">{{ $t('featured') }}</router-link>
|
||||
<MkA class="_link" to="/featured">{{ $t('featured') }}</MkA>
|
||||
</template>
|
||||
<template #explore>
|
||||
<router-link class="_link" to="/explore">{{ $t('explore') }}</router-link>
|
||||
<MkA class="_link" to="/explore">{{ $t('explore') }}</MkA>
|
||||
</template>
|
||||
</i18n-t>
|
||||
<div>{{ $t('_tutorial.step5_3') }}</div>
|
||||
@@ -43,7 +43,7 @@
|
||||
<div>{{ $t('_tutorial.step7_1') }}</div>
|
||||
<i18n-t keypath="_tutorial.step7_2" tag="div">
|
||||
<template #help>
|
||||
<router-link class="_link" to="/docs">{{ $t('help') }}</router-link>
|
||||
<MkA class="_link" to="/docs">{{ $t('help') }}</MkA>
|
||||
</template>
|
||||
</i18n-t>
|
||||
<div>{{ $t('_tutorial.step7_3') }}</div>
|
||||
|
@@ -10,7 +10,6 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import parseAcct from '../../../misc/acct/parse';
|
||||
import MkUserInfo from '@/components/user-info.vue';
|
||||
import MkPagination from '@/components/ui/pagination.vue';
|
||||
import { userPage, acct } from '../../filters/user';
|
||||
@@ -22,10 +21,14 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
props: {
|
||||
user: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
@@ -34,7 +37,7 @@ export default defineComponent({
|
||||
endpoint: () => this.type === 'following' ? 'users/following' : 'users/followers',
|
||||
limit: 20,
|
||||
params: {
|
||||
...parseAcct(this.$route.params.user),
|
||||
userId: this.user.id,
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -45,7 +48,7 @@ export default defineComponent({
|
||||
this.$refs.list.reload();
|
||||
},
|
||||
|
||||
'$route'() {
|
||||
user() {
|
||||
this.$refs.list.reload();
|
||||
}
|
||||
},
|
||||
|
@@ -2,11 +2,11 @@
|
||||
<div class="ujigsodd">
|
||||
<MkLoading v-if="fetching"/>
|
||||
<div class="stream" v-if="!fetching && images.length > 0">
|
||||
<router-link v-for="(image, i) in images" :key="i"
|
||||
<MkA v-for="image in images"
|
||||
class="img"
|
||||
:style="`background-image: url(${thumbnail(image.file)})`"
|
||||
:to="notePage(image.note)"
|
||||
></router-link>
|
||||
></MkA>
|
||||
</div>
|
||||
<p class="empty" v-if="!fetching && images.length == 0">{{ $t('nothing') }}</p>
|
||||
</div>
|
||||
|
@@ -67,24 +67,23 @@
|
||||
</dl>
|
||||
</div>
|
||||
<div class="status">
|
||||
<router-link :to="userPage(user)" :class="{ active: $route.name === 'user' }">
|
||||
<MkA :to="userPage(user)" :class="{ active: page === 'index' }">
|
||||
<b>{{ number(user.notesCount) }}</b>
|
||||
<span>{{ $t('notes') }}</span>
|
||||
</router-link>
|
||||
<router-link :to="userPage(user, 'following')" :class="{ active: $route.name === 'userFollowing' }">
|
||||
</MkA>
|
||||
<MkA :to="userPage(user, 'following')" :class="{ active: page === 'following' }">
|
||||
<b>{{ number(user.followingCount) }}</b>
|
||||
<span>{{ $t('following') }}</span>
|
||||
</router-link>
|
||||
<router-link :to="userPage(user, 'followers')" :class="{ active: $route.name === 'userFollowers' }">
|
||||
</MkA>
|
||||
<MkA :to="userPage(user, 'followers')" :class="{ active: page === 'followers' }">
|
||||
<b>{{ number(user.followersCount) }}</b>
|
||||
<span>{{ $t('followers') }}</span>
|
||||
</router-link>
|
||||
</MkA>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<router-view :user="user"></router-view>
|
||||
<template v-if="$route.name == 'user'">
|
||||
<template v-if="page === 'index'">
|
||||
<div class="_section">
|
||||
<div class="_content _vMargin" v-if="user.pinnedNotes.length > 0">
|
||||
<XNote v-for="note in user.pinnedNotes" class="note _vMargin" :note="note" @update:note="pinnedNoteUpdated(note, $event)" :key="note.id" :detail="true" :pinned="true"/>
|
||||
@@ -106,6 +105,8 @@
|
||||
<XUserTimeline :user="user" class="_content"/>
|
||||
</div>
|
||||
</template>
|
||||
<XFollowList v-else-if="page === 'following'" type="following" :user="user"/>
|
||||
<XFollowList v-else-if="page === 'followers'" type="followers" :user="user"/>
|
||||
</div>
|
||||
<div v-else-if="error">
|
||||
<MkError @retry="fetch()"/>
|
||||
@@ -128,7 +129,7 @@ import parseAcct from '../../../misc/acct/parse';
|
||||
import { getScrollPosition } from '@/scripts/scroll';
|
||||
import { getUserMenu } from '@/scripts/get-user-menu';
|
||||
import number from '../../filters/number';
|
||||
import { userPage, acct } from '../../filters/user';
|
||||
import { userPage, acct as getAcct } from '../../filters/user';
|
||||
import * as os from '@/os';
|
||||
|
||||
export default defineComponent({
|
||||
@@ -139,10 +140,23 @@ export default defineComponent({
|
||||
MkContainer,
|
||||
MkRemoteCaution,
|
||||
MkFolder,
|
||||
XFollowList: defineAsyncComponent(() => import('./follow-list.vue')),
|
||||
XPhotos: defineAsyncComponent(() => import('./index.photos.vue')),
|
||||
XActivity: defineAsyncComponent(() => import('./index.activity.vue')),
|
||||
},
|
||||
|
||||
props: {
|
||||
acct: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
page: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'index'
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
INFO: computed(() => this.user ? {
|
||||
@@ -176,7 +190,7 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
watch: {
|
||||
$route: 'fetch'
|
||||
acct: 'fetch'
|
||||
},
|
||||
|
||||
created() {
|
||||
@@ -192,10 +206,12 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
methods: {
|
||||
getAcct,
|
||||
|
||||
fetch() {
|
||||
if (this.$route.params.user == null) return;
|
||||
if (this.acct == null) return;
|
||||
Progress.start();
|
||||
os.api('users/show', parseAcct(this.$route.params.user)).then(user => {
|
||||
os.api('users/show', parseAcct(this.acct)).then(user => {
|
||||
this.user = user;
|
||||
}).catch(e => {
|
||||
this.error = e;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
import { defineAsyncComponent, markRaw } from 'vue';
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import MkLoading from '@/pages/_loading_.vue';
|
||||
import MkError from '@/pages/_error_.vue';
|
||||
@@ -18,30 +18,11 @@ export const router = createRouter({
|
||||
routes: [
|
||||
// NOTE: MkTimelineをdynamic importするとAsyncComponentWrapperが間に入るせいでkeep-aliveのコンポーネント指定が効かなくなる
|
||||
{ path: '/', name: 'index', component: store.getters.isSignedIn ? MkTimeline : page('welcome') },
|
||||
{ path: '/@:user', name: 'user', component: page('user/index'), children: [
|
||||
{ path: 'following', name: 'userFollowing', component: page('user/follow-list'), props: { type: 'following' } },
|
||||
{ path: 'followers', name: 'userFollowers', component: page('user/follow-list'), props: { type: 'followers' } },
|
||||
]},
|
||||
{ path: '/@:acct/:page?', name: 'user', component: page('user/index'), props: route => ({ acct: route.params.acct, page: route.params.page || 'index' }) },
|
||||
{ path: '/@:user/pages/:page', component: page('page'), props: route => ({ pageName: route.params.page, username: route.params.user }) },
|
||||
{ path: '/@:user/pages/:pageName/view-source', component: page('page-editor/page-editor'), props: route => ({ initUser: route.params.user, initPageName: route.params.pageName }) },
|
||||
{ path: '/@:acct/room', props: true, component: page('room/room') },
|
||||
{ path: '/settings', name: 'settings', component: page('settings/index'), children: [
|
||||
{ path: 'profile', component: page('settings/profile') },
|
||||
{ path: 'privacy', component: page('settings/privacy') },
|
||||
{ path: 'reaction', component: page('settings/reaction') },
|
||||
{ path: 'notifications', component: page('settings/notifications') },
|
||||
{ path: 'mute-block', component: page('settings/mute-block') },
|
||||
{ path: 'word-mute', component: page('settings/word-mute') },
|
||||
{ path: 'integration', component: page('settings/integration') },
|
||||
{ path: 'security', component: page('settings/security') },
|
||||
{ path: 'api', component: page('settings/api') },
|
||||
{ path: 'other', component: page('settings/other') },
|
||||
{ path: 'general', component: page('settings/general') },
|
||||
{ path: 'theme', component: page('settings/theme') },
|
||||
{ path: 'sidebar', component: page('settings/sidebar') },
|
||||
{ path: 'sounds', component: page('settings/sounds') },
|
||||
{ path: 'plugins', component: page('settings/plugins') },
|
||||
]},
|
||||
{ path: '/settings/:page?', name: 'settings', component: page('settings/index'), props: route => ({ page: route.params.page || null }) },
|
||||
{ path: '/announcements', component: page('announcements') },
|
||||
{ path: '/about', component: page('about') },
|
||||
{ path: '/about-misskey', component: page('about-misskey') },
|
||||
@@ -87,8 +68,8 @@ export const router = createRouter({
|
||||
{ path: '/instance/relays', component: page('instance/relays') },
|
||||
{ path: '/instance/announcements', component: page('instance/announcements') },
|
||||
{ path: '/instance/abuses', component: page('instance/abuses') },
|
||||
{ path: '/notes/:note', name: 'note', component: page('note') },
|
||||
{ path: '/tags/:tag', component: page('tag') },
|
||||
{ path: '/notes/:note', name: 'note', component: page('note'), props: route => ({ noteId: route.params.note }) },
|
||||
{ path: '/tags/:tag', component: page('tag'), props: route => ({ tag: route.params.tag }) },
|
||||
{ path: '/auth/:token', component: page('auth') },
|
||||
{ path: '/miauth/:session', component: page('miauth') },
|
||||
{ path: '/authorize-follow', component: page('follow') },
|
||||
@@ -120,3 +101,13 @@ router.afterEach((to, from) => {
|
||||
indexScrollPos = window.scrollY;
|
||||
}
|
||||
});
|
||||
|
||||
export function resolve(path: string) {
|
||||
const resolved = router.resolve(path);
|
||||
const route = resolved.matched[0];
|
||||
return {
|
||||
component: markRaw(route.components.default),
|
||||
// TODO: route.propsには関数以外も入る可能性があるのでよしなにハンドリングする
|
||||
props: route.props?.default ? route.props.default(resolved) : resolved.params
|
||||
};
|
||||
}
|
||||
|
@@ -7,7 +7,6 @@ import getAcct from '../../misc/acct/render';
|
||||
import * as os from '@/os';
|
||||
import { store, userActions } from '@/store';
|
||||
import { router } from '@/router';
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
import { popout } from './popout';
|
||||
|
||||
export function getUserMenu(user) {
|
||||
@@ -137,7 +136,7 @@ export function getUserMenu(user) {
|
||||
action: () => {
|
||||
const acct = getAcct(user);
|
||||
switch (store.state.device.chatOpenBehavior) {
|
||||
case 'window': { os.pageWindow('/my/messaging/' + acct, defineAsyncComponent(() => import('@/pages/messaging/messaging-room.vue')), { userAcct: acct }); break; }
|
||||
case 'window': { os.pageWindow('/my/messaging/' + acct); break; }
|
||||
case 'popout': { popout('/my/messaging'); break; }
|
||||
default: { router.push('/my/messaging'); break; }
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { faBell, faComments, faEnvelope } from '@fortawesome/free-regular-svg-icons';
|
||||
import { faAt, faBroadcastTower, faCloud, faColumns, faDoorClosed, faFileAlt, faFireAlt, faGamepad, faHashtag, faListUl, faSatellite, faSatelliteDish, faSearch, faStar, faTerminal, faUserClock, faUsers } from '@fortawesome/free-solid-svg-icons';
|
||||
import { computed, defineAsyncComponent } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
import { store } from '@/store';
|
||||
import { deckmode } from '@/config';
|
||||
import { search } from '@/scripts/search';
|
||||
@@ -23,7 +23,7 @@ export const sidebarDef = {
|
||||
indicated: computed(() => store.getters.isSignedIn && store.state.i.hasUnreadMessagingMessage),
|
||||
action: () => {
|
||||
switch (store.state.device.chatOpenBehavior) {
|
||||
case 'window': { os.pageWindow('/my/messaging', defineAsyncComponent(() => import('@/pages/messaging/index.vue'))); break; }
|
||||
case 'window': { os.pageWindow('/my/messaging'); break; }
|
||||
case 'popout': { popout('/my/messaging'); break; }
|
||||
default: { router.push('/my/messaging'); break; }
|
||||
}
|
||||
|
@@ -70,6 +70,8 @@ export const defaultDeviceSettings = {
|
||||
animatedMfm: true,
|
||||
imageNewTab: false,
|
||||
chatOpenBehavior: 'page',
|
||||
defaultSideView: false,
|
||||
deckNavWindow: true,
|
||||
showFixedPostForm: false,
|
||||
disablePagesScript: false,
|
||||
enableInfiniteScroll: true,
|
||||
@@ -202,6 +204,15 @@ export const store = createStore({
|
||||
state: defaultDeviceSettings,
|
||||
|
||||
mutations: {
|
||||
overwrite(state, x) {
|
||||
for (const k of Object.keys(state)) {
|
||||
if (x[k] === undefined) delete state[k];
|
||||
}
|
||||
for (const k of Object.keys(x)) {
|
||||
state[k] = x[k];
|
||||
}
|
||||
},
|
||||
|
||||
set(state, x: { key: string; value: any }) {
|
||||
state[x.key] = x.value;
|
||||
},
|
||||
@@ -218,6 +229,15 @@ export const store = createStore({
|
||||
state: defaultDeviceUserSettings,
|
||||
|
||||
mutations: {
|
||||
overwrite(state, x) {
|
||||
for (const k of Object.keys(state)) {
|
||||
if (x[k] === undefined) delete state[k];
|
||||
}
|
||||
for (const k of Object.keys(x)) {
|
||||
state[k] = x[k];
|
||||
}
|
||||
},
|
||||
|
||||
init(state, x) {
|
||||
for (const [key, value] of Object.entries(defaultDeviceUserSettings)) {
|
||||
if (x[key]) {
|
||||
|
@@ -1,9 +1,4 @@
|
||||
<template>
|
||||
<ZenUI v-if="zen"/>
|
||||
<VisitorUI v-else-if="!$store.getters.isSignedIn"/>
|
||||
<DeckUI v-else-if="deckmode"/>
|
||||
<DefaultUI v-else/>
|
||||
|
||||
<component v-for="popup in popups"
|
||||
:key="popup.id"
|
||||
:is="popup.component"
|
||||
@@ -13,27 +8,23 @@
|
||||
|
||||
<XUpload v-if="uploads.length > 0"/>
|
||||
|
||||
<XStreamIndicator/>
|
||||
|
||||
<div id="wait" v-if="pendingApiRequestsCount > 0"></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineAsyncComponent, defineComponent } from 'vue';
|
||||
import { deckmode } from '@/config';
|
||||
import { popups, uploads, pendingApiRequestsCount } from '@/os';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
DefaultUI: defineAsyncComponent(() => import('@/ui/default.vue')),
|
||||
DeckUI: defineAsyncComponent(() => import('@/ui/deck.vue')),
|
||||
ZenUI: defineAsyncComponent(() => import('@/ui/zen.vue')),
|
||||
VisitorUI: defineAsyncComponent(() => import('@/ui/visitor.vue')),
|
||||
XUpload: defineAsyncComponent(() => import('@/components/upload.vue')),
|
||||
XStreamIndicator: defineAsyncComponent(() => import('./stream-indicator.vue')),
|
||||
XUpload: defineAsyncComponent(() => import('./upload.vue')),
|
||||
},
|
||||
|
||||
setup() {
|
||||
return {
|
||||
zen: window.location.search === '?zen',
|
||||
deckmode,
|
||||
uploads,
|
||||
popups,
|
||||
pendingApiRequestsCount,
|
@@ -29,7 +29,7 @@
|
||||
<button v-if="$store.getters.isSignedIn" class="nav _button" @click="showNav()"><Fa :icon="faBars"/><i v-if="navIndicated"><Fa :icon="faCircle"/></i></button>
|
||||
<button v-if="$store.getters.isSignedIn" class="post _buttonPrimary" @click="post()"><Fa :icon="faPencilAlt"/></button>
|
||||
|
||||
<StreamIndicator v-if="$store.getters.isSignedIn"/>
|
||||
<XCommon/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -47,9 +47,11 @@ import XHeader from './_common_/header.vue';
|
||||
import { getScrollContainer } from '@/scripts/scroll';
|
||||
import * as os from '@/os';
|
||||
import { sidebarDef } from '@/sidebar';
|
||||
import XCommon from './_common_/common.vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
XCommon,
|
||||
XSidebar,
|
||||
XHeader,
|
||||
DeckColumn,
|
||||
|
157
src/client/ui/default.side.vue
Normal file
157
src/client/ui/default.side.vue
Normal file
@@ -0,0 +1,157 @@
|
||||
<template>
|
||||
<div class="qvzfzxam _narrow_" v-if="component">
|
||||
<div class="container">
|
||||
<header class="header" @contextmenu.prevent.stop="onContextmenu">
|
||||
<button class="_button" @click="back()" v-if="history.length > 0"><Fa :icon="faChevronLeft"/></button>
|
||||
<button class="_button" style="pointer-events: none;" v-else><!-- マージンのバランスを取るためのダミー --></button>
|
||||
<XHeader class="title" :info="pageInfo" :with-back="false"/>
|
||||
<button class="_button" @click="close()"><Fa :icon="faTimes"/></button>
|
||||
</header>
|
||||
<component :is="component" v-bind="props" :ref="changePage"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { faTimes, faChevronLeft, faExpandAlt, faWindowMaximize, faExternalLinkAlt, faLink } from '@fortawesome/free-solid-svg-icons';
|
||||
import XHeader from './_common_/header.vue';
|
||||
import * as os from '@/os';
|
||||
import copyToClipboard from '@/scripts/copy-to-clipboard';
|
||||
import { resolve } from '@/router';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
XHeader
|
||||
},
|
||||
|
||||
provide() {
|
||||
return {
|
||||
navHook: (url) => {
|
||||
this.navigate(url);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
url: null,
|
||||
component: null,
|
||||
props: {},
|
||||
pageInfo: null,
|
||||
history: [],
|
||||
faTimes, faChevronLeft,
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
changePage(page) {
|
||||
if (page == null) return;
|
||||
if (page.INFO) {
|
||||
this.pageInfo = page.INFO;
|
||||
}
|
||||
},
|
||||
|
||||
navigate(url, record = true) {
|
||||
if (record && this.url) this.history.push(this.url);
|
||||
this.url = url;
|
||||
const { component, props } = resolve(url);
|
||||
this.component = component;
|
||||
this.props = props;
|
||||
},
|
||||
|
||||
back() {
|
||||
this.navigate(this.history.pop(), false);
|
||||
},
|
||||
|
||||
close() {
|
||||
this.url = null;
|
||||
this.component = null;
|
||||
this.props = {};
|
||||
},
|
||||
|
||||
onContextmenu(e) {
|
||||
os.contextMenu([{
|
||||
type: 'label',
|
||||
text: this.url,
|
||||
}, {
|
||||
icon: faExpandAlt,
|
||||
text: this.$t('showInPage'),
|
||||
action: () => {
|
||||
this.$router.push(this.url);
|
||||
this.close();
|
||||
}
|
||||
}, {
|
||||
icon: faWindowMaximize,
|
||||
text: this.$t('openInWindow'),
|
||||
action: () => {
|
||||
os.pageWindow(this.url);
|
||||
this.close();
|
||||
}
|
||||
}, null, {
|
||||
icon: faExternalLinkAlt,
|
||||
text: this.$t('openInNewTab'),
|
||||
action: () => {
|
||||
window.open(this.url, '_blank');
|
||||
this.close();
|
||||
}
|
||||
}, {
|
||||
icon: faLink,
|
||||
text: this.$t('copyLink'),
|
||||
action: () => {
|
||||
copyToClipboard(this.url);
|
||||
}
|
||||
}], e);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.qvzfzxam {
|
||||
$header-height: 58px; // TODO: どこかに集約したい
|
||||
|
||||
--section-padding: 16px;
|
||||
--margin: var(--marginHalf);
|
||||
|
||||
> .container {
|
||||
position: fixed;
|
||||
width: 370px;
|
||||
height: 100vh;
|
||||
overflow: auto;
|
||||
box-sizing: border-box;
|
||||
|
||||
> .header {
|
||||
display: flex;
|
||||
position: sticky;
|
||||
z-index: 1000;
|
||||
top: 0;
|
||||
height: $header-height;
|
||||
width: 100%;
|
||||
line-height: $header-height;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
//background-color: var(--panel);
|
||||
-webkit-backdrop-filter: blur(32px);
|
||||
backdrop-filter: blur(32px);
|
||||
background-color: var(--header);
|
||||
border-bottom: solid 1px var(--divider);
|
||||
|
||||
> ._button {
|
||||
height: $header-height;
|
||||
width: $header-height;
|
||||
|
||||
&:hover {
|
||||
color: var(--fgHighlighted);
|
||||
}
|
||||
}
|
||||
|
||||
> .title {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@@ -20,6 +20,8 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<XSide v-if="isDesktop" class="side" ref="side"/>
|
||||
|
||||
<div v-if="isDesktop" class="widgets">
|
||||
<div ref="widgetsSpacer"></div>
|
||||
<XWidgets @mounted="attachSticky"/>
|
||||
@@ -47,19 +49,21 @@
|
||||
<XWidgets v-if="widgetsShowing" class="tray"/>
|
||||
</transition>
|
||||
|
||||
<StreamIndicator/>
|
||||
<XCommon/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, defineAsyncComponent } from 'vue';
|
||||
import { defineComponent, defineAsyncComponent, markRaw } from 'vue';
|
||||
import { faLayerGroup, faBars, faHome, faCircle } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faBell } from '@fortawesome/free-regular-svg-icons';
|
||||
import { host } from '@/config';
|
||||
import { search } from '@/scripts/search';
|
||||
import { StickySidebar } from '@/scripts/sticky-sidebar';
|
||||
import XSidebar from '@/components/sidebar.vue';
|
||||
import XCommon from './_common_/common.vue';
|
||||
import XHeader from './_common_/header.vue';
|
||||
import XSide from './default.side.vue';
|
||||
import * as os from '@/os';
|
||||
import { sidebarDef } from '@/sidebar';
|
||||
|
||||
@@ -67,9 +71,19 @@ const DESKTOP_THRESHOLD = 1100;
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
XCommon,
|
||||
XSidebar,
|
||||
XHeader,
|
||||
XWidgets: defineAsyncComponent(() => import('./default.widgets.vue')),
|
||||
XSide, // NOTE: dynamic importするとAsyncComponentWrapperが間に入るせいでref取得できなくて面倒になる
|
||||
},
|
||||
|
||||
provide() {
|
||||
return {
|
||||
sideViewHook: (url) => {
|
||||
this.$refs.side.navigate(url);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
data() {
|
||||
@@ -245,7 +259,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
.mk-app {
|
||||
$header-height: 60px;
|
||||
$header-height: 58px; // TODO: どこかに集約したい
|
||||
$ui-font-size: 1em; // TODO: どこかに集約したい
|
||||
$widgets-hide-threshold: 1090px;
|
||||
|
||||
@@ -301,6 +315,12 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
> .side {
|
||||
min-width: 370px;
|
||||
max-width: 370px;
|
||||
border-left: solid 1px var(--divider);
|
||||
}
|
||||
|
||||
> .widgets {
|
||||
padding: 0 var(--margin);
|
||||
border-left: solid 1px var(--divider);
|
||||
|
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div class="mk-app">
|
||||
<header>
|
||||
<router-link class="link" to="/">{{ $t('home') }}</router-link>
|
||||
<router-link class="link" to="/announcements">{{ $t('announcements') }}</router-link>
|
||||
<router-link class="link" to="/channels">{{ $t('channel') }}</router-link>
|
||||
<router-link class="link" to="/about">{{ $t('aboutX', { x: instanceName || host }) }}</router-link>
|
||||
<MkA class="link" to="/">{{ $t('home') }}</MkA>
|
||||
<MkA class="link" to="/announcements">{{ $t('announcements') }}</MkA>
|
||||
<MkA class="link" to="/channels">{{ $t('channel') }}</MkA>
|
||||
<MkA class="link" to="/about">{{ $t('aboutX', { x: instanceName || host }) }}</MkA>
|
||||
</header>
|
||||
|
||||
<div class="banner" :style="{ backgroundImage: `url(${ $store.state.instance.meta.bannerUrl })` }">
|
||||
@@ -23,12 +23,12 @@
|
||||
</router-view>
|
||||
</main>
|
||||
<div class="powered-by">
|
||||
<b><router-link to="/">{{ host }}</router-link></b>
|
||||
<b><MkA to="/">{{ host }}</MkA></b>
|
||||
<small>Powered by <a href="https://github.com/syuilo/misskey" target="_blank">Misskey</a></small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<StreamIndicator v-if="$store.getters.isSignedIn"/>
|
||||
<XCommon/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -39,12 +39,14 @@ import { host, instanceName } from '@/config';
|
||||
import { search } from '@/scripts/search';
|
||||
import * as os from '@/os';
|
||||
import XHeader from './_common_/header.vue';
|
||||
import XCommon from './_common_/common.vue';
|
||||
|
||||
const DESKTOP_THRESHOLD = 1100;
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
XHeader
|
||||
XCommon,
|
||||
XHeader,
|
||||
},
|
||||
|
||||
data() {
|
||||
@@ -130,7 +132,7 @@ export default defineComponent({
|
||||
line-height: 60px;
|
||||
padding: 0 0.7em;
|
||||
|
||||
&.router-link-active {
|
||||
&.MkA-active {
|
||||
box-shadow: 0 -2px 0 0 var(--accent) inset;
|
||||
}
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<StreamIndicator/>
|
||||
<XCommon/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -28,10 +28,12 @@ import { faBell } from '@fortawesome/free-regular-svg-icons';
|
||||
import { host } from '@/config';
|
||||
import { search } from '@/scripts/search';
|
||||
import XHeader from './_common_/header.vue';
|
||||
import XCommon from './_common_/common.vue';
|
||||
import * as os from '@/os';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
XCommon,
|
||||
XHeader,
|
||||
},
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<transition-group tag="div" name="chart" class="tags" v-else>
|
||||
<div v-for="stat in stats" :key="stat.tag">
|
||||
<div class="tag">
|
||||
<router-link class="a" :to="`/tags/${ encodeURIComponent(stat.tag) }`" :title="stat.tag">#{{ stat.tag }}</router-link>
|
||||
<MkA class="a" :to="`/tags/${ encodeURIComponent(stat.tag) }`" :title="stat.tag">#{{ stat.tag }}</MkA>
|
||||
<p>{{ $t('nUsersMentioned', { n: stat.usersCount }) }}</p>
|
||||
</div>
|
||||
<MkMiniChart class="chart" :src="stat.chart"/>
|
||||
|
77
yarn.lock
77
yarn.lock
@@ -1344,7 +1344,7 @@ acorn@^7.4.0:
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
|
||||
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
|
||||
|
||||
acorn@^8.0.3:
|
||||
acorn@^8.0.4:
|
||||
version "8.0.4"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.0.4.tgz#7a3ae4191466a6984eee0fe3407a4f3aa9db8354"
|
||||
integrity sha512-XNP0PqF1XD19ZlLKvB7cMmnZswW4C/03pRHgirB30uSJTaS3A3V1/P4sS3HPvFmjoriPCJQs+JDSbm4bL1TxGQ==
|
||||
@@ -1931,7 +1931,7 @@ browserslist@^4.0.0:
|
||||
node-releases "^1.1.53"
|
||||
pkg-up "^2.0.0"
|
||||
|
||||
browserslist@^4.14.3:
|
||||
browserslist@^4.14.5:
|
||||
version "4.14.5"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.5.tgz#1c751461a102ddc60e40993639b709be7f2c4015"
|
||||
integrity sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA==
|
||||
@@ -3476,10 +3476,10 @@ enhanced-resolve@^4.0.0:
|
||||
memory-fs "^0.5.0"
|
||||
tapable "^1.0.0"
|
||||
|
||||
enhanced-resolve@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.2.0.tgz#3db3307a608f236f33aeea79303d32915792cbab"
|
||||
integrity sha512-NZlGLl8DxmZoq0uqPPtJfsCAir68uR047+Udsh1FH4+5ydGQdMurn/A430A1BtxASVmMEuS7/XiJ5OxJ9apAzQ==
|
||||
enhanced-resolve@^5.3.0:
|
||||
version "5.3.1"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.3.1.tgz#3f988d0d7775bdc2d96ede321dc81f8249492f57"
|
||||
integrity sha512-G1XD3MRGrGfNcf6Hg0LVZG7GIKcYkbfHa5QMxt1HDUTdYoXH0JR1xXyg+MaKLF73E9A27uWNVxvFivNRYeUB6w==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.4"
|
||||
tapable "^2.0.0"
|
||||
@@ -3694,14 +3694,6 @@ eslint-scope@^5.0.0:
|
||||
esrecurse "^4.1.0"
|
||||
estraverse "^4.1.1"
|
||||
|
||||
eslint-scope@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5"
|
||||
integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==
|
||||
dependencies:
|
||||
esrecurse "^4.1.0"
|
||||
estraverse "^4.1.1"
|
||||
|
||||
eslint-scope@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
|
||||
@@ -6632,6 +6624,11 @@ nanoid@^3.1.12:
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.12.tgz#6f7736c62e8d39421601e4a0c77623a97ea69654"
|
||||
integrity sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==
|
||||
|
||||
nanoid@^3.1.15:
|
||||
version "3.1.15"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.15.tgz#28e7c4ce56aff2d0c2d37814c7aef9d6c5b3e6f3"
|
||||
integrity sha512-n8rXUZ8UU3lV6+43atPrSizqzh25n1/f00Wx1sCiE7R1sSHytZLTTiQl8DjC4IDLOnEZDlgJhy0yO4VsIpMxow==
|
||||
|
||||
nanomatch@^1.2.9:
|
||||
version "1.2.13"
|
||||
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
|
||||
@@ -7880,14 +7877,14 @@ postcss-value-parser@^4.1.0:
|
||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb"
|
||||
integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==
|
||||
|
||||
postcss@8.1.2, postcss@^8.1.1:
|
||||
version "8.1.2"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.2.tgz#9731fcaa4f7b0bef47121821bdae9eeb609a324c"
|
||||
integrity sha512-mToqEVFq8jF9TFhlIK4HhE34zknFJuNTgqtsr60vUvrWn+9TIYugCwiV1JZRxCuOrej2jjstun1bn4Bc7/1HkA==
|
||||
postcss@8.1.3:
|
||||
version "8.1.3"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.3.tgz#b25138b872ca9f9512c218d9d57ebb59015a9c39"
|
||||
integrity sha512-AKsHGqd7HmXmL/EgyAjI4Gx719A5yQdt9HzyXrI8M/hzxfumecYS95kfvIt40UZqPVNoEt0Va1M3PG54XtNPbg==
|
||||
dependencies:
|
||||
colorette "^1.2.1"
|
||||
line-column "^1.0.2"
|
||||
nanoid "^3.1.12"
|
||||
nanoid "^3.1.15"
|
||||
source-map "^0.6.1"
|
||||
|
||||
postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.27, postcss@^7.0.5, postcss@^7.0.6:
|
||||
@@ -7908,6 +7905,16 @@ postcss@^7.0.32:
|
||||
source-map "^0.6.1"
|
||||
supports-color "^6.1.0"
|
||||
|
||||
postcss@^8.1.1:
|
||||
version "8.1.2"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.2.tgz#9731fcaa4f7b0bef47121821bdae9eeb609a324c"
|
||||
integrity sha512-mToqEVFq8jF9TFhlIK4HhE34zknFJuNTgqtsr60vUvrWn+9TIYugCwiV1JZRxCuOrej2jjstun1bn4Bc7/1HkA==
|
||||
dependencies:
|
||||
colorette "^1.2.1"
|
||||
line-column "^1.0.2"
|
||||
nanoid "^3.1.12"
|
||||
source-map "^0.6.1"
|
||||
|
||||
postgres-array@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e"
|
||||
@@ -8837,10 +8844,10 @@ safe-regex@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
||||
sass-loader@10.0.3:
|
||||
version "10.0.3"
|
||||
resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.0.3.tgz#9e2f1bfdd6355f2adde4e4835d838b020bf800b0"
|
||||
integrity sha512-W4+FV5oUdYy0PnC11ZoPrcAexODgDCa3ngxoy5X5qBhZYoPz9FPjb6Oox8Aa0ZYEyx34k8AQfOVuvqefOSAAUQ==
|
||||
sass-loader@10.0.4:
|
||||
version "10.0.4"
|
||||
resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.0.4.tgz#ec7181096947d078d60a1d76d527f47c19b151d8"
|
||||
integrity sha512-zhdZ8qvZM4iL5XjLVEjJLvKWvC+MB+hHgzL2x/Nf7UHpUNmPYsJvypW79bW39g4LZ603dH/dRSsRYzJJIljtdA==
|
||||
dependencies:
|
||||
klona "^2.0.4"
|
||||
loader-utils "^2.0.0"
|
||||
@@ -9623,10 +9630,10 @@ syslog-pro@1.0.0:
|
||||
dependencies:
|
||||
moment "^2.22.2"
|
||||
|
||||
systeminformation@4.27.8:
|
||||
version "4.27.8"
|
||||
resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-4.27.8.tgz#40e7d3d784f5358a05dace8d019015e7c6382628"
|
||||
integrity sha512-KTjL78Y4syAos1G4Ux4FXnyvTceqwMaTAniRbI56w6MK11Q8V30eh6Sqsx82GUjE8nJgT/8L7drJyjt7BZu3cw==
|
||||
systeminformation@4.27.10:
|
||||
version "4.27.10"
|
||||
resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-4.27.10.tgz#d15181c2872c46de21607d302bd161659a78b148"
|
||||
integrity sha512-qXuJaa+3A1bLkFNr/rn3H9Uw8UGodSbq+1QjxDbXua9iexfw4UIdAZZTyu9kE5OkXG1Lt6u0z4aZfxYRVL68EA==
|
||||
|
||||
syuilo-password-strength@0.0.1:
|
||||
version "0.0.1"
|
||||
@@ -10634,10 +10641,10 @@ webpack-sources@^2.0.1:
|
||||
source-list-map "^2.0.1"
|
||||
source-map "^0.6.1"
|
||||
|
||||
webpack@5.1.3:
|
||||
version "5.1.3"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.1.3.tgz#a6e4fd250ef2513f94844ae5d8f7570215a2ac49"
|
||||
integrity sha512-bNBF5EOpt5a6NeCBFu0+8KJtG61cVmOb2b/a5tPNRLz3OWgDpHMbmnDkaSm3nf/UQ6ufw4PWYGVsVOAi8UfL2A==
|
||||
webpack@5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.2.0.tgz#02f22466b79751a80a50f20f027a716e296b3ef5"
|
||||
integrity sha512-evtOjOJQq3zaHJIWsJjM4TGtNHtSrNVAIyQ+tdPW/fRd+4PLGbUG6S3xt+N4+QwDBOaCVd0xCWiHd4R6lWO5DQ==
|
||||
dependencies:
|
||||
"@types/eslint-scope" "^3.7.0"
|
||||
"@types/estree" "^0.0.45"
|
||||
@@ -10645,11 +10652,11 @@ webpack@5.1.3:
|
||||
"@webassemblyjs/helper-module-context" "1.9.0"
|
||||
"@webassemblyjs/wasm-edit" "1.9.0"
|
||||
"@webassemblyjs/wasm-parser" "1.9.0"
|
||||
acorn "^8.0.3"
|
||||
browserslist "^4.14.3"
|
||||
acorn "^8.0.4"
|
||||
browserslist "^4.14.5"
|
||||
chrome-trace-event "^1.0.2"
|
||||
enhanced-resolve "^5.2.0"
|
||||
eslint-scope "^5.1.0"
|
||||
enhanced-resolve "^5.3.0"
|
||||
eslint-scope "^5.1.1"
|
||||
events "^3.2.0"
|
||||
glob-to-regexp "^0.4.1"
|
||||
graceful-fs "^4.2.4"
|
||||
|
Reference in New Issue
Block a user