Compare commits
102 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 929e545514 | |||
| 3e7a87f75a | |||
| caf40e40fb | |||
| b608f63a1a | |||
| dc44d9a0a8 | |||
| bb926dd301 | |||
| 79cb836483 | |||
| f1c4e4a10e | |||
| 798aedfc0f | |||
| 1077c2a637 | |||
| cbe689607c | |||
| 948b70cb0f | |||
| 0263539202 | |||
| 52e54cf0dc | |||
| 24e7eeca0f | |||
| d76345264d | |||
| 0eb115bf7e | |||
| 30d2a1d8b6 | |||
| 857c88e8d6 | |||
| ffb9646ce9 | |||
| db3724cf33 | |||
| 466c083233 | |||
| ae2267220b | |||
| c92744c3d3 | |||
| 35f075b887 | |||
| 6cc4edc5e8 | |||
| c06091f78a | |||
| f85399e355 | |||
| 47aaf04481 | |||
| 7063a6925f | |||
| 3cd04c4b81 | |||
| 942c802431 | |||
| e6754eb880 | |||
| 70d02cf1be | |||
| ef646b9576 | |||
| ecd541873b | |||
| 5d10642e07 | |||
| da34acd35f | |||
| 0108b8bfe3 | |||
| b16c3798a4 | |||
| 4b33c42da7 | |||
| 961b3177d5 | |||
| 7dc85a624e | |||
| bfd215542b | |||
| d752275730 | |||
| be7e389bb5 | |||
| f96c60c1a0 | |||
| 99234632b2 | |||
| 3a7393e1dd | |||
| 2d12f8b49e | |||
| 3461f0ffc9 | |||
| f24f7f14c3 | |||
| 917e57d475 | |||
| 6b43c5c18c | |||
| 7cd7059fbc | |||
| 591a5c277c | |||
| 164959a0c5 | |||
| 47fa7bb22a | |||
| 5b250c15f8 | |||
| b60f9fbc00 | |||
| 8accb78fa9 | |||
| 3d7c3c39ff | |||
| dd628006ec | |||
| 6cec662ec4 | |||
| 588b838deb | |||
| 05203e2cf0 | |||
| 80f8c2de78 | |||
| d011aeefc5 | |||
| 44627c3b5f | |||
| 925a61e4d7 | |||
| d8b17daf9d | |||
| 5e40930f11 | |||
| b6c9ab0c15 | |||
| 1a8f41010e | |||
| 67f58b5217 | |||
| cdef5cd1ad | |||
| 2efae80b97 | |||
| 1157df1407 | |||
| 94ac0a7797 | |||
| 35cf05d6ca | |||
| 18e1efc7ec | |||
| 71ebb068f7 | |||
| e9170e630c | |||
| 6ae642245e | |||
| a34d8549d0 | |||
| 52e1df2df3 | |||
| d7a5efbd36 | |||
| 9f5123d176 | |||
| ea7d4d323e | |||
| 18da55bd81 | |||
| 25424fe62e | |||
| c7e60cfd0c | |||
| 3e19bcb6cb | |||
| 6573c3b522 | |||
| 17fff8c665 | |||
| fa9f0d9ff9 | |||
| 77ccf3b929 | |||
| 4b205aee91 | |||
| d348e211d4 | |||
| 42539575a6 | |||
| 8bce241170 | |||
| c039665a97 |
@@ -12,7 +12,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x, 14.x, 15.x]
|
||||
node-version: [14.x, 16.x]
|
||||
|
||||
services:
|
||||
postgres:
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
v14.15.5
|
||||
v16.2.0
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ Configuration files are located in [`/.circleci`](/.circleci).
|
||||
* Your PR should include all source files (e.g. `.png`, `.blend`) of your models (for later editing).
|
||||
* Your PR must include the glTF binary files (`.glb`) of your models.
|
||||
* Add a locale key `room.furnitures.YOUR_ITEM` at [`/locales/ja-JP.yml`](/locales/ja-JP.yml).
|
||||
* Add a furniture definition at [`/src/client/app/common/scripts/room/furnitures.json5`](/src/client/app/common/scripts/room/furnitures.json5).
|
||||
* Add a furniture definition at [`src/client/scripts/room/furnitures.json5`](src/client/scripts/room/furnitures.json5).
|
||||
|
||||
If you have no experience on 3D modeling, we suggest to use the free 3DCG software [Blender](https://www.blender.org/).
|
||||
You can find information on glTF 2.0 at [glTF 2.0 — Blender Manual]( https://docs.blender.org/manual/en/dev/addons/io_scene_gltf2.html).
|
||||
|
||||
@@ -6,10 +6,6 @@ And is distributed under The GNU Affero General Public License Version 3, you sh
|
||||
|
||||
Misskey includes several third-party Open-Source softwares.
|
||||
|
||||
Unicode emoji regular expressions by Twitter, Inc.
|
||||
License: MIT
|
||||
https://github.com/twitter/twemoji-parser/blob/master/LICENSE.md
|
||||
|
||||
Emoji keywords for Unicode 11 and below by Mu-An Chiou
|
||||
License: MIT
|
||||
https://github.com/muan/emojilib/blob/master/LICENSE
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM node:14.15.5-alpine3.13 AS base
|
||||
FROM node:16.2.0-alpine3.13 AS base
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
|
||||
@@ -99,6 +99,11 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
||||
|
||||
To receive updates of this repo, follow [@repo@misskey.io](https://misskey.io/@repo) on fediverse.
|
||||
|
||||
Related projects
|
||||
----------------------------------------------------------------
|
||||
- [misskey.js](https://github.com/misskey-dev/misskey.js) - Misskey SDK for JavaScript
|
||||
- [mfm.js](https://github.com/misskey-dev/mfm.js) - MFM parser
|
||||
|
||||
:heart: Backers
|
||||
----------------------------------------------------------------
|
||||
<!-- PATREON_START -->
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# Reporting Security Issues
|
||||
|
||||
If you discover a security issue in Misskey, please report it by sending an
|
||||
email to [syuilotan@yahoo.co.jp](mailto:syuilotan@yahoo.co.jp).
|
||||
|
||||
This will allow us to assess the risk, and make a fix available before we add a
|
||||
bug report to the GitHub repository.
|
||||
|
||||
Thanks for helping make Misskey safe for everyone.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 38 KiB |
Binary file not shown.
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as gulp from 'gulp';
|
||||
import * as rimraf from 'rimraf';
|
||||
import rimraf from 'rimraf';
|
||||
const replace = require('gulp-replace');
|
||||
const terser = require('gulp-terser');
|
||||
const cssnano = require('gulp-cssnano');
|
||||
|
||||
+2
-2
@@ -259,8 +259,6 @@ monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "الصفحات"
|
||||
integration: "دمج"
|
||||
connectSerice: "أوصل"
|
||||
disconnectSerice: "قطع الاتصال"
|
||||
enableLocalTimeline: "تفعيل الخيط المحلي"
|
||||
enableGlobalTimeline: "تفعيل الخيط الزمني الشامل"
|
||||
disablingTimelinesInfo: "سيتمكن المسؤولون ومن تعديل دائمًا و من الوصول إلى جميع المخططات الزمنية ، حتى إذا لم يتم تمكينها."
|
||||
@@ -430,6 +428,8 @@ inUse: "مستخدم"
|
||||
info: "عن"
|
||||
user: "المستخدمون"
|
||||
administration: "إدارة "
|
||||
expiration: "ينتهي استطلاع الرأي في"
|
||||
middle: "متوسط"
|
||||
_email:
|
||||
_follow:
|
||||
title: "يتابعك"
|
||||
|
||||
+31
-2
@@ -1,11 +1,13 @@
|
||||
---
|
||||
_lang_: "Čeština"
|
||||
headlineMisskey: "Síť propojená poznámkami"
|
||||
introMisskey: "Vítejte! Misskey je otevřený a decentralizovaný microblogový servis.\n\"Poznámkami\" můžete sdílet co se zrovna děje se všemi ve Vašem okolí. 📡\nPomocí \"reakcí\" můžete sdílet své názory a pocity na ostatní poznámky. 👍\nPojďte objevovat nový svět! 🚀"
|
||||
monthAndDay: "{day}. {month}."
|
||||
search: "Vyhledávání"
|
||||
notifications: "Oznámení"
|
||||
username: "Uživatelské jméno"
|
||||
password: "Heslo"
|
||||
forgotPassword: "Zapomenuté heslo"
|
||||
fetchingAsApObject: "Načítám data z Fediversu..."
|
||||
ok: "Potvrdit"
|
||||
gotIt: "Rozumím!"
|
||||
@@ -72,6 +74,7 @@ error: "Chyba"
|
||||
somethingHappened: "Jejda. Něco se nepovedlo."
|
||||
retry: "Opakovat"
|
||||
pageLoadError: "Nepodařilo se načíst stránku"
|
||||
enterListName: "Jméno seznamu"
|
||||
privacy: "Soukromí"
|
||||
follow: "Sledovaní"
|
||||
unfollow: "Přestat sledovat"
|
||||
@@ -112,16 +115,24 @@ emojiName: "Jméno emoji"
|
||||
emojiUrl: "URL obrázku"
|
||||
addEmoji: "Přidat emoji"
|
||||
settingGuide: "Doporučené nastavení"
|
||||
cacheRemoteFiles: "Ukládání vzdálených souborů do mezipaměti"
|
||||
cacheRemoteFilesDescription: "Zakázání tohoto nastavení způsobí, že vzdálené soubory budou odkazovány přímo, místo aby byly ukládány do mezipaměti. Tím se ušetří úložiště na serveru, ale zvýší se provoz, protože se negenerují miniatury."
|
||||
flagAsBot: "Tento účet je bot"
|
||||
flagAsBotDescription: "Pokud je tento účet kontrolován programem zaškrtněte tuto možnost. To označí tento účet jako bot pro ostatní vývojáře a zabrání tak nekonečným interakcím s ostatními boty a upraví Misskey systém aby se choval k tomuhle účtu jako bot."
|
||||
flagAsCat: "Tenhle účet je kočka"
|
||||
flagAsCatDescription: "Vyberte tuto možnost aby tento účet byl označen jako kočka."
|
||||
autoAcceptFollowed: "Automaticky akceptovat následování od účtů které sledujete"
|
||||
addAccount: "Přidat účet"
|
||||
loginFailed: "Přihlášení se nezdařilo."
|
||||
showOnRemote: "Více na původním profilu"
|
||||
general: "Obecně"
|
||||
wallpaper: "Obrázek na pozadí"
|
||||
setWallpaper: "Nastavení obrázku na pozadí"
|
||||
removeWallpaper: "Odstranit pozadí"
|
||||
youHaveNoLists: "Nemáte žádné seznamy"
|
||||
proxyAccount: "Proxy účet"
|
||||
proxyAccountDescription: "Proxy účet je účet, který za určitých podmínek sleduje uživatele na dálku vaším jménem. Například když uživatel zařadí vzdáleného uživatele do seznamu, pokud nikdo nesleduje uživatele na seznamu, aktivita nebude doručena instanci, takže místo toho bude uživatele sledovat účet proxy."
|
||||
host: "Hostitel"
|
||||
selectUser: "Vyberte uživatele"
|
||||
recipient: "Pro"
|
||||
annotation: "Komentáře"
|
||||
@@ -139,6 +150,8 @@ operations: "Operace"
|
||||
software: "Software"
|
||||
version: "Verze"
|
||||
metadata: "Metadata"
|
||||
withNFiles: "{n} soubor(ů)"
|
||||
monitor: "Monitorovat"
|
||||
jobQueue: "Fronta úloh"
|
||||
cpuAndMemory: "CPU a paměť"
|
||||
network: "Síť"
|
||||
@@ -204,8 +217,12 @@ remoteUserCaution: "Tyto informace nemusí být aktuální jelikož uživatel je
|
||||
activity: "Aktivita"
|
||||
images: "Obrázky"
|
||||
birthday: "Datum narození"
|
||||
yearsOld: "{age} let"
|
||||
registeredDate: "Datum registrace"
|
||||
location: "Lokace"
|
||||
theme: "Vzhled"
|
||||
themeForLightMode: "Vzhled pro použití ve světlém režimu"
|
||||
themeForDarkMode: "Vzhled k použití v tmavém režimu"
|
||||
light: "Světlý"
|
||||
dark: "Tmavý"
|
||||
lightThemes: "Světlý vzhled"
|
||||
@@ -252,8 +269,6 @@ monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Stránky"
|
||||
integration: "Integrace"
|
||||
connectSerice: "Připojit"
|
||||
disconnectSerice: "Odpojit"
|
||||
enableLocalTimeline: "Povolit lokální čas"
|
||||
enableGlobalTimeline: "Povolit globální čas"
|
||||
registration: "Registrace"
|
||||
@@ -319,6 +334,10 @@ retype: "Zadejte znovu"
|
||||
noteOf: "{user} poznámky"
|
||||
inviteToGroup: "Pozvat do skupiny"
|
||||
invitations: "Pozvat"
|
||||
checking: "Ověřuji"
|
||||
available: "K dispozici"
|
||||
unavailable: "Není k dispozici"
|
||||
usernameInvalidFormat: "Písmena, čísla a _ jsou povolená."
|
||||
tooShort: "Příliš krátké"
|
||||
tooLong: "Příliš dlouhé"
|
||||
weakPassword: "Slabé heslo"
|
||||
@@ -330,7 +349,13 @@ signinWith: "Přihlásit se s {x}"
|
||||
signinFailed: "Nelze se přihlásit. Zkontrolujte prosím své uživatelské jméno a heslo."
|
||||
or: "Nebo"
|
||||
language: "Jazyk"
|
||||
uiLanguage: "Jazyk uživatelského rozhraní"
|
||||
groupInvited: "Pozvat do skupiny"
|
||||
aboutX: "O {x}"
|
||||
useOsNativeEmojis: "Použití nativních emoji operačního systému"
|
||||
youHaveNoGroups: "Nemáte žádné skupiny"
|
||||
joinOrCreateGroup: "Můžete požádat o pozvání do stávající skupiny nebo vytvořit novou."
|
||||
noHistory: "Žádná historie"
|
||||
signinHistory: "Historie přihlášení"
|
||||
category: "Kategorie"
|
||||
tags: "Štítky"
|
||||
@@ -371,6 +396,7 @@ rooms: "Místnost"
|
||||
inboxUrl: "Inbox URL"
|
||||
deletedNote: "Odstraněné příspěvky"
|
||||
invisibleNote: "Skryté příspěvky"
|
||||
smtpHost: "Hostitel"
|
||||
smtpUser: "Uživatelské jméno"
|
||||
smtpPass: "Heslo"
|
||||
clearCache: "Vyprázdnit mezipaměť"
|
||||
@@ -416,6 +442,8 @@ _timelines:
|
||||
_rooms:
|
||||
_roomType:
|
||||
default: "Výchozí"
|
||||
_furnitures:
|
||||
monitor: "Monitorovat"
|
||||
_pages:
|
||||
blocks:
|
||||
image: "Obrázky"
|
||||
@@ -438,6 +466,7 @@ _pages:
|
||||
types:
|
||||
array: "Seznamy"
|
||||
_notification:
|
||||
youWereInvitedToGroup: "Pozvat do skupiny"
|
||||
_types:
|
||||
follow: "Sledovaní"
|
||||
mention: "Zmínění"
|
||||
|
||||
+27
-5
@@ -7,6 +7,7 @@ search: "Suchen"
|
||||
notifications: "Benachrichtigungen"
|
||||
username: "Benutzername"
|
||||
password: "Passwort"
|
||||
forgotPassword: "Passwort vergessen"
|
||||
fetchingAsApObject: "Wird aus dem Fediverse angefragt..."
|
||||
ok: "OK"
|
||||
gotIt: "Verstanden!"
|
||||
@@ -278,6 +279,7 @@ emptyDrive: "Drive ist leer"
|
||||
emptyFolder: "Der Ordner ist leer"
|
||||
unableToDelete: "Nicht löschbar"
|
||||
inputNewFileName: "Gib einen neuen Dateinamen ein"
|
||||
inputNewDescription: "Gib eine neue Beschreibung ein"
|
||||
inputNewFolderName: "Gib einen neuen Ordnernamen ein"
|
||||
circularReferenceFolder: "Der Zielordner ist ein Unterorder des Ordners, den du verschieben möchtest."
|
||||
hasChildFilesOrFolders: "Dieser Ordner kann nicht gelöscht werden, da er nicht leer ist."
|
||||
@@ -298,8 +300,8 @@ reject: "Ablehnen"
|
||||
normal: "Normal"
|
||||
instanceName: "Name der Instanz"
|
||||
instanceDescription: "Beschreibung der Instanz"
|
||||
maintainerName: "Betreiber"
|
||||
maintainerEmail: "Betreiber-Email"
|
||||
maintainerName: "Administrator"
|
||||
maintainerEmail: "Administrator-Email"
|
||||
tosUrl: "URL der Nutzungsbedingungen"
|
||||
thisYear: "Dieses Jahr"
|
||||
thisMonth: "Dieser Monat"
|
||||
@@ -309,8 +311,8 @@ monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Seiten"
|
||||
integration: "Integration"
|
||||
connectSerice: "Verbinden"
|
||||
disconnectSerice: "Trennen"
|
||||
connectService: "Verbinden"
|
||||
disconnectService: "Trennen"
|
||||
enableLocalTimeline: "Lokale Chronik aktivieren"
|
||||
enableGlobalTimeline: "Globale Chronik aktivieren"
|
||||
disablingTimelinesInfo: "Administratoren und Moderatoren haben immer Zugriff auf alle Chroniken, auch wenn diese deaktiviert sind."
|
||||
@@ -545,6 +547,8 @@ disablePlayer: "Video-Player schließen"
|
||||
expandTweet: "Tweet ausklappen"
|
||||
themeEditor: "Farbthemen-Editor"
|
||||
description: "Beschreibung"
|
||||
describeFile: "Beschreibung hinzufügen"
|
||||
enterFileDescription: "Beschreibung eingeben"
|
||||
author: "Autor"
|
||||
leaveConfirm: "Es gibt unspeicherte Änderungen. Möchtest du diese verwerfen?"
|
||||
manage: "Verwaltung"
|
||||
@@ -730,14 +734,16 @@ active: "Aktiv"
|
||||
offline: "Offline"
|
||||
notRecommended: "Nicht empfohlen"
|
||||
botProtection: "Bot-Schutz"
|
||||
instanceBlocking: "Blockierte Instanzen"
|
||||
selectAccount: "Benutzerkonto auswählen"
|
||||
enabled: "Aktiviert"
|
||||
disabled: "Deaktiviert"
|
||||
quickAction: "Schnellaktionen"
|
||||
user: "Benutzer"
|
||||
administration: "Verwaltung"
|
||||
accounts: "Benutzerkonten"
|
||||
switch: "Wechseln"
|
||||
noMaintainerInformationWarning: "Betreiberinformationen sind nicht konfiguriert."
|
||||
noMaintainerInformationWarning: "Administratorinformationen sind nicht konfiguriert."
|
||||
noBotProtectionWarning: "Bot-Schutz ist nicht konfiguriert."
|
||||
configure: "Konfigurieren"
|
||||
postToGallery: "Beitrag zu Galerie hinzufügen"
|
||||
@@ -745,6 +751,22 @@ gallery: "Galerie"
|
||||
recentPosts: "Neue Beiträge"
|
||||
popularPosts: "Beliebte Beiträge"
|
||||
shareWithNote: "Mit Notiz teilen"
|
||||
ads: "Werbung"
|
||||
expiration: "Frist"
|
||||
memo: "Merkzettel"
|
||||
priority: "Priorität"
|
||||
high: "Hoch"
|
||||
middle: "Mittel"
|
||||
low: "Niedrig"
|
||||
emailNotConfiguredWarning: "Keine Email-Adresse hinterlegt"
|
||||
ratio: "Verhältnis"
|
||||
_ad:
|
||||
back: "Zurück"
|
||||
reduceFrequencyOfThisAd: "Diese Werbung weniger anzeigen"
|
||||
_forgotPassword:
|
||||
enterEmail: "Gib die Email-Adresse ein, mit der du dich registriert hast. An diese wird ein Link gesendet, mit der du dein Passwort zurücksetzen kannst."
|
||||
ifNoEmail: "Solltest du bei der Registrierung keine Email-Adresse angegeben haben, wende dich bitte an den Administrator."
|
||||
contactAdmin: "Diese Instanz unterstützt die Verwendung von Email-Adressen nicht. Wende dich, um dein Passwort zurückzusetzen, an den Administrator."
|
||||
_gallery:
|
||||
my: "Meine Galerie"
|
||||
liked: "Beiträge, die mir gefallen"
|
||||
|
||||
+25
-4
@@ -7,6 +7,7 @@ search: "Search"
|
||||
notifications: "Notifications"
|
||||
username: "Username"
|
||||
password: "Password"
|
||||
forgotPassword: "Forgot password"
|
||||
fetchingAsApObject: "Fetching from Fediverse..."
|
||||
ok: "OK"
|
||||
gotIt: "Got it!"
|
||||
@@ -278,6 +279,7 @@ emptyDrive: "The drive is empty"
|
||||
emptyFolder: "This folder is empty"
|
||||
unableToDelete: "Unable to delete"
|
||||
inputNewFileName: "Enter a new filename"
|
||||
inputNewDescription: "Enter new caption"
|
||||
inputNewFolderName: "Enter a new folder name"
|
||||
circularReferenceFolder: "The destination folder is a subfolder of the folder you wish to move."
|
||||
hasChildFilesOrFolders: "Since this folder is not empty, it can not be deleted."
|
||||
@@ -309,8 +311,8 @@ monthX: "{month}"
|
||||
yearX: "{year} /"
|
||||
pages: "Pages"
|
||||
integration: "Integration"
|
||||
connectSerice: "Connect"
|
||||
disconnectSerice: "Disconnect"
|
||||
connectService: "Connect"
|
||||
disconnectService: "Disconnect"
|
||||
enableLocalTimeline: "Enable local timeline"
|
||||
enableGlobalTimeline: "Enable global timeline"
|
||||
disablingTimelinesInfo: "Admins and Mods will always have access to all timelines, even if they are not enabled."
|
||||
@@ -339,7 +341,7 @@ recaptcha: "reCAPTCHA"
|
||||
enableRecaptcha: "Enable reCAPTCHA"
|
||||
recaptchaSiteKey: "Site key"
|
||||
recaptchaSecretKey: "Secret key"
|
||||
avoidMultiCaptchaConfirm: "Using multiple Captchas may cause interference. Would you like to disable the other Captcha? You can leave multiple Captchas enabled by press cancel."
|
||||
avoidMultiCaptchaConfirm: "Using multiple Captchas may cause interferences. Would you like to disable the other Captcha? You can leave multiple Captchas enabled by pressing cancel."
|
||||
antennas: "Antennas"
|
||||
manageAntennas: "Manage Antennas"
|
||||
name: "Name"
|
||||
@@ -545,6 +547,8 @@ disablePlayer: "Close video player"
|
||||
expandTweet: "Expand tweet"
|
||||
themeEditor: "Theme editor"
|
||||
description: "Description"
|
||||
describeFile: "Add caption"
|
||||
enterFileDescription: "Enter caption"
|
||||
author: "Author"
|
||||
leaveConfirm: "There are unsaved changes. Do you want to discard them?"
|
||||
manage: "Management"
|
||||
@@ -730,6 +734,7 @@ active: "Active"
|
||||
offline: "Offline"
|
||||
notRecommended: "Not recommended"
|
||||
botProtection: "Bot Protection"
|
||||
instanceBlocking: "Blocked Instances"
|
||||
selectAccount: "Select account"
|
||||
enabled: "Enabled"
|
||||
disabled: "Disabled"
|
||||
@@ -746,6 +751,22 @@ gallery: "Gallery"
|
||||
recentPosts: "Recent posts"
|
||||
popularPosts: "Popular posts"
|
||||
shareWithNote: "Share with note"
|
||||
ads: "Advertisements"
|
||||
expiration: "Deadline"
|
||||
memo: "Memo"
|
||||
priority: "Priority"
|
||||
high: "High"
|
||||
middle: "Medium"
|
||||
low: "Low"
|
||||
emailNotConfiguredWarning: "Email address not set"
|
||||
ratio: "Ratio"
|
||||
_ad:
|
||||
back: "Back"
|
||||
reduceFrequencyOfThisAd: "Show this ad less"
|
||||
_forgotPassword:
|
||||
enterEmail: "Enter the email address you used to register. A link with which you can reset your password will then be sent to it."
|
||||
ifNoEmail: "If you did not use an email during registration, please contact the administrator instead."
|
||||
contactAdmin: "This instance does not support using email addresses, please contact the administrator to reset your password instead."
|
||||
_gallery:
|
||||
my: "My Gallery"
|
||||
liked: "Liked Posts"
|
||||
@@ -1068,7 +1089,7 @@ _auth:
|
||||
permissionAsk: "This application requires following permissions:"
|
||||
pleaseGoBack: "Please go back to the application"
|
||||
callback: "Returning back to the application"
|
||||
denied: "Access Denied"
|
||||
denied: "Access denied"
|
||||
_antennaSources:
|
||||
all: "All notes"
|
||||
homeTimeline: "Notes from following users"
|
||||
|
||||
+17
-2
@@ -1,5 +1,6 @@
|
||||
---
|
||||
_lang_: "Español"
|
||||
headlineMisskey: "Red conectada por notas"
|
||||
introMisskey: "¡Bienvenido/a! Misskey es un servicio de microblogging descentralizado de código abierto.\nEscribe \"notas\" para compartir lo que te ocurre ahora o para contar sobre ti a todos 📡\nCon la función de \"reacciones\", puedes también añadir una reacción rápida a las notas de todos 👍\nExplora un nuevo mundo 🚀"
|
||||
monthAndDay: "{day}/{month}"
|
||||
search: "Buscar"
|
||||
@@ -137,6 +138,7 @@ flagAsBotDescription: "En caso de que esta cuenta fuera usada por un programa, a
|
||||
flagAsCat: "Esta cuenta es un gato"
|
||||
flagAsCatDescription: "En caso de que declare que esta cuenta es de un gato, active esta opción."
|
||||
autoAcceptFollowed: "Aceptar automáticamente las solicitudes de seguimiento de los usuarios que sigues"
|
||||
addAccount: "Agregar Cuenta"
|
||||
loginFailed: "Error al iniciar sesión."
|
||||
showOnRemote: "Ver en una instancia remota"
|
||||
general: "General"
|
||||
@@ -307,8 +309,6 @@ monthX: "Mes {month}"
|
||||
yearX: "Año {year}"
|
||||
pages: "Páginas"
|
||||
integration: "Integración"
|
||||
connectSerice: "Conectarse"
|
||||
disconnectSerice: "Desconectarse"
|
||||
enableLocalTimeline: "Habilitar linea de tiempo local"
|
||||
enableGlobalTimeline: "Habilitar linea de tiempo global"
|
||||
disablingTimelinesInfo: "Aunque se desactiven estas lineas de tiempo, por conveniencia el administrador y los moderadores pueden seguir usándolos"
|
||||
@@ -435,6 +435,7 @@ signinWith: "Inicie sesión con {x}"
|
||||
signinFailed: "Autenticación fallida. Asegúrate de haber usado el nombre de usuario y contraseña correctos."
|
||||
tapSecurityKey: "Toque la clave de seguridad"
|
||||
or: "O"
|
||||
language: "Idioma"
|
||||
uiLanguage: "Idioma de visualización de la interfaz"
|
||||
groupInvited: "Invitado al grupo"
|
||||
aboutX: "Acerca de {x}"
|
||||
@@ -449,6 +450,7 @@ category: "Categoría"
|
||||
tags: "Etiqueta"
|
||||
docSource: "Fuente de este documento"
|
||||
createAccount: "Crear cuenta"
|
||||
existingAccount: "Cuenta existente"
|
||||
regenerate: "Regenerar"
|
||||
fontSize: "Tamaño de la letra"
|
||||
noFollowRequests: "No hay solicitudes de seguimiento"
|
||||
@@ -563,6 +565,7 @@ pluginTokenRequestedDescription: "Este plugin podrá usar los permisos descritos
|
||||
notificationType: "Tipo de notificación"
|
||||
edit: "Editar"
|
||||
useStarForReactionFallback: "En caso de que los emojis de reacciones no sean claros, usar en su lugar una estrella"
|
||||
emailServer: "Servidor de correo"
|
||||
enableEmail: "Activar el envío de correos electrónicos"
|
||||
emailConfigInfo: "Usar en caso de validación de correo electrónico y pedido de contraseña"
|
||||
email: "Correo"
|
||||
@@ -642,6 +645,14 @@ driveFilesCount: "Cantidad de archivos en el drive"
|
||||
driveUsage: "Uso del drive"
|
||||
noCrawle: "Rechazar indexación del crawler"
|
||||
noCrawleDescription: "Pedir a los motores de búsqueda que no indexen tu perfil, notas, páginas, etc."
|
||||
alwaysMarkSensitive: "Marcar los medios de comunicación como contenido sensible por defecto"
|
||||
verificationEmailSent: "Se le ha enviado un correo electrónico de confirmación. Por favor, acceda al enlace proporcionado en el correo electrónico para completar la configuración."
|
||||
notSet: "Sin especificar"
|
||||
emailVerified: "Su dirección de correo electrónico ha sido verificada."
|
||||
noteFavoritesCount: "Número de notas favoritas"
|
||||
pageLikesCount: "Número de favoritos en la página"
|
||||
pageLikedCount: "Número de favoritos de su página"
|
||||
contact: "Contacto"
|
||||
clips: "Clip"
|
||||
clearCache: "Limpiar caché"
|
||||
backgroundColor: "Fondo"
|
||||
@@ -652,6 +663,10 @@ goBack: "Deseleccionar"
|
||||
info: "Información"
|
||||
user: "Usuarios"
|
||||
administration: "Administrar"
|
||||
expiration: "Termina el"
|
||||
middle: "Mediano"
|
||||
_ad:
|
||||
back: "Deseleccionar"
|
||||
_gallery:
|
||||
unlike: "Quitar me gusta"
|
||||
_email:
|
||||
|
||||
+85
-35
@@ -7,6 +7,7 @@ search: "Rechercher"
|
||||
notifications: "Notifications"
|
||||
username: "Nom d’utilisateur·rice"
|
||||
password: "Mot de passe"
|
||||
forgotPassword: "Mot de passe oublié"
|
||||
fetchingAsApObject: "Récupération depuis le fédiverse …"
|
||||
ok: "OK"
|
||||
gotIt: "J’ai compris !"
|
||||
@@ -309,8 +310,6 @@ monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Pages"
|
||||
integration: "Intégrations"
|
||||
connectSerice: "Connecter"
|
||||
disconnectSerice: "Déconnecter"
|
||||
enableLocalTimeline: "Activer le fil local"
|
||||
enableGlobalTimeline: "Activer le fil global"
|
||||
disablingTimelinesInfo: "Même si vous désactivez ces fils, les administrateur·rice·s et les modérateur·rice·s pourront toujours y accéder."
|
||||
@@ -486,7 +485,7 @@ objectStorageRegionDesc: "Spécifiez une région comme 'xx-east-1'. Si votre ser
|
||||
objectStorageUseSSL: "Utiliser SSL"
|
||||
objectStorageUseSSLDesc: "Désactivez cette option si vous n'utilisez pas HTTPS pour la connexion API"
|
||||
objectStorageUseProxy: "Se connecter via proxy"
|
||||
objectStorageUseProxyDesc: "Désactivez cette option si vous n'utilisez pas Proxy pour la connexion API"
|
||||
objectStorageUseProxyDesc: "Désactivez cette option si vous n'utilisez pas de proxy pour la connexion API"
|
||||
objectStorageSetPublicRead: "Régler sur « public » lors de l'envoi"
|
||||
serverLogs: "Journal du serveur"
|
||||
deleteAll: "Supprimer tout"
|
||||
@@ -600,12 +599,13 @@ useGlobalSettingDesc: "S'il est activé, les paramètres de notification de votr
|
||||
other: "Autre"
|
||||
regenerateLoginToken: "Régénérer le jeton de connexion"
|
||||
regenerateLoginTokenDescription: "Générer un nouveau jeton d'authentification. Cette opération ne devrait pas être nécessaire ; lors de la génération d'un nouveau jeton, tous les appareils seront déconnectés. "
|
||||
setMultipleBySeparatingWithSpace: "Vous pouvez définir plus d’un, séparés par des espaces."
|
||||
setMultipleBySeparatingWithSpace: "Vous pouvez en définir plusieurs, en les séparant par des espaces."
|
||||
fileIdOrUrl: "ID du fichier ou URL"
|
||||
chatOpenBehavior: "Comportement de la fenêtre de discussion lors de son ouverture"
|
||||
behavior: "Comportement"
|
||||
sample: "Exemple"
|
||||
abuseReports: "Signalements"
|
||||
reportAbuse: "Signalements"
|
||||
reportAbuse: "Signaler"
|
||||
reportAbuseOf: "Signaler {name}"
|
||||
fillAbuseReportDescription: "Veuillez expliquer les raisons du signalement. S'il s'agit d'une note précise, veuillez en donner le lien."
|
||||
abuseReported: "Le rapport est envoyé. Merci."
|
||||
@@ -725,9 +725,11 @@ onlineStatus: "Statut"
|
||||
hideOnlineStatus: "Se rendre invisible"
|
||||
hideOnlineStatusDescription: "Rendre votre statut invisible peut diminuer les performances de certaines fonctionnalités, telles que la Recherche."
|
||||
online: "En ligne"
|
||||
active: "Actif·ve"
|
||||
offline: "Hors ligne"
|
||||
notRecommended: "Déconseillé"
|
||||
botProtection: "Protection contre les bots"
|
||||
instanceBlocking: "Instances bloquées"
|
||||
selectAccount: "Sélectionner un compte"
|
||||
enabled: "Activé"
|
||||
disabled: "Désactivé"
|
||||
@@ -744,6 +746,22 @@ gallery: "Galerie"
|
||||
recentPosts: "Les plus récentes"
|
||||
popularPosts: "Les plus consultées"
|
||||
shareWithNote: "Partager dans une note"
|
||||
ads: "Publicité"
|
||||
expiration: "Échéance"
|
||||
memo: "Pense-bête"
|
||||
priority: "Priorité"
|
||||
high: "Haute"
|
||||
middle: "Moyen"
|
||||
low: "Basse"
|
||||
emailNotConfiguredWarning: "Vous n'avez pas configuré d'adresse e-mail."
|
||||
ratio: "Ratio"
|
||||
_ad:
|
||||
back: "Retour"
|
||||
reduceFrequencyOfThisAd: "Voir cette publicité moins souvent"
|
||||
_forgotPassword:
|
||||
enterEmail: "Entrez ici l'adresse e-mail que vous avez enregistrée pour votre compte. Un lien vous permettant de réinitialiser votre mot de passe sera envoyé à cette adresse."
|
||||
ifNoEmail: "Si vous n'avez pas enregistré d'adresse e-mail, merci de contacter l'administrateur·rice de votre instance."
|
||||
contactAdmin: "Cette instance ne permettant pas l'utilisation d'adresses e-mail, prenez contact avec l'administrateur·rice pour procéder à la réinitialisation de votre mot de passe."
|
||||
_gallery:
|
||||
my: "Mes publications"
|
||||
liked: " Publications que j'ai aimées"
|
||||
@@ -759,6 +777,7 @@ _plugin:
|
||||
installWarn: "N’installez que des extensions provenant de sources de confiance."
|
||||
manage: "Gestion des plugins"
|
||||
_registry:
|
||||
scope: "Portée"
|
||||
key: "Clé "
|
||||
keys: "Clé "
|
||||
domain: "Domaine"
|
||||
@@ -792,18 +811,38 @@ _mfm:
|
||||
boldDescription: "Il est possible de mettre le texte en exergue en le mettant en gras."
|
||||
small: "Diminuer l'emphase"
|
||||
smallDescription: "Le contenu peut être affiché en petit et fin."
|
||||
center: "Centrée"
|
||||
center: "Centrer"
|
||||
centerDescription: "Le contenu peut être centré"
|
||||
inlineCode: "Code (inline)"
|
||||
inlineCodeDescription: "Coloration syntaxique des lignes de code."
|
||||
blockCode: "Bloc de code"
|
||||
blockCodeDescription: "Coloration syntaxique des lignes de code pour les blocs multi-lignes."
|
||||
inlineMath: "Formule mathématique (inline)"
|
||||
inlineMathDescription: "Afficher les formules mathématiques (KaTeX)."
|
||||
blockMath: "Formule mathématique (bloc)"
|
||||
blockMathDescription: "Afficher les formules mathématiques (KaTeX) multi-lignes dans un bloc."
|
||||
quote: "Citer"
|
||||
quoteDescription: "Affiche le contenu sous forme de citation."
|
||||
emoji: "Émojis personnalisés"
|
||||
emojiDescription: "Entourez le nom de l'émoji personnalisé de deux points pour l'afficher."
|
||||
search: "Rechercher"
|
||||
searchDescription: "Affiche une boîte de recherche avec du texte pré-saisi."
|
||||
flip: "Inverser"
|
||||
flipDescription: "Rotation verticale ou horizontale du contenu"
|
||||
jelly: "Animation (Gelée)"
|
||||
jellyDescription: "Donne une animation d'étirement."
|
||||
tada: "Animation (Tada)"
|
||||
tadaDescription: "Donne une animation qui donne une impression de \"Tada !\""
|
||||
jump: "Animation (Saut)"
|
||||
jumpDescription: "Donne une animation qui saute."
|
||||
bounce: "Animation (Rebond)"
|
||||
bounceDescription: "Donne une animation de rebondissement."
|
||||
shake: "Animation (Secousse)"
|
||||
shakeDescription: "Donne une animation tremblante."
|
||||
twitch: "Animation (Tremblement)"
|
||||
twitchDescription: "Donne une animation de tremblement intense."
|
||||
spin: "Animation (Rotation)"
|
||||
spinDescription: "Donne une animation de rotation."
|
||||
x2: "Grand"
|
||||
x2Description: "Afficher le contenu en grand."
|
||||
x3: "Très grand"
|
||||
@@ -845,6 +884,7 @@ _reversi:
|
||||
ended: "Fin de partie"
|
||||
playing: "En cours"
|
||||
isLlotheo: "Celui ou celle qui a le moins de pièces gagne (Llotheo)"
|
||||
loopedMap: "Carte en boucle"
|
||||
canPutEverywhere: "Les pions peuvent être placés partout "
|
||||
_instanceTicker:
|
||||
none: "Cacher "
|
||||
@@ -894,17 +934,21 @@ _theme:
|
||||
constant: "Constante"
|
||||
defaultValue: "Valeur par défaut"
|
||||
color: "Couleur"
|
||||
refConst: "Référencez une constante"
|
||||
refProp: "Appeler une propriété"
|
||||
refConst: "Appeler une constante"
|
||||
key: "Clé "
|
||||
func: "Fonction"
|
||||
funcKind: "Type de fonction"
|
||||
argument: "Argument"
|
||||
basedProp: "Nom de la propriété référencée"
|
||||
alpha: "Transparence"
|
||||
darken: "Assombrir"
|
||||
darken: "Sombre"
|
||||
lighten: "Clair"
|
||||
inputConstantName: "Insérez un nom de constante"
|
||||
importInfo: "Vous pouvez importer un thème vers l’éditeur de thèmes en saisissant son code ici."
|
||||
deleteConstantConfirm: "Êtes-vous sûr·e de vouloir supprimer la constante {const} ?"
|
||||
keys:
|
||||
accent: "Accentuation"
|
||||
bg: "Arrière-plan"
|
||||
fg: "Texte"
|
||||
focus: "Mise au point"
|
||||
@@ -922,9 +966,12 @@ _theme:
|
||||
mention: "Mentionner"
|
||||
mentionMe: "Mentions (Moi)"
|
||||
renote: "Partager"
|
||||
modalBg: "Modal d'arrière-plan"
|
||||
divider: "Séparateur"
|
||||
scrollbarHandle: "Poignée de la barre de navigation"
|
||||
scrollbarHandleHover: "Poignée de la barre de navigation (survolée)"
|
||||
dateLabelFg: "Texte de l'étiquette de la date"
|
||||
infoBg: "Arrière-plan pour les informations"
|
||||
infoFg: "Texte d'information"
|
||||
infoWarnBg: "Arrière-plan des avertissements"
|
||||
infoWarnFg: "Texte d’avertissement"
|
||||
@@ -938,15 +985,18 @@ _theme:
|
||||
inputBorder: "Cadre de la zone de texte"
|
||||
listItemHoverBg: "Arrière-plan d'item de liste (survolé)"
|
||||
driveFolderBg: "Arrière-plan du dossier de disque"
|
||||
wallpaperOverlay: "Superposition de fond d'écran"
|
||||
badge: "Badge"
|
||||
messageBg: "Arrière plan de la discussion"
|
||||
accentDarken: "Plus sombre"
|
||||
accentLighten: "Plus clair"
|
||||
fgHighlighted: "Texte mis en évidence"
|
||||
_sfx:
|
||||
note: "Nouvelle note"
|
||||
noteMy: "Ma note"
|
||||
notification: "Notifications"
|
||||
chat: "Discuter"
|
||||
chatBg: "Discuter (De fond)"
|
||||
chatBg: "Discussion (arrière-plan)"
|
||||
antenna: "Réception de l’antenne"
|
||||
channel: "Notifications de canal"
|
||||
reversiPutBlack: "Reversi : les pions noirs ont joué"
|
||||
@@ -991,14 +1041,14 @@ _tutorial:
|
||||
step7_2: "Si vous désirez en savoir plus sur Misskey, jetez un œil sur la section {help}."
|
||||
step7_3: "Bon courage et amusez-vous bien sur Misskey ! 🚀"
|
||||
_2fa:
|
||||
alreadyRegistered: "Cette étape à déjà été complétée"
|
||||
alreadyRegistered: "Configuration déjà achevée."
|
||||
registerDevice: "Ajouter un nouvel appareil"
|
||||
registerKey: "S’inscrire la clé"
|
||||
registerKey: "Enregistrer une clef"
|
||||
step1: "Tout d'abord, installez une application d'authentification, telle que {a} ou {b}, sur votre appareil."
|
||||
step2: "Ensuite, scannez le code QR affiché sur l’écran."
|
||||
step3: "Entrez le jeton affiché sur votre application pour compléter la configuration."
|
||||
step4: "Lorsque vous vous connectez, entrez le jeton de la même manière."
|
||||
securityKeyInfo: "Vous pouvez configurer l'authentification WebAuthN pour sécuriser davantage le processus de connexion avec non seulement la clé de sécurité matérielle qui prend en charge FIDO2, mais également l'authentification par empreinte digitale ou PIN sur votre appareil."
|
||||
step4: "À partir de maintenant, ce même jeton vous sera demandé à chacune de vos connexions."
|
||||
securityKeyInfo: "Vous pouvez configurer l'authentification WebAuthN pour sécuriser davantage le processus de connexion grâce à une clé de sécurité matérielle qui prend en charge FIDO2, ou bien en configurant l'authentification par empreinte digitale ou par code PIN sur votre appareil."
|
||||
_permissions:
|
||||
"read:account": "Afficher les informations du compte"
|
||||
"write:account": "Mettre à jour les informations de votre compte"
|
||||
@@ -1010,8 +1060,8 @@ _permissions:
|
||||
"write:favorites": "Gérer les favoris"
|
||||
"read:following": "Voir les informations de vos abonnements"
|
||||
"write:following": "Abonnements/Se désabonner"
|
||||
"read:messaging": "Cherche à discuter"
|
||||
"write:messaging": "Contrôler le discuter"
|
||||
"read:messaging": "Voir vos discussions"
|
||||
"write:messaging": "Gérer les discussions"
|
||||
"read:mutes": "Voir les comptes masqués"
|
||||
"write:mutes": "Gérer les comptes masqués"
|
||||
"write:notes": "Créer / supprimer des notes"
|
||||
@@ -1020,10 +1070,10 @@ _permissions:
|
||||
"read:reactions": "Lire les réactions"
|
||||
"write:reactions": "Gérer vos réactions"
|
||||
"write:votes": "Voter"
|
||||
"read:pages": "Afficher la page"
|
||||
"write:pages": "Mettre à jour les Pages"
|
||||
"read:page-likes": "Voir les favoris sur les Pages"
|
||||
"write:page-likes": "Mettre à jour les favoris sur les Pages"
|
||||
"read:pages": "Voir vos pages"
|
||||
"write:pages": "Gérer les pages"
|
||||
"read:page-likes": "Voir les mentions « J'aime » des pages"
|
||||
"write:page-likes": "Gérer les mentions « J'aime » sur les pages"
|
||||
"read:user-groups": "Voir les groupes d'utilisateur·rice·s"
|
||||
"write:user-groups": "Éditer les groupes des utilisateur·rice·s"
|
||||
"read:channels": "Lire les canaux"
|
||||
@@ -1136,8 +1186,8 @@ _exportOrImport:
|
||||
blockingList: "Comptes bloqués"
|
||||
userLists: "Listes"
|
||||
_charts:
|
||||
federationInstancesIncDec: "Variation du nombre des instances fédérées"
|
||||
federationInstancesTotal: "Nombre total des instances fédérées"
|
||||
federationInstancesIncDec: "Variation du nombre d'instances fédérées"
|
||||
federationInstancesTotal: "Nombre total d'instances fédérées"
|
||||
usersIncDec: "Variation du nombre d'utilisateur·rice·s"
|
||||
usersTotal: "Nombre des utilisateur·rice·s au total"
|
||||
activeUsers: "Utilisateur·rice·s actif·ve·s"
|
||||
@@ -1152,15 +1202,15 @@ _charts:
|
||||
_instanceCharts:
|
||||
requests: "Requêtes"
|
||||
users: "Variation du nombre d'utilisateur·rice·s"
|
||||
usersTotal: "Nombre d'utilisateur·rice·s au total cumulé"
|
||||
notes: "Variation du nombre des notes"
|
||||
usersTotal: "Total cumulé du nombre d'utilisateur·rice·s"
|
||||
notes: "Variation du nombre de notes"
|
||||
notesTotal: "Nombre total cumulé des notes"
|
||||
ff: "Variation des abonné·e·s"
|
||||
ffTotal: "Nombre d'abonné·e·s au total cumulé"
|
||||
ff: "Variation des abonné·e·s / abonnements"
|
||||
ffTotal: "Total cumulé du nombre d'abonné·e·s / abonnements"
|
||||
cacheSize: "Variation de la taille du cache"
|
||||
cacheSizeTotal: "La taille du cache au total cumulé"
|
||||
cacheSizeTotal: "Total cumulé de la taille du cache"
|
||||
files: "Variation du nombre de fichiers"
|
||||
filesTotal: "Nombre de fichiers au total cumulé"
|
||||
filesTotal: "Total cumulé du nombre de fichiers"
|
||||
_timelines:
|
||||
home: "Principal"
|
||||
local: "Local"
|
||||
@@ -1183,7 +1233,7 @@ _rooms:
|
||||
default: "Par défaut"
|
||||
washitsu: "Style japonnais"
|
||||
_furnitures:
|
||||
milk: "Lait en carton"
|
||||
milk: "Brique de lait"
|
||||
bed: "Lit"
|
||||
low-table: "Table basse"
|
||||
desk: "Bureau"
|
||||
@@ -1202,7 +1252,7 @@ _rooms:
|
||||
book: "Livre"
|
||||
book2: "Livre 2"
|
||||
piano: "Piano"
|
||||
facial-tissue: "Mouchoirs en papier"
|
||||
facial-tissue: "Boîte de mouchoirs"
|
||||
server: "Serveurs"
|
||||
moon: "Lune"
|
||||
corkboard: "Tableau en liège"
|
||||
@@ -1215,7 +1265,7 @@ _rooms:
|
||||
wall-clock: "Horloge murale"
|
||||
photoframe: "Cadre photo"
|
||||
cube: "Cube"
|
||||
tv: "Téléviseur"
|
||||
tv: "Télé"
|
||||
pinguin: "Pingouin"
|
||||
rubik-cube: "Cube de Rubik"
|
||||
poster-h: "Affiche (horizontale)"
|
||||
@@ -1237,7 +1287,7 @@ _pages:
|
||||
deleted: "La page a été supprimée"
|
||||
pageSetting: "Paramètres de la Page"
|
||||
nameAlreadyExists: "L'URL de page spécifiée existe déjà"
|
||||
invalidNameTitle: "La URL de la page spécifiée n’est pas valide"
|
||||
invalidNameTitle: "L'URL de page spécifiée n’est pas valide"
|
||||
invalidNameText: "Assurez-vous qu’il n’est pas vide"
|
||||
editThisPage: "Éditer cette page"
|
||||
viewSource: "Afficher la source"
|
||||
@@ -1259,14 +1309,14 @@ _pages:
|
||||
font: "Police de caractères"
|
||||
fontSerif: "Serif"
|
||||
fontSansSerif: "Sans Serif"
|
||||
eyeCatchingImageSet: "Définir une image attirante"
|
||||
eyeCatchingImageRemove: "Supprimer une image attirante"
|
||||
eyeCatchingImageSet: "Définir une image attractive"
|
||||
eyeCatchingImageRemove: "Supprimer l'image attractive"
|
||||
chooseBlock: "Ajouter un bloc"
|
||||
selectType: "Choisir un type"
|
||||
enterVariableName: "Veuillez entrer un nom pour votre variable"
|
||||
variableNameIsAlreadyUsed: "Cette variable est déjà utilisée"
|
||||
variableNameIsAlreadyUsed: "Ce nom de variable est déjà utilisé"
|
||||
contentBlocks: "Contenu"
|
||||
inputBlocks: "Entrée"
|
||||
inputBlocks: "Blocs d'entrée"
|
||||
specialBlocks: "Spécial"
|
||||
blocks:
|
||||
text: "Texte"
|
||||
|
||||
+1376
-12
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,7 @@ const languages = [
|
||||
'en-US',
|
||||
'es-ES',
|
||||
'fr-FR',
|
||||
'id-ID',
|
||||
'ja-JP',
|
||||
'ja-KS',
|
||||
'kab-KAB',
|
||||
|
||||
+169
-14
@@ -7,6 +7,7 @@ search: "Cerca"
|
||||
notifications: "Notifiche"
|
||||
username: "Nome utente"
|
||||
password: "Password"
|
||||
forgotPassword: "Hai dimenticato la tua password?"
|
||||
fetchingAsApObject: "Recuperando dal Fediverso..."
|
||||
ok: "OK"
|
||||
gotIt: "Capito!"
|
||||
@@ -153,6 +154,9 @@ recipient: "Destinatario"
|
||||
annotation: "Descrizione"
|
||||
federation: "Federazione"
|
||||
instances: "Istanza"
|
||||
latestRequestSentAt: "Ultima richiesta inviata"
|
||||
latestRequestReceivedAt: "Ultima richiesta ricevuta"
|
||||
latestStatus: "Ultimo stato"
|
||||
storageUsage: "Volume di dischi"
|
||||
charts: "Grafici"
|
||||
perHour: "All'ora"
|
||||
@@ -172,6 +176,7 @@ instanceInfo: "Informazioni sull'istanza"
|
||||
statistics: "Statistiche"
|
||||
clearQueue: "Svuota coda"
|
||||
clearQueueConfirmTitle: "Vuoi davvero svuotare la coda?"
|
||||
clearQueueConfirmText: "Le note ancora non distribuite non verranno rilasciate. Solitamente, non è necessario eseguire questa operazione."
|
||||
clearCachedFiles: "Svuota cache"
|
||||
clearCachedFilesConfirm: "Vuoi davvero svuotare la cache da tutti i file remoti?"
|
||||
blockedInstances: "Istanze bloccate"
|
||||
@@ -300,8 +305,6 @@ monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Pagine"
|
||||
integration: "App collegate"
|
||||
connectSerice: "Connetti"
|
||||
disconnectSerice: "Disconnetti"
|
||||
enableLocalTimeline: "Abilita Timeline locale"
|
||||
enableGlobalTimeline: "Abilita Timeline federata"
|
||||
disablingTimelinesInfo: "Anche se disabiliti queste timeline, gli amministratori e i moderatori potranno sempre accederci."
|
||||
@@ -329,6 +332,7 @@ recaptcha: "reCAPTCHA"
|
||||
enableRecaptcha: "Abilita reCAPTCHA"
|
||||
recaptchaSiteKey: "Chiave del sito"
|
||||
recaptchaSecretKey: "Chiave segreta"
|
||||
avoidMultiCaptchaConfirm: "Utilizzare diversi Captcha può causare interferenze. Vuoi disattivare l'altro Captcha? Puoi lasciare diversi Captcha attivi premendo \"Cancella\"."
|
||||
antennas: "Antenne"
|
||||
manageAntennas: "Gestore delle antenne"
|
||||
name: "Nome"
|
||||
@@ -468,6 +472,9 @@ objectStoragePrefixDesc: "I file saranno conservati sotto la directory di questo
|
||||
objectStorageEndpoint: "Endpoint"
|
||||
objectStorageRegion: "Region"
|
||||
objectStorageUseSSL: "Usare SSL"
|
||||
objectStorageUseProxy: "Usa proxy"
|
||||
objectStorageUseProxyDesc: "Disabilita quest'opzione se non usi proxy per la connessione API."
|
||||
objectStorageSetPublicRead: "Imposta \"visibilità pubblica\" al momento di caricare"
|
||||
serverLogs: "Log del server"
|
||||
deleteAll: "Cancella cronologia"
|
||||
showFixedPostForm: "Visualizzare la finestra di pubblicazione in cima alla timeline"
|
||||
@@ -497,7 +504,7 @@ scratchpad: "ScratchPad"
|
||||
output: "Uscita"
|
||||
script: "Script"
|
||||
disablePagesScript: "Disabilita AiScript nelle pagine"
|
||||
updateRemoteUser: "Aggiornare le informazioni di utente remoto"
|
||||
updateRemoteUser: "Aggiornare le informazioni di utente remot@"
|
||||
deleteAllFiles: "Elimina tutti i file"
|
||||
deleteAllFilesConfirm: "Vuoi davvero eliminare tutti i file?"
|
||||
removeAllFollowing: "Cancella tutti i follows"
|
||||
@@ -508,7 +515,10 @@ sidebar: "Barra laterale"
|
||||
divider: "Linea di separazione"
|
||||
addItem: "Aggiungi elemento"
|
||||
rooms: "Camera"
|
||||
relays: "Ripetitori"
|
||||
addRelay: "Aggiungi ripetitore"
|
||||
inboxUrl: "Inbox URL"
|
||||
addedRelays: "Ripetitori configurati"
|
||||
serviceworkerInfo: "Deve essere abilitato per le notifiche push. "
|
||||
deletedNote: "Nota eliminata"
|
||||
invisibleNote: "Nota invisibile"
|
||||
@@ -533,9 +543,12 @@ height: "Altezza"
|
||||
large: "Grande"
|
||||
medium: "Predefinito"
|
||||
small: "Piccolo"
|
||||
generateAccessToken: "Genera token di accesso"
|
||||
permission: "Autorizzazioni "
|
||||
enableAll: "Abilita tutto"
|
||||
disableAll: "Disabilita tutto"
|
||||
tokenRequested: "Autorizza accesso all'account"
|
||||
pluginTokenRequestedDescription: "Il plugin potrà utilizzare le autorizzazioni impostate qui."
|
||||
notificationType: "Tipo di notifiche"
|
||||
edit: "Modifica"
|
||||
useStarForReactionFallback: "Se è sconosciuto l'emoji di reazione, usare la ★ come alternativa."
|
||||
@@ -570,12 +583,18 @@ notificationSettingDesc: "Seleziona il tipo di notifiche da visualizzare."
|
||||
useGlobalSetting: "Usa impostazioni generali"
|
||||
useGlobalSettingDesc: "Se abilitato, le impostazioni notifiche dell'account verranno utilizzate. Se disabilitato, si possono definire diverse singole impostazioni."
|
||||
other: "Avanzate"
|
||||
regenerateLoginToken: "Genera di nuovo un token di connessione"
|
||||
regenerateLoginTokenDescription: "Genera un nuovo token di autenticazione. Solitamente questa operazione non è necessaria: quando si genera un nuovo token, tutti i dispositivi vanno disconnessi."
|
||||
fileIdOrUrl: "ID o URL del file"
|
||||
chatOpenBehavior: "Comportamento della finestra di chat quando viene aperta"
|
||||
behavior: "Comportamento"
|
||||
abuseReports: "Segnala"
|
||||
reportAbuse: "Segnala"
|
||||
abuseReports: "Segnalazioni"
|
||||
reportAbuse: "Segnalazioni"
|
||||
reportAbuseOf: "Segnala {name}"
|
||||
fillAbuseReportDescription: "Si prega di spiegare il motivo della segnalazione. Se riguarda una nota precisa, si prega di collegare anche l'URL della nota."
|
||||
abuseReported: "La segnalazione è stata inviata. Grazie."
|
||||
send: "Inviare"
|
||||
abuseMarkAsResolved: "Contrassegna la segnalazione come risolta"
|
||||
openInNewTab: "Apri in una nuova scheda"
|
||||
openInSideView: "Apri in vista laterale"
|
||||
defaultNavigationBehaviour: "Navigazione preimpostata"
|
||||
@@ -592,6 +611,7 @@ optional: "Opzionale"
|
||||
createNewClip: "Nuova clip"
|
||||
public: "Pubblica"
|
||||
i18nInfo: "Misskey è tradotto in diverse lingue da volontari. Anche tu puoi contribuire su {link}."
|
||||
manageAccessTokens: "Gestisci token di accesso"
|
||||
accountInfo: "Informazioni account"
|
||||
notesCount: "Conteggio note"
|
||||
repliesCount: "Numero di risposte inviate"
|
||||
@@ -608,7 +628,12 @@ yes: "Sì"
|
||||
no: "No"
|
||||
driveFilesCount: "Numero di file nel Drive"
|
||||
driveUsage: "Utilizzazione del Drive"
|
||||
noCrawle: "Rifiuta l'indicizzazione dai robot."
|
||||
noCrawleDescription: "Richiedi che i motori di ricerca non indicizzino la tua pagina di profilo, le tue note, pagine, ecc."
|
||||
lockedAccountInfo: "A meno che non imposti la visibilità delle tue note su \"Solo ai follower\", le tue note sono visibili da tutti, anche se hai configurato l'account per confermare manualmente le richieste di follow."
|
||||
alwaysMarkSensitive: "Segnare i media come sensibili per impostazione predefinita"
|
||||
loadRawImages: "Visualizza le intere immagini allegate invece delle miniature."
|
||||
disableShowingAnimatedImages: "Disabilita le immagini animate"
|
||||
verificationEmailSent: "Una mail di verifica è stata inviata. Si prega di accedere al collegamento per compiere la verifica."
|
||||
notSet: "Non impostato"
|
||||
emailVerified: "Il tuo indirizzo email è stato verificato"
|
||||
@@ -628,6 +653,7 @@ duplicate: "Duplica"
|
||||
left: "Sinistra"
|
||||
center: "Centro"
|
||||
wide: "Largo"
|
||||
reloadToApplySetting: "Le tue preferenze verranno impostate dopo il ricaricamento della pagina. Vuoi ricaricare adesso?"
|
||||
showTitlebar: "Visualizza la barra del titolo"
|
||||
clearCache: "Svuota cache"
|
||||
onlineUsersCount: "{n} utenti online"
|
||||
@@ -644,6 +670,7 @@ createdAt: "Data di creazione"
|
||||
updatedAt: "Aggiornato il"
|
||||
saveConfirm: "Vuoi salvare le modifiche?"
|
||||
deleteConfirm: "Rimuovere?"
|
||||
invalidValue: "Questo non è un valore valido."
|
||||
registry: "Registro"
|
||||
closeAccount: "Disattiva account"
|
||||
currentVersion: "Versione attuale"
|
||||
@@ -652,8 +679,10 @@ youAreRunningUpToDateClient: "Stai usando la versione più recente del client."
|
||||
newVersionOfClientAvailable: "Una nuova versione del tuo client è disponibile."
|
||||
usageAmount: "In utilizzo"
|
||||
capacity: "Capacità"
|
||||
inUse: "In utilizzo"
|
||||
editCode: "Modifica codice"
|
||||
apply: "Applica"
|
||||
receiveAnnouncementFromInstance: "Ricevi i messaggi informativi dall'istanza"
|
||||
emailNotification: "Eventi per notifiche via mail"
|
||||
publish: "Pubblico"
|
||||
inChannelSearch: "Cerca in canale"
|
||||
@@ -677,9 +706,11 @@ onlineStatus: "Stato di connessione"
|
||||
hideOnlineStatus: "Stato invisibile"
|
||||
hideOnlineStatusDescription: "Abilitare l'opzione di stato invisibile può guastare la praticità di singole funzioni, come la ricerca."
|
||||
online: "Online"
|
||||
active: "Attiv@"
|
||||
offline: "Offline"
|
||||
notRecommended: "Sconsigliato"
|
||||
botProtection: "Protezione contro i bot"
|
||||
instanceBlocking: "Istanze bloccate"
|
||||
selectAccount: "Scegli account"
|
||||
enabled: "Attivo"
|
||||
disabled: "Inattivo"
|
||||
@@ -696,6 +727,22 @@ gallery: "Galleria"
|
||||
recentPosts: "Le più recenti"
|
||||
popularPosts: "Le più visualizzate"
|
||||
shareWithNote: "Condividere in nota"
|
||||
ads: "Pubblicità"
|
||||
expiration: "Scadenza"
|
||||
memo: "Promemoria"
|
||||
priority: "Priorità"
|
||||
high: "Alta"
|
||||
middle: "Media"
|
||||
low: "Bassa"
|
||||
emailNotConfiguredWarning: "Non hai impostato nessun indirizzo e-mail."
|
||||
ratio: "Rapporto"
|
||||
_ad:
|
||||
back: "Indietro"
|
||||
reduceFrequencyOfThisAd: "Visualizza questa pubblicità meno spesso"
|
||||
_forgotPassword:
|
||||
enterEmail: "Inserisci l'indirizzo di posta elettronica che hai registrato nel tuo profilo. Il collegamento necessario per ripristinare la password verrà inviato a questo indirizzo."
|
||||
ifNoEmail: "Se nessun indirizzo e-mail è stato registrato, si prega di contattare l'amministratore·trice dell'istanza."
|
||||
contactAdmin: "Poiché questa istanza non permette l'utilizzo di una mail, si prega di contattare l'amministratore·trice dell'istanza per poter ripristinare la password."
|
||||
_gallery:
|
||||
my: "Le mie pubblicazioni"
|
||||
liked: "Pubblicazioni che mi piacciono"
|
||||
@@ -730,6 +777,7 @@ _nsfw:
|
||||
force: "Nascondere tutti i media"
|
||||
_mfm:
|
||||
cheatSheet: "Bigliettino MFM"
|
||||
intro: "MFM è un linguaggio Markdown particolare che si può usare in diverse parti di Misskey. Qui puoi visualizzare a colpo d'occhio tutta la sintassi MFM utile."
|
||||
dummy: "Il Fediverso si espande con Misskey"
|
||||
mention: "Menzioni"
|
||||
mentionDescription: "Si può menzionare un utente specifico digitando il suo nome utente subito dopo il segno @."
|
||||
@@ -802,11 +850,15 @@ _theme:
|
||||
constant: "Costante"
|
||||
defaultValue: "Valore predefinito"
|
||||
color: "Colore"
|
||||
refConst: "Chiama costante"
|
||||
key: "Chiave"
|
||||
func: "Funzione"
|
||||
funcKind: "Tipo di funzione"
|
||||
argument: "Argomento"
|
||||
darken: "Scuro"
|
||||
lighten: "Chiaro"
|
||||
inputConstantName: "Inserisci un nome per la costante"
|
||||
deleteConstantConfirm: "Vuoi davvero eliminare la costante {const}?"
|
||||
keys:
|
||||
bg: "Sfondo"
|
||||
fg: "Testo"
|
||||
@@ -823,8 +875,10 @@ _theme:
|
||||
link: "Link"
|
||||
hashtag: "Hashtag"
|
||||
mention: "Menzioni"
|
||||
mentionMe: "Menzioni (di me)"
|
||||
renote: "Rinota"
|
||||
divider: "Interruzione di linea"
|
||||
infoBg: "Sfondo informazioni"
|
||||
infoFg: "Testo di informazioni"
|
||||
infoWarnBg: "Sfondo degli avvisi"
|
||||
infoWarnFg: "Testo di avviso"
|
||||
@@ -838,11 +892,13 @@ _theme:
|
||||
inputBorder: "Inquadra casella di testo"
|
||||
listItemHoverBg: "Sfondo della voce di elenco (sorvolato)"
|
||||
driveFolderBg: "Sfondo della cartella di disco"
|
||||
messageBg: "Sfondo della chat"
|
||||
_sfx:
|
||||
note: "Nota"
|
||||
noteMy: "Mia nota"
|
||||
notification: "Notifiche"
|
||||
chat: "Messaggi"
|
||||
chatBg: "Chat (sfondo)"
|
||||
antenna: "Ricezione dell'antenna"
|
||||
channel: "Notifiche di canale"
|
||||
_ago:
|
||||
@@ -887,12 +943,18 @@ _tutorial:
|
||||
_2fa:
|
||||
registerDevice: "Aggiungi dispositivo"
|
||||
_permissions:
|
||||
"read:account": "Visualizzare le informazioni dell'account"
|
||||
"write:account": "Modificare le informazioni dell'account"
|
||||
"read:blocks": "Visualizza gli account bloccati"
|
||||
"write:blocks": "Gestisci gli account bloccati"
|
||||
"read:drive": "Aprire il Drive"
|
||||
"write:drive": "Gestire il Drive"
|
||||
"read:favorites": "Visualizza i tuoi preferiti"
|
||||
"write:favorites": "Gestisci i tuoi preferiti"
|
||||
"read:following": "Vedi le informazioni di follow"
|
||||
"write:following": "Seguiti/ Smetti di seguire"
|
||||
"read:messaging": "Visualizzare la chat"
|
||||
"write:messaging": "Gestire la chat"
|
||||
"read:mutes": "Vedi account silenziati"
|
||||
"write:mutes": "Gerisci account silenziati"
|
||||
"write:notes": "Creare / Eliminare note"
|
||||
@@ -900,12 +962,22 @@ _permissions:
|
||||
"write:notifications": "Gerisci notifiche"
|
||||
"read:reactions": "Vedi reazioni"
|
||||
"write:reactions": "Gerisci reazioni"
|
||||
"write:votes": "Votare"
|
||||
"read:pages": "Visualizzare pagine"
|
||||
"write:pages": "Gestire pagine"
|
||||
"read:page-likes": "Visualizzare i \"Mi piace\" di pagine"
|
||||
"write:page-likes": "Gestire i \"Mi piace\" di pagine"
|
||||
"read:user-groups": "Vedi gruppi di utenti"
|
||||
"write:user-groups": "Gestisci gruppi di utenti"
|
||||
"read:channels": "Visualizza canali"
|
||||
"write:channels": "Gerisci canali"
|
||||
_auth:
|
||||
shareAccess: "Autorizzare「{name}」ad accedere al tuo account?"
|
||||
shareAccessAsk: "Vuoi davvero consentire l'accesso al tuo account a questa app'?"
|
||||
permissionAsk: "Questa app richiede le seguenti autorizzazioni:"
|
||||
pleaseGoBack: "Si prega di ritornare sulla app"
|
||||
callback: "Ritornando sulla app"
|
||||
denied: "Accesso negato"
|
||||
_antennaSources:
|
||||
all: "Tutte le note"
|
||||
homeTimeline: "Note dagli utenti che segui"
|
||||
@@ -932,22 +1004,40 @@ _widgets:
|
||||
photos: "Foto"
|
||||
digitalClock: "Orologio digitale"
|
||||
federation: "Federazione"
|
||||
postForm: "Finestra di pubblicazione"
|
||||
slideshow: "Diapositive"
|
||||
button: "Pulsante"
|
||||
onlineUsers: "Utenti online"
|
||||
jobQueue: "Coda di lavoro"
|
||||
serverMetric: "Statistiche server"
|
||||
aiscript: "Console AiScript"
|
||||
_cw:
|
||||
hide: "Nascondere"
|
||||
show: "Mostra di più"
|
||||
chars: "{count} caratteri"
|
||||
files: "{count} file"
|
||||
_poll:
|
||||
noOnlyOneChoice: "Sono necessarie almeno 2 risposte"
|
||||
choiceN: "Opzione {n}"
|
||||
noMore: "Hai aggiunto il numero massimo di opzioni."
|
||||
canMultipleVote: "Risposte multiple"
|
||||
canMultipleVote: "Possibilità di risposte multiple"
|
||||
expiration: "Scadenza"
|
||||
infinite: "Permanente"
|
||||
infinite: "Non scade"
|
||||
at: "Seleziona data"
|
||||
after: "Seleziona durata"
|
||||
deadlineDate: "Data di scadenza"
|
||||
deadlineTime: "h"
|
||||
voted: "Votato"
|
||||
deadlineTime: "Ora di scadenza"
|
||||
duration: "Durata"
|
||||
votesCount: "{n} voti"
|
||||
totalVotes: "Totale di {n} voti"
|
||||
vote: "Vota"
|
||||
showResult: "Visualizza risultati"
|
||||
voted: "Hai votato"
|
||||
closed: "Terminato"
|
||||
remainingDays: "Rimangono {d} giorni e {h} ore"
|
||||
remainingHours: "Rimangono {h} ore e {m} minuti"
|
||||
remainingMinutes: "Rimangono {m} minuti e {s} secondi"
|
||||
remainingSeconds: "Rimangono {s} secondi"
|
||||
_visibility:
|
||||
public: "Pubblica"
|
||||
publicDescription: "Visibile per tutti sul Fediverso"
|
||||
@@ -975,7 +1065,7 @@ _profile:
|
||||
username: "Nome utente"
|
||||
description: "Bio"
|
||||
youCanIncludeHashtags: "Puoi anche includere hashtag."
|
||||
metadata: "Metadati"
|
||||
metadata: "Informazioni aggiuntive"
|
||||
metadataEdit: "Modifica informazioni aggiuntive"
|
||||
metadataDescription: "Puoi pubblicare fino a quattro informazioni aggiuntive sul profilo."
|
||||
metadataLabel: "Etichetta"
|
||||
@@ -1001,10 +1091,19 @@ _charts:
|
||||
filesIncDec: "Variazione del numero dei file"
|
||||
filesTotal: "Numero totale di file"
|
||||
storageUsageIncDec: "Variazione dell'utilizzo dell'immagazzinamento"
|
||||
storageUsageTotal: "Utilizzo totale dell'immagazzinamento"
|
||||
_instanceCharts:
|
||||
requests: "Richieste"
|
||||
users: "Variazione del numero di utenti"
|
||||
usersTotal: "Totale cumulativo di utenti"
|
||||
notes: "Variazione del numero di note"
|
||||
notesTotal: "Totale cumulato di note"
|
||||
ff: "Variazione dei follow/ follower"
|
||||
ffTotal: "Totale cumulato dei follow/ follower"
|
||||
cacheSize: "Variazione dello spazio occupato dalla cache"
|
||||
cacheSizeTotal: "Totale cumulato dello spazio occupato dalla cache"
|
||||
files: "Variazione del numero di file"
|
||||
filesTotal: "Totale cumulato del numero di file"
|
||||
_timelines:
|
||||
home: "Home"
|
||||
local: "Locale"
|
||||
@@ -1012,20 +1111,29 @@ _timelines:
|
||||
global: "Federata"
|
||||
_rooms:
|
||||
roomOf: "Camera di {user}"
|
||||
addFurniture: "Disponi mobilia"
|
||||
translate: "Sposta"
|
||||
rotate: "Ruota"
|
||||
exit: "Indietro"
|
||||
remove: "Togli"
|
||||
clear: "Rimuovi tutto"
|
||||
clearConfirm: "Sei sicur@ di voler rimuovere tutti i mobili dalla tua camera?"
|
||||
leaveConfirm: "Hai fatto modifiche ancora non salvate. Vuoi davvero uscire?"
|
||||
chooseImage: "Seleziona immagine"
|
||||
roomType: "Tipo di stanza"
|
||||
carpetColor: "Colore del suolo"
|
||||
_roomType:
|
||||
default: "Predefinito"
|
||||
washitsu: "Washitsu"
|
||||
_furnitures:
|
||||
milk: "Cartone del latte"
|
||||
bed: "Letto"
|
||||
low-table: "Tavolino Coffee"
|
||||
low-table: "Tavolino"
|
||||
desk: "Tavolo"
|
||||
chair: "Sedia"
|
||||
chair2: "Sedia 2"
|
||||
fan: "Ventilatore"
|
||||
pc: "PC"
|
||||
pc: "Computer"
|
||||
plant: "Pianta da appartamento"
|
||||
plant2: "Pianta da appartamento2"
|
||||
eraser: "Gomma"
|
||||
@@ -1037,21 +1145,32 @@ _rooms:
|
||||
book: "Libro"
|
||||
book2: "Libro2"
|
||||
piano: "Pianoforte"
|
||||
facial-tissue: "Scatola di fazzolettini"
|
||||
server: "Server"
|
||||
moon: "Luna"
|
||||
corkboard: "Bacheca"
|
||||
mousepad: "Tappetino per il mouse"
|
||||
monitor: "Monitor "
|
||||
keyboard: "Tastiera"
|
||||
carpet-stripe: "Tappeto (a strisce)"
|
||||
mat: "Zerbino"
|
||||
color-box: "Libreria"
|
||||
wall-clock: "Orologio da parete"
|
||||
photoframe: "Cornice"
|
||||
cube: "Cubo"
|
||||
tv: "Televisore"
|
||||
tv: "TV"
|
||||
pinguin: "Pinguino"
|
||||
rubik-cube: "Cubo di Rubik"
|
||||
poster-h: "Poster (orizzontale)"
|
||||
poster-v: "Poster (verticale)"
|
||||
sofa: "Divano"
|
||||
spiral: "Scale a chiocciola"
|
||||
bin: "Cestino"
|
||||
cup-noodle: "Noodle istantanei"
|
||||
holo-display: "Visualizzazione olografica"
|
||||
energy-drink: "Bevanda energetica"
|
||||
doll-ai: "Bambola Ai"
|
||||
banknote: "Mazzetta di banconote"
|
||||
_pages:
|
||||
newPage: "Crea pagina"
|
||||
editPage: "Modifica pagina"
|
||||
@@ -1060,6 +1179,9 @@ _pages:
|
||||
updated: "Pagina aggiornata con successo!"
|
||||
deleted: "Pagina eliminata"
|
||||
pageSetting: "Impostazioni pagina"
|
||||
nameAlreadyExists: "Esiste già una pagina con lo stesso URL."
|
||||
invalidNameTitle: "L'URL di pagina definito non è valido"
|
||||
invalidNameText: "Verifica che il campo non è vuoto"
|
||||
editThisPage: "Modifica questa pagina"
|
||||
viewSource: "Visualizza sorgente"
|
||||
viewPage: "Visualizza pagina"
|
||||
@@ -1072,11 +1194,21 @@ _pages:
|
||||
content: "Blocco di pagina"
|
||||
variables: "Variabili"
|
||||
title: "Titolo"
|
||||
url: "URL della pagina"
|
||||
summary: "Riassunto di pagina"
|
||||
hideTitleWhenPinned: "Nascondere il titolo pagina quando è fissata in cima al profilo."
|
||||
font: "Tipo di carattere"
|
||||
fontSerif: "Serif"
|
||||
fontSansSerif: "Sans serif"
|
||||
eyeCatchingImageSet: "Imposta un'immagine attrattiva"
|
||||
eyeCatchingImageRemove: "Elimina l'immagine attrattiva"
|
||||
chooseBlock: "Aggiungi blocco"
|
||||
selectType: "Seleziona tipo"
|
||||
enterVariableName: "Digita un nome di variabile"
|
||||
variableNameIsAlreadyUsed: "Esiste già una variabile con lo stesso nome"
|
||||
contentBlocks: "Contenuto"
|
||||
inputBlocks: "Blocchi di input"
|
||||
specialBlocks: "Speciale"
|
||||
blocks:
|
||||
text: "Testo"
|
||||
textarea: "Area di testo"
|
||||
@@ -1086,16 +1218,20 @@ _pages:
|
||||
if: "Se"
|
||||
_if:
|
||||
variable: "Variabili"
|
||||
post: "Finestra di pubblicazione"
|
||||
_post:
|
||||
text: "Contenuto"
|
||||
textInput: "Immissione testo"
|
||||
_textInput:
|
||||
name: "Nome della variabile"
|
||||
text: "Titolo"
|
||||
default: "Valore predefinito"
|
||||
textareaInput: "Immissione testo a più righe"
|
||||
_textareaInput:
|
||||
name: "Nome della variabile"
|
||||
text: "Titolo"
|
||||
default: "Valore predefinito"
|
||||
numberInput: "Immissione numerica"
|
||||
_numberInput:
|
||||
name: "Nome della variabile"
|
||||
text: "Titolo"
|
||||
@@ -1108,24 +1244,35 @@ _pages:
|
||||
id: "ID nota"
|
||||
idDescription: "Qui puoi anche incollare l'URL della nota che vuoi impostare."
|
||||
detailed: "Visualizzazione dettagliata"
|
||||
switch: "Interruttore"
|
||||
_switch:
|
||||
name: "Nome della variabile"
|
||||
text: "Titolo"
|
||||
default: "Valore predefinito"
|
||||
counter: "Contatore"
|
||||
_counter:
|
||||
name: "Nome della variabile"
|
||||
text: "Titolo"
|
||||
inc: "Valore da aggiungere"
|
||||
_button:
|
||||
text: "Titolo"
|
||||
colored: "Colorato"
|
||||
action: "Operazione da eseguire quando viene premuto il pulsante"
|
||||
_action:
|
||||
dialog: "Visualizzare una finestra di dialogo"
|
||||
_dialog:
|
||||
content: "Contenuto"
|
||||
resetRandom: "Ripristinare un numero aleatorio"
|
||||
pushEvent: "Inviare evento"
|
||||
_pushEvent:
|
||||
event: "Nome evento"
|
||||
message: "Messaggio da visualizzare quando abilitato"
|
||||
variable: "Variabile da inviare"
|
||||
no-variable: "Nessun contenuto"
|
||||
callAiScript: "Chiamare AiScript"
|
||||
_callAiScript:
|
||||
functionName: "Nome della funzione"
|
||||
radioButton: "Opzioni"
|
||||
_radioButton:
|
||||
name: "Nome della variabile"
|
||||
title: "Titolo"
|
||||
@@ -1139,6 +1286,8 @@ _pages:
|
||||
list: "Liste"
|
||||
blocks:
|
||||
text: "Testo"
|
||||
multiLineText: "Testo (a più righe)"
|
||||
textList: "Lista di testo"
|
||||
_strLen:
|
||||
arg1: "Testo"
|
||||
_strPick:
|
||||
@@ -1193,13 +1342,18 @@ _pages:
|
||||
arg2: "B"
|
||||
_if:
|
||||
arg1: "Se"
|
||||
arg2: "Se"
|
||||
random: "Aleatorietà"
|
||||
_randomPick:
|
||||
arg1: "Liste"
|
||||
_dailyRandomPick:
|
||||
arg1: "Liste"
|
||||
_seedRandom:
|
||||
arg2: "Probabilità"
|
||||
_seedRandomPick:
|
||||
arg2: "Liste"
|
||||
_DRPWPM:
|
||||
arg1: "Lista di testo"
|
||||
_pick:
|
||||
arg1: "Liste"
|
||||
_listLen:
|
||||
@@ -1213,13 +1367,14 @@ _pages:
|
||||
types:
|
||||
string: "Testo"
|
||||
array: "Liste"
|
||||
stringArray: "Lista di testo"
|
||||
_notification:
|
||||
fileUploaded: "File caricato correttamente"
|
||||
youGotMention: "{name} ti ha menzionato"
|
||||
youGotReply: "{name} ti ha risposto"
|
||||
youGotQuote: "{name} ha citato il tuo Nota e ha detto"
|
||||
youRenoted: "{name} ha rinotato"
|
||||
youGotPoll: "{name} ha volluto."
|
||||
youGotPoll: "{name} ha votato"
|
||||
youGotMessagingMessageFromUser: "{name} ti ha mandato un messaggio"
|
||||
youGotMessagingMessageFromGroup: "{name} ti ha mandato un messaggio nella chat"
|
||||
youWereFollowed: "Ha iniziato a seguirti"
|
||||
|
||||
+24
-2
@@ -7,6 +7,7 @@ search: "検索"
|
||||
notifications: "通知"
|
||||
username: "ユーザー名"
|
||||
password: "パスワード"
|
||||
forgotPassword: "パスワードを忘れた"
|
||||
fetchingAsApObject: "連合に照会中"
|
||||
ok: "OK"
|
||||
gotIt: "わかった"
|
||||
@@ -278,6 +279,7 @@ emptyDrive: "ドライブは空です"
|
||||
emptyFolder: "フォルダーは空です"
|
||||
unableToDelete: "削除できません"
|
||||
inputNewFileName: "新しいファイル名を入力してください"
|
||||
inputNewDescription: "新しいキャプションを入力してください"
|
||||
inputNewFolderName: "新しいフォルダ名を入力してください"
|
||||
circularReferenceFolder: "移動先のフォルダーは、移動するフォルダーのサブフォルダーです。"
|
||||
hasChildFilesOrFolders: "このフォルダは空でないため、削除できません。"
|
||||
@@ -309,8 +311,8 @@ monthX: "{month}月"
|
||||
yearX: "{year}年"
|
||||
pages: "ページ"
|
||||
integration: "連携"
|
||||
connectSerice: "接続する"
|
||||
disconnectSerice: "切断する"
|
||||
connectService: "接続する"
|
||||
disconnectService: "切断する"
|
||||
enableLocalTimeline: "ローカルタイムラインを有効にする"
|
||||
enableGlobalTimeline: "グローバルタイムラインを有効にする"
|
||||
disablingTimelinesInfo: "これらのタイムラインを無効化しても、利便性のため管理者およびモデレーターは引き続き利用することができます。"
|
||||
@@ -545,6 +547,8 @@ disablePlayer: "プレイヤーを閉じる"
|
||||
expandTweet: "ツイートを展開する"
|
||||
themeEditor: "テーマエディター"
|
||||
description: "説明"
|
||||
describeFile: "キャプションを付ける"
|
||||
enterFileDescription: "キャプションを入力"
|
||||
author: "作者"
|
||||
leaveConfirm: "未保存の変更があります。破棄しますか?"
|
||||
manage: "管理"
|
||||
@@ -747,6 +751,24 @@ gallery: "ギャラリー"
|
||||
recentPosts: "最近の投稿"
|
||||
popularPosts: "人気の投稿"
|
||||
shareWithNote: "ノートで共有"
|
||||
ads: "広告"
|
||||
expiration: "期限"
|
||||
memo: "メモ"
|
||||
priority: "優先度"
|
||||
high: "高"
|
||||
middle: "中"
|
||||
low: "低"
|
||||
emailNotConfiguredWarning: "メールアドレスの設定がされていません。"
|
||||
ratio: "比率"
|
||||
|
||||
_ad:
|
||||
back: "戻る"
|
||||
reduceFrequencyOfThisAd: "この広告の表示頻度を下げる"
|
||||
|
||||
_forgotPassword:
|
||||
enterEmail: "アカウントに登録したメールアドレスを入力してください。そのアドレス宛てに、パスワードリセット用のリンクが送信されます。"
|
||||
ifNoEmail: "メールアドレスを登録していない場合は、管理者までお問い合わせください。"
|
||||
contactAdmin: "このインスタンスではメールがサポートされていないため、パスワードリセットを行う場合は管理者までお問い合わせください。"
|
||||
|
||||
_gallery:
|
||||
my: "自分の投稿"
|
||||
|
||||
+9
-3
@@ -308,8 +308,6 @@ monthX: "{month}月"
|
||||
yearX: "{year}年"
|
||||
pages: "ページ"
|
||||
integration: "連携"
|
||||
connectSerice: "つなぐ"
|
||||
disconnectSerice: "切ってまう"
|
||||
enableLocalTimeline: "ローカルタイムラインを使えるようにする"
|
||||
enableGlobalTimeline: "グローバルタイムラインを使えるようにする"
|
||||
disablingTimelinesInfo: "ここらへんのタイムラインを使えんようにしてしもても、管理者とモデレーターは使えるままになってるで、そうやなかったら不便やからな。"
|
||||
@@ -552,7 +550,7 @@ smtpSecure: "SMTP 接続に暗黙的なSSL/TLSを使用する"
|
||||
testEmail: "配信テスト"
|
||||
wordMute: "ワードミュート"
|
||||
userSaysSomething: "{name}が何か言ったようやで"
|
||||
makeActive: "アクティブにしてや"
|
||||
makeActive: "使うで"
|
||||
display: "表示"
|
||||
copy: "コピー"
|
||||
metrics: "メトリクス"
|
||||
@@ -643,6 +641,14 @@ goBack: "戻る"
|
||||
info: "情報"
|
||||
user: "ユーザー"
|
||||
administration: "管理"
|
||||
ads: "広告"
|
||||
expiration: "期限"
|
||||
memo: "メモ"
|
||||
high: "高い"
|
||||
middle: "中"
|
||||
low: "低い"
|
||||
_ad:
|
||||
back: "戻る"
|
||||
_gallery:
|
||||
unlike: "良くないわ"
|
||||
_email:
|
||||
|
||||
+46
-3
@@ -7,6 +7,7 @@ search: "검색"
|
||||
notifications: "알림"
|
||||
username: "유저명"
|
||||
password: "비밀번호"
|
||||
forgotPassword: "비밀번호 재설정"
|
||||
fetchingAsApObject: "연합에서 조회 중"
|
||||
ok: "OK"
|
||||
gotIt: "알겠어요"
|
||||
@@ -138,6 +139,7 @@ flagAsBotDescription: "이 계정을 자동화된 수단으로 운용할 경우
|
||||
flagAsCat: "나는 고양이다냥"
|
||||
flagAsCatDescription: "이 계정이 고양이라면 활성화 해주세요."
|
||||
autoAcceptFollowed: "팔로우 중인 유저로부터의 팔로우 요청을 자동 수락"
|
||||
addAccount: "계정 추가"
|
||||
loginFailed: "로그인에 실패했습니다"
|
||||
showOnRemote: "리모트에서 보기"
|
||||
general: "일반"
|
||||
@@ -277,6 +279,7 @@ emptyDrive: "드라이브가 비어 있습니다"
|
||||
emptyFolder: "폴더가 비어 있습니다"
|
||||
unableToDelete: "삭제할 수 없습니다"
|
||||
inputNewFileName: "바꿀 파일명을 입력해 주세요"
|
||||
inputNewDescription: "새 캡션을 입력해 주세요"
|
||||
inputNewFolderName: "바꿀 폴더명을 입력해 주세요"
|
||||
circularReferenceFolder: "지정한 폴더가 이동할 폴더의 하위 폴더입니다."
|
||||
hasChildFilesOrFolders: "이 폴더는 비어있지 않기 때문에 삭제할 수 없습니다."
|
||||
@@ -308,8 +311,8 @@ monthX: "{month}월"
|
||||
yearX: "{year}년"
|
||||
pages: "페이지"
|
||||
integration: "연동"
|
||||
connectSerice: "접속"
|
||||
disconnectSerice: "연결 끊기"
|
||||
connectService: "계정 연동"
|
||||
disconnectService: "계정 연동 해제"
|
||||
enableLocalTimeline: "로컬 타임라인 활성화"
|
||||
enableGlobalTimeline: "글로벌 타임라인 활성화"
|
||||
disablingTimelinesInfo: "특정 타임라인을 비활성화하더라도 관리자 및 모더레이터는 계속 사용할 수 있습니다."
|
||||
@@ -451,6 +454,7 @@ category: "카테고리"
|
||||
tags: "태그"
|
||||
docSource: "이 문서의 소스"
|
||||
createAccount: "계정 만들기"
|
||||
existingAccount: "기존 계정"
|
||||
regenerate: "재생성"
|
||||
fontSize: "글자 크기"
|
||||
noFollowRequests: "처리되지 않은 팔로우 요청이 없습니다"
|
||||
@@ -543,6 +547,8 @@ disablePlayer: "플레이어 닫기"
|
||||
expandTweet: "트윗 확장하기"
|
||||
themeEditor: "테마 에디터"
|
||||
description: "설명"
|
||||
describeFile: "캡션 추가"
|
||||
enterFileDescription: "캡션 입력"
|
||||
author: "작성자"
|
||||
leaveConfirm: "저장하지 않은 변경사항이 있습니다. 취소하시겠습니까?"
|
||||
manage: "관리"
|
||||
@@ -565,6 +571,7 @@ pluginTokenRequestedDescription: "이 플러그인은 여기서 설정한 권한
|
||||
notificationType: "알림 유형"
|
||||
edit: "편집"
|
||||
useStarForReactionFallback: "알 수 없는 리액션 이모지 대신 ★ 사용"
|
||||
emailServer: "메일 서버"
|
||||
enableEmail: "이메일 송신 기능 활성화"
|
||||
emailConfigInfo: "가입 시 메일 주소 확인이나 비밀번호 초기화 시에 사용합니다."
|
||||
email: "이메일"
|
||||
@@ -701,6 +708,7 @@ editCode: "코드 수정"
|
||||
apply: "적용"
|
||||
receiveAnnouncementFromInstance: "이 인스턴스의 알림을 이메일로 수신할게요"
|
||||
emailNotification: "메일 알림"
|
||||
publish: "게시"
|
||||
inChannelSearch: "채널에서 검색"
|
||||
useReactionPickerForContextMenu: "우클릭하여 리액션 선택기 열기"
|
||||
typingUsers: "{users} 님이 입력하고 있어요.."
|
||||
@@ -724,11 +732,46 @@ hideOnlineStatusDescription: "온라인 상태를 숨기면, 검색과 같은
|
||||
online: "온라인"
|
||||
active: "최근에 활동함"
|
||||
offline: "오프라인"
|
||||
notRecommended: "추천하지 않음"
|
||||
botProtection: "Bot 방어"
|
||||
instanceBlocking: "인스턴스 차단"
|
||||
selectAccount: "계정 선택"
|
||||
enabled: "활성화"
|
||||
disabled: "비활성화"
|
||||
quickAction: "빠른 동작"
|
||||
user: "유저"
|
||||
administration: "관리"
|
||||
accounts: "계정"
|
||||
switch: "전환"
|
||||
noMaintainerInformationWarning: "관리자 정보가 설정되어 있지 않습니다."
|
||||
noBotProtectionWarning: "Bot 방어가 설정되어 있지 않습니다."
|
||||
configure: "설정하기"
|
||||
postToGallery: "갤러리에 업로드"
|
||||
gallery: "갤러리"
|
||||
recentPosts: "최근 포스트"
|
||||
popularPosts: "인기 포스트"
|
||||
shareWithNote: "노트로 공유"
|
||||
ads: "광고"
|
||||
expiration: "기한"
|
||||
memo: "메모"
|
||||
priority: "우선순위"
|
||||
high: "높음"
|
||||
middle: "보통"
|
||||
low: "낮음"
|
||||
emailNotConfiguredWarning: "메일 주소가 설정되어 있지 않습니다."
|
||||
ratio: "비율"
|
||||
_ad:
|
||||
back: "뒤로"
|
||||
reduceFrequencyOfThisAd: "이 광고의 표시 빈도 낮추기"
|
||||
_forgotPassword:
|
||||
enterEmail: "여기에 계정에 등록한 메일 주소를 입력해 주세요. 입력한 메일 주소로 비밀번호 재설정 링크를 발송합니다."
|
||||
ifNoEmail: "메일 주소를 등록하지 않은 경우, 관리자에 문의해 주십시오."
|
||||
contactAdmin: "이 인스턴스에서는 메일 기능이 지원되지 않습니다. 비밀번호를 재설정하려면 관리자에게 문의해 주십시오."
|
||||
_gallery:
|
||||
unlike: "좋아요 해제"
|
||||
my: "내 갤러리"
|
||||
liked: "좋아요 한 갤러리"
|
||||
like: "좋아요!"
|
||||
unlike: "좋아요 취소"
|
||||
_email:
|
||||
_follow:
|
||||
title: "새로운 팔로워가 있습니다"
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
---
|
||||
_lang_: "Nederlands"
|
||||
headlineMisskey: "Netwerk verbonden door notities"
|
||||
|
||||
+116
-2
@@ -7,6 +7,7 @@ search: "Szukaj"
|
||||
notifications: "Powiadomienia"
|
||||
username: "Nazwa użytkownika"
|
||||
password: "Hasło"
|
||||
forgotPassword: "Nie pamiętam hasła"
|
||||
fetchingAsApObject: "Pobieranie z Fediwersum…"
|
||||
ok: "OK"
|
||||
gotIt: "Rozumiem!"
|
||||
@@ -65,6 +66,7 @@ download: "Pobierz"
|
||||
driveFileDeleteConfirm: "Czy chcesz usunąć plik \"{name}\"? Zniknie również notatka, do której dołączony jest ten plik."
|
||||
unfollowConfirm: "Czy na pewno chcesz przestać obserwować {name}?"
|
||||
exportRequested: "Zażądałeś eksportu. Może to zająć trochę czasu. Po zakończeniu eksportu zostanie on dodany do Twoich \"dysków\"."
|
||||
importRequested: "Zażądano importu. Może to zająć chwilę."
|
||||
lists: "Listy"
|
||||
noLists: "Nie masz żadnych list"
|
||||
note: "Utwórz wpis"
|
||||
@@ -133,9 +135,11 @@ settingGuide: "Proponowana konfiguracja"
|
||||
cacheRemoteFiles: "Przechowuj zdalne pliki w pamięci podręcznej"
|
||||
cacheRemoteFilesDescription: "Gdy ta opcja jest wyłączona, zdalne pliki są ładowane bezpośrednio ze zdalnych instancji. Wyłączenie the opcji zmniejszy użycie powierzchni dyskowej, ale zwiększy transfer, ponieważ miniaturki nie będą generowane."
|
||||
flagAsBot: "To konto jest botem"
|
||||
flagAsBotDescription: "Jeżeli ten kanał jest kontrolowany przez jakiś program, ustaw tę opcję. Jeżeli włączona, będzie działać jako flaga informująca innych programistów, aby zapobiegać nieskończonej interakcji z różnymi botami i dostosowywać wewnętrzne systemy Misskey, traktując konto jako bota."
|
||||
flagAsCat: "To konto jest kotem"
|
||||
flagAsCatDescription: "Przełącz tę opcję, aby konto było oznaczone jako kot."
|
||||
autoAcceptFollowed: "Automatycznie przyjmuj prośby o możliwość obserwacji od użytkowników, których obserwujesz"
|
||||
addAccount: "Dodaj konto"
|
||||
loginFailed: "Nie udało się zalogować"
|
||||
showOnRemote: "Zobacz na zdalnej instancji"
|
||||
general: "Ogólne"
|
||||
@@ -179,6 +183,7 @@ clearQueueConfirmTitle: "Czy na pewno chcesz wyczyścić kolejkę?"
|
||||
clearCachedFiles: "Wyczyść pamięć podręczną"
|
||||
clearCachedFilesConfirm: "Czy na pewno chcesz usunąć wszystkie zdalne pliki z pamięci podręcznej?"
|
||||
blockedInstances: "Zablokowane instancje"
|
||||
blockedInstancesDescription: "Wypisz nazwy hostów instancji, które powinny zostać zablokowane. Wypisane instancje nie będą mogły dłużej komunikować się z tą instancją."
|
||||
muteAndBlock: "Wycisz / Zablokuj"
|
||||
mutedUsers: "Wyciszeni użytkownicy"
|
||||
blockedUsers: "Zablokowani użytkownicy"
|
||||
@@ -271,6 +276,7 @@ emptyDrive: "Dysk jest pusty"
|
||||
emptyFolder: "Ten katalog jest pusty"
|
||||
unableToDelete: "Nie można usunąć"
|
||||
inputNewFileName: "Wprowadź nową nazwę pliku"
|
||||
inputNewDescription: "Proszę wpisać nowy napis"
|
||||
inputNewFolderName: "Wprowadź nową nazwę katalogu"
|
||||
circularReferenceFolder: "Katalog docelowy jest podkatalogiem katalogu, który chcesz przenieść."
|
||||
hasChildFilesOrFolders: "Ponieważ ten katalog nie jest pusty, nie może być usunięty."
|
||||
@@ -291,16 +297,17 @@ reject: "Odrzuć"
|
||||
normal: "Normalny"
|
||||
instanceName: "Nazwa instancji"
|
||||
instanceDescription: "Opis instancji"
|
||||
maintainerName: "Administrator"
|
||||
maintainerEmail: "E-mail administratora"
|
||||
tosUrl: "Adres URL regulaminu"
|
||||
thisYear: "Rok"
|
||||
thisMonth: "Miesiąc"
|
||||
today: "Dziś"
|
||||
dayX: "{day}"
|
||||
monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Strony"
|
||||
integration: "Integracja"
|
||||
connectSerice: "Połącz"
|
||||
disconnectSerice: "Rozłącz"
|
||||
enableLocalTimeline: "Włącz lokalną oś czasu"
|
||||
enableGlobalTimeline: "Włącz globalną oś czasu"
|
||||
disablingTimelinesInfo: "Administratorzy i moderatorzy będą zawsze mieć dostęp do wszystkich osi czasu, nawet gdy są one wyłączone."
|
||||
@@ -332,6 +339,7 @@ manageAntennas: "Zarządzaj Antenami"
|
||||
name: "Nazwa"
|
||||
antennaSource: "Źródło Anteny"
|
||||
antennaExcludeKeywords: "Wykluczone słowa kluczowe"
|
||||
notifyAntenna: "Powiadamiaj o nowych wpisach"
|
||||
withFileAntenna: "Filtruj tylko wpisy z załączonym plikiem"
|
||||
enableServiceworker: "Włącz ServiceWorker"
|
||||
antennaUsersDescription: "Wypisz po jednej nazwie użytkownika w linii"
|
||||
@@ -358,6 +366,7 @@ administrator: "Admin"
|
||||
token: "Token"
|
||||
twoStepAuthentication: "Uwierzytelnianie dwuskładnikowe"
|
||||
moderator: "Moderator"
|
||||
nUsersMentioned: "{n} wspomnianych użytkowników"
|
||||
securityKey: "Klucz bezpieczeństwa"
|
||||
securityKeyName: "Nazwa klucza"
|
||||
registerSecurityKey: "Zarejestruj klucz bezpieczeństwa"
|
||||
@@ -397,6 +406,7 @@ retype: "Wprowadź ponownie"
|
||||
noteOf: "Wpisy {user}"
|
||||
inviteToGroup: "Zaproś do grupy"
|
||||
maxNoteTextLength: "Limit znaków dla wpisów"
|
||||
quoteAttached: "Zacytowano"
|
||||
quoteQuestion: "Czy na pewno chcesz umieścić cytat?"
|
||||
noMessagesYet: "Nie napisano jeszcze wiadomości"
|
||||
newMessageExists: "Masz nową wiadomość"
|
||||
@@ -419,6 +429,7 @@ signinWith: "Zaloguj się z {x}"
|
||||
signinFailed: "Nie udało się zalogować. Wprowadzona nazwa użytkownika lub hasło są nieprawidłowe."
|
||||
tapSecurityKey: "Wybierz swój klucz bezpieczeństwa"
|
||||
or: "Lub"
|
||||
language: "Język"
|
||||
uiLanguage: "Język wyświetlania UI"
|
||||
groupInvited: "Zaproszony(-a) do grupy"
|
||||
aboutX: "O {x}"
|
||||
@@ -432,6 +443,7 @@ category: "Kategoria"
|
||||
tags: "Tagi"
|
||||
docSource: "Źródło tego dokumentu"
|
||||
createAccount: "Utwórz konto"
|
||||
existingAccount: "Istniejące konto"
|
||||
regenerate: "Wygeneruj ponownie"
|
||||
fontSize: "Rozmiar czcionki"
|
||||
noFollowRequests: "Nie masz żadnych oczekujących próśb o możliwość obserwacji"
|
||||
@@ -453,6 +465,8 @@ showFeaturedNotesInTimeline: "Pokazuj wyróżnione wpisy w osi czasu"
|
||||
objectStorage: "Pamięć obiektowa"
|
||||
useObjectStorage: "Używaj pamięci obiektowej"
|
||||
objectStorageBaseUrl: "Podstawowy URL"
|
||||
objectStorageBucket: "Bucket"
|
||||
objectStorageBucketDesc: "Podaj nazwę „wiadra” używaną przez konfigurowaną usługę."
|
||||
objectStoragePrefix: "Prefiks"
|
||||
objectStoragePrefixDesc: "Pliki będą przechowywane w katalogu z tym prefiksem."
|
||||
objectStorageEndpoint: "Punkt końcowy"
|
||||
@@ -519,6 +533,8 @@ disablePlayer: "Zamknij odtwarzacz wideo"
|
||||
expandTweet: "Rozwiń tweet"
|
||||
themeEditor: "Edytor motywu"
|
||||
description: "Opis"
|
||||
describeFile: "dodaj podpis"
|
||||
enterFileDescription: "Wprowadź napis"
|
||||
author: "Autor"
|
||||
leaveConfirm: "Są niezapisane zmiany. Czy chcesz je odrzucić?"
|
||||
manage: "Zarządzanie"
|
||||
@@ -540,6 +556,7 @@ pluginTokenRequestedDescription: "Ta wtyczka będzie mogła korzystać z ustawio
|
||||
notificationType: "Rodzaj powiadomień"
|
||||
edit: "Edytuj"
|
||||
useStarForReactionFallback: "Użyj ★ jako zapasowego emoji, gdy emoji reakcji jest nieznane"
|
||||
emailServer: "Serwer poczty e-mail"
|
||||
enableEmail: "Włącz dostarczanie wiadomości e-mail"
|
||||
emailConfigInfo: "Wykorzystywany do potwierdzenia adresu e-mail w trakcie rejestracji, lub gdy zapomnisz hasła"
|
||||
email: "Adres e-mail"
|
||||
@@ -552,6 +569,7 @@ smtpPass: "Hasło"
|
||||
emptyToDisableSmtpAuth: "Pozostaw adres e-mail i hasło puste, aby wyłączyć weryfikację SMTP"
|
||||
smtpSecureInfo: "Wyłącz, jeżeli używasz STARTTLS"
|
||||
testEmail: "Przetestuj dostarczanie wiadomości e-mail"
|
||||
wordMute: "Wyciszenie słowa"
|
||||
userSaysSomething: "{name} powiedział(-a) coś"
|
||||
makeActive: "Aktywuj"
|
||||
display: "Wyświetlanie"
|
||||
@@ -622,6 +640,7 @@ emailVerified: "Adres e-mail został potwierdzony"
|
||||
noteFavoritesCount: "Liczba polubionych wpisów"
|
||||
pageLikesCount: "Liczba otrzymanych polubień stron"
|
||||
pageLikedCount: "Liczba polubionych stron"
|
||||
reversiCount: "Liczba rozgrywek Reversi"
|
||||
contact: "Kontakt"
|
||||
useSystemFont: "Używaj domyślnej czcionki systemu"
|
||||
experimentalFeatures: "Eksperymentalne funkcje"
|
||||
@@ -630,6 +649,7 @@ makeExplorable: "Pokazuj konto na stronie „Eksploruj”"
|
||||
makeExplorableDescription: "Jeżeli wyłączysz tę opcję, Twoje konto nie będzie wyświetlać się w sekcji „Eksploruj”."
|
||||
showGapBetweenNotesInTimeline: "Pokazuj odstęp między wpisami na osi czasu."
|
||||
duplicate: "Duplikuj"
|
||||
left: "Lewo"
|
||||
center: "Wyśsrodkuj"
|
||||
wide: "Szerokie"
|
||||
narrow: "Wąskie"
|
||||
@@ -639,22 +659,107 @@ clearCache: "Wyczyść pamięć podręczną"
|
||||
onlineUsersCount: "{n} osób jest online"
|
||||
nUsers: "{n} użytkowników"
|
||||
nNotes: "{n} wpisów"
|
||||
sendErrorReports: "Wyślij raporty o błędach"
|
||||
myTheme: "Mój motyw"
|
||||
backgroundColor: "Tło"
|
||||
accentColor: "Akcent"
|
||||
textColor: "Tekst"
|
||||
saveAs: "Zapisz jako…"
|
||||
advanced: "Zaawansowane"
|
||||
value: "Wartość"
|
||||
createdAt: "Utworzono"
|
||||
updatedAt: "Zaktualizowano"
|
||||
saveConfirm: "Zapisać zmiany?"
|
||||
deleteConfirm: "Na pewno usunąć?"
|
||||
invalidValue: "Nieprawidłowa wartość."
|
||||
registry: "Rejestr"
|
||||
closeAccount: "Zamknij konto"
|
||||
currentVersion: "Bieżąca wersja"
|
||||
latestVersion: "Najnowsza wersja"
|
||||
youAreRunningUpToDateClient: "Korzystasz z najnowszej wersji klienta."
|
||||
newVersionOfClientAvailable: "Nowsza wersja klienta jest dostępna."
|
||||
usageAmount: "Użycie"
|
||||
capacity: "Pojemność"
|
||||
inUse: "Użyto"
|
||||
editCode: "Edytuj kod"
|
||||
apply: "Zastosuj"
|
||||
receiveAnnouncementFromInstance: "Otrzymuj powiadomienia e-mail z tej instancji"
|
||||
emailNotification: "Powiadomienia e-mail"
|
||||
publish: "Publikuj"
|
||||
inChannelSearch: "Szukaj na kanale"
|
||||
useReactionPickerForContextMenu: "Otwórz wybornik reakcji prawym kliknięciem"
|
||||
typingUsers: "{users} pisze(-ą)..."
|
||||
jumpToSpecifiedDate: "Przejdź do określonej daty"
|
||||
showingPastTimeline: "Obecnie wyświetla starą oś czasu"
|
||||
clear: "Wróć"
|
||||
markAllAsRead: "Oznacz wszystkie jako przeczytane"
|
||||
goBack: "Wróć"
|
||||
unlikeConfirm: "Na pewno chcesz usunąć polubienie?"
|
||||
fullView: "Pełny widok"
|
||||
quitFullView: "Opuść pełny widok"
|
||||
addDescription: "Dodaj opis"
|
||||
info: "Informacje"
|
||||
userInfo: "Informacje o użykowniku"
|
||||
unknown: "Nieznane"
|
||||
onlineStatus: "Status online"
|
||||
hideOnlineStatus: "Ukryj status online"
|
||||
hideOnlineStatusDescription: "Ukrywanie statusu online ogranicza wygody niektórych funkcji, tj. wyszukiwanie"
|
||||
online: "Online"
|
||||
active: "Aktywny"
|
||||
offline: "Offline"
|
||||
notRecommended: "Nie zalecane"
|
||||
botProtection: "Zabezpieczenie przed botami"
|
||||
instanceBlocking: "Zablokowane instancje"
|
||||
selectAccount: "Wybierz konto"
|
||||
enabled: "Właczono"
|
||||
disabled: "Wyłączono"
|
||||
quickAction: "Szybkie działania"
|
||||
user: "Użytkownicy"
|
||||
administration: "Zarządzanie"
|
||||
accounts: "Konta"
|
||||
switch: "Przełącz"
|
||||
noMaintainerInformationWarning: "Informacje o administratorze nie są skonfigurowane."
|
||||
noBotProtectionWarning: "Zabezpieczenie przed botami nie jest skonfigurowane."
|
||||
configure: "Skonfiguruj"
|
||||
postToGallery: "Opublikuj w galerii"
|
||||
gallery: "Galeria"
|
||||
recentPosts: "Ostatnie wpisy"
|
||||
popularPosts: "Popularne wpisy"
|
||||
shareWithNote: "Udostępnij z wpisem"
|
||||
ads: "Reklamy"
|
||||
expiration: "Ankieta kończy się"
|
||||
memo: "Notatki"
|
||||
priority: "Priorytet"
|
||||
high: "Wysoki"
|
||||
middle: "Średnie"
|
||||
low: "Niski"
|
||||
emailNotConfiguredWarning: "Nie podano adresu e-mail"
|
||||
ratio: "Stosunek"
|
||||
_ad:
|
||||
back: "Wróć"
|
||||
reduceFrequencyOfThisAd: "Pokazuj tę reklamę rzadziej"
|
||||
_forgotPassword:
|
||||
ifNoEmail: "Jeżeli nie podano adresu e-mail podczas rejestracji, skontaktuj się z administratorem zamiast tego."
|
||||
contactAdmin: "Jeżeli Twoja instancja nie obsługuje adresów e-mail, skontaktuj się zamiast tego z administratorem, aby zresetować hasło."
|
||||
_gallery:
|
||||
my: "Moja galeria"
|
||||
liked: "Polubione wpisy"
|
||||
like: "Polub"
|
||||
unlike: "Cofnij polubienie"
|
||||
_email:
|
||||
_follow:
|
||||
title: "Zaobserwował(a) Cię"
|
||||
_receiveFollowRequest:
|
||||
title: "Otrzymano prośbę o możliwość obserwacji"
|
||||
_plugin:
|
||||
install: "Zainstaluj wtyczki"
|
||||
installWarn: "Nie instaluj niezaufanych wtyczek."
|
||||
manage: "Zarządzanie wtyczkami"
|
||||
_registry:
|
||||
scope: "Zakres"
|
||||
key: "Klucz"
|
||||
keys: "Klucz"
|
||||
domain: "Domena"
|
||||
createKey: "Utwórz klucz"
|
||||
_aboutMisskey:
|
||||
about: "Misskey jest oprogramowanie open source rozwijanym przez syuilo od 2014."
|
||||
@@ -704,6 +809,7 @@ _mfm:
|
||||
x4Description: "Czyni treść jeszcze większą niż jeszcze większa."
|
||||
blur: "Rozmycie"
|
||||
font: "Czcionka"
|
||||
fontDescription: "Wybiera czcionkę do wyświetlania treści."
|
||||
_reversi:
|
||||
reversi: "Reversi"
|
||||
gameSettings: "Ustawienia gry"
|
||||
@@ -968,16 +1074,21 @@ _profile:
|
||||
username: "Nazwa użytkownika"
|
||||
description: "Opis"
|
||||
youCanIncludeHashtags: "Możesz umieścić hashtagi w swoim opisie."
|
||||
metadata: "Dodatkowe informacje"
|
||||
metadataEdit: "Edytuj dodatkowe informacje"
|
||||
metadataDescription: "Możesz wyświetlać do czterech sekcji dodatkowych informacji na swoim profilu."
|
||||
metadataLabel: "Etykieta"
|
||||
metadataContent: "Treść"
|
||||
changeAvatar: "Zmień awatar"
|
||||
changeBanner: "Zmień baner"
|
||||
_exportOrImport:
|
||||
allNotes: "Wszystkie wpisy"
|
||||
followingList: "Obserwowani"
|
||||
muteList: "Wycisz"
|
||||
blockingList: "Zablokuj"
|
||||
userLists: "Listy"
|
||||
_charts:
|
||||
federationInstancesTotal: "Łącznie sfederowanych instancji"
|
||||
usersTotal: "Łącznie # użytkowników"
|
||||
activeUsers: "Aktywni użytkownicy"
|
||||
_instanceCharts:
|
||||
@@ -992,6 +1103,7 @@ _instanceCharts:
|
||||
_timelines:
|
||||
home: "Strona główna"
|
||||
local: "Lokalne"
|
||||
social: "Społeczność"
|
||||
global: "Globalna"
|
||||
_rooms:
|
||||
roomOf: "Pokój {user}"
|
||||
@@ -1362,6 +1474,8 @@ _deck:
|
||||
swapRight: "Przesuń w prawo"
|
||||
swapUp: "Zamień z powyższym"
|
||||
swapDown: "Zamień z poniższym"
|
||||
stackLeft: "Przypnij do lewej"
|
||||
popRight: "Odepnij w prawo"
|
||||
profile: "Profil"
|
||||
_columns:
|
||||
main: "Główna"
|
||||
|
||||
+13
-2
@@ -309,8 +309,6 @@ monthX: "{month} месяц"
|
||||
yearX: "{year} год"
|
||||
pages: "Страницы"
|
||||
integration: "Интеграция"
|
||||
connectSerice: "Соединение"
|
||||
disconnectSerice: "Отключение"
|
||||
enableLocalTimeline: "Включить локальную ленту"
|
||||
enableGlobalTimeline: "Включить глобальную ленту"
|
||||
disablingTimelinesInfo: "У администраторов и модераторов есть доступ ко всем лентам, даже если они отключены."
|
||||
@@ -704,6 +702,7 @@ editCode: "Редактировать исходный текст"
|
||||
apply: "Применить"
|
||||
receiveAnnouncementFromInstance: "Получать оповещения с инстанса"
|
||||
emailNotification: "Уведомления по электронной почте"
|
||||
publish: "Опубликовать"
|
||||
inChannelSearch: "Поиск по каналу"
|
||||
useReactionPickerForContextMenu: "Открывать палитру реакций правой кнопкой"
|
||||
typingUsers: "Стук клавиш. Это {users}…"
|
||||
@@ -741,7 +740,19 @@ switch: "Переключение"
|
||||
noMaintainerInformationWarning: "Не заполнены сведения об администраторах"
|
||||
noBotProtectionWarning: "Ботозащита не настроена"
|
||||
configure: "Настроить"
|
||||
postToGallery: "Опубликовать в галерею"
|
||||
gallery: "Галерея"
|
||||
recentPosts: "Недавние публикации"
|
||||
popularPosts: "Популярные публикации"
|
||||
shareWithNote: "Поделиться заметкой"
|
||||
expiration: "Опрос длится"
|
||||
middle: "Средне"
|
||||
_ad:
|
||||
back: "Выход"
|
||||
_gallery:
|
||||
my: "Личная"
|
||||
liked: "Понравившееся"
|
||||
like: "Нравится!"
|
||||
unlike: "Отменить «нравится»"
|
||||
_email:
|
||||
_follow:
|
||||
|
||||
+4
-2
@@ -307,8 +307,6 @@ monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Сторінки"
|
||||
integration: "Інтеграція"
|
||||
connectSerice: "Під’єднати"
|
||||
disconnectSerice: "Відключитися"
|
||||
enableLocalTimeline: "Увімкнути локальну стрічку"
|
||||
enableGlobalTimeline: "Увімкнути глобальну стрічку"
|
||||
disablingTimelinesInfo: "Адміністратори та модератори завжди мають доступ до всіх стрічок, навіть якщо вони вимкнуті."
|
||||
@@ -689,6 +687,10 @@ goBack: "Назад"
|
||||
info: "Інформація"
|
||||
user: "Користувачі"
|
||||
administration: "Управління"
|
||||
expiration: "Опитування закінчується"
|
||||
middle: "Середній"
|
||||
_ad:
|
||||
back: "Назад"
|
||||
_gallery:
|
||||
unlike: "Не вподобати"
|
||||
_email:
|
||||
|
||||
+26
-6
@@ -7,6 +7,7 @@ search: "搜索"
|
||||
notifications: "通知"
|
||||
username: "用户名"
|
||||
password: "密码"
|
||||
forgotPassword: "忘记密码"
|
||||
fetchingAsApObject: "联合查询中"
|
||||
ok: "OK"
|
||||
gotIt: "我明白了"
|
||||
@@ -173,7 +174,7 @@ metadata: "元数据"
|
||||
withNFiles: "{n}个文件"
|
||||
monitor: "监视器"
|
||||
jobQueue: "作业队列"
|
||||
cpuAndMemory: "CPU使用量"
|
||||
cpuAndMemory: "CPU和内存"
|
||||
network: "网络"
|
||||
disk: "存储"
|
||||
instanceInfo: "实例信息"
|
||||
@@ -278,6 +279,7 @@ emptyDrive: "驱动器为空"
|
||||
emptyFolder: "空文件夹"
|
||||
unableToDelete: "无法删除"
|
||||
inputNewFileName: "请输入新文件名"
|
||||
inputNewDescription: "请输入新标题"
|
||||
inputNewFolderName: "请输入新文件名"
|
||||
circularReferenceFolder: "目标文件夹是您要移动的文件夹的子文件夹。"
|
||||
hasChildFilesOrFolders: "此文件夹不为空,无法删除。"
|
||||
@@ -309,8 +311,8 @@ monthX: "{month}月"
|
||||
yearX: "{year}年"
|
||||
pages: "页面"
|
||||
integration: "关联"
|
||||
connectSerice: "连接"
|
||||
disconnectSerice: "断开连接"
|
||||
connectService: "连接"
|
||||
disconnectService: "断开连接"
|
||||
enableLocalTimeline: "启用本地时间线功能"
|
||||
enableGlobalTimeline: "启用全局时间线"
|
||||
disablingTimelinesInfo: "即使时间线功能被禁用,出于便利性的原因,管理员和数据图表也可以继续使用。"
|
||||
@@ -545,6 +547,8 @@ disablePlayer: "关闭播放器"
|
||||
expandTweet: "展开贴文"
|
||||
themeEditor: "主题编辑器"
|
||||
description: "描述"
|
||||
describeFile: "添加标题"
|
||||
enterFileDescription: "输入标题"
|
||||
author: "作者"
|
||||
leaveConfirm: "存在未保存的更改。要放弃更改吗?"
|
||||
manage: "管理"
|
||||
@@ -747,11 +751,27 @@ gallery: "图库"
|
||||
recentPosts: "最新发布"
|
||||
popularPosts: "热门投稿"
|
||||
shareWithNote: "在帖子中分享"
|
||||
ads: "广告"
|
||||
expiration: "截止时间"
|
||||
memo: "便笺"
|
||||
priority: "优先级"
|
||||
high: "高"
|
||||
middle: "中"
|
||||
low: "低"
|
||||
emailNotConfiguredWarning: "电子邮件地址未设置。"
|
||||
ratio: "比率"
|
||||
_ad:
|
||||
back: "返回"
|
||||
reduceFrequencyOfThisAd: "减少此广告的频率"
|
||||
_forgotPassword:
|
||||
enterEmail: "请输入您用来注册帐户的电子邮件地址。密码重置链接将发送到该地址。"
|
||||
ifNoEmail: "如果您没有使用电子邮件地址注册,请联系管理员。"
|
||||
contactAdmin: "该实例不支持电子邮件。如果您想重设密码,请联系管理员。"
|
||||
_gallery:
|
||||
my: "我的图库"
|
||||
liked: "喜欢的图片"
|
||||
like: "喜欢❤"
|
||||
unlike: "取消赞"
|
||||
like: "喜欢"
|
||||
unlike: "取消喜欢"
|
||||
_email:
|
||||
_follow:
|
||||
title: "你有新的关注者"
|
||||
@@ -1278,7 +1298,7 @@ _pages:
|
||||
viewSource: "查看源代码"
|
||||
viewPage: "查看页面"
|
||||
like: "赞"
|
||||
unlike: "取消赞"
|
||||
unlike: "取消喜欢"
|
||||
my: "我的页面"
|
||||
liked: "喜欢的页面"
|
||||
featured: "热门"
|
||||
|
||||
+17
-12
@@ -1,18 +1,19 @@
|
||||
---
|
||||
_lang_: "繁體中文"
|
||||
headlineMisskey: "貼文連繫網絡"
|
||||
introMisskey: "歡迎! Misskey是一個開源且去中心化的社群網絡。\n通過「貼文」分享周邊新鮮事,並告訴其他人您的想法!📡\n透過「情感」功能,對大家的貼文表達情感!👍\n一起來探索這個新的世界吧!🚀"
|
||||
headlineMisskey: "貼文連繫網路"
|
||||
introMisskey: "歡迎! Misskey是一個開放原始碼且去中心化的社群網路。\n透過「貼文」分享周邊新鮮事,並告訴其他人您的想法!📡\n透過「情感」功能,對大家的貼文表達情感!👍\n一起來探索這個新的世界吧!🚀"
|
||||
monthAndDay: "{month}月 {day}日"
|
||||
search: "搜尋"
|
||||
notifications: "通知"
|
||||
username: "使用者名稱"
|
||||
password: "密碼"
|
||||
forgotPassword: "忘記密碼"
|
||||
fetchingAsApObject: "從聯邦宇宙取得中..."
|
||||
ok: "OK"
|
||||
gotIt: "知道了"
|
||||
cancel: "取消"
|
||||
enterUsername: "輸入使用者名稱"
|
||||
renotedBy: "{user} 轉發了"
|
||||
renotedBy: "{user} 轉傳了"
|
||||
noNotes: "貼文不可用。"
|
||||
noNotifications: "沒有通知"
|
||||
instance: "實例"
|
||||
@@ -44,7 +45,7 @@ copyLink: "複製連結"
|
||||
delete: "刪除"
|
||||
deleteAndEdit: "刪除並編輯"
|
||||
deleteAndEditConfirm: "要刪除並再次編輯嗎?此貼文的所有情感、轉發和回覆也將會消失。"
|
||||
addToList: "新增至清單"
|
||||
addToList: "加入至清單"
|
||||
sendMessage: "發送訊息"
|
||||
copyUsername: "複製用戶名"
|
||||
searchUser: "搜尋用戶"
|
||||
@@ -92,9 +93,9 @@ followRequestPending: "追隨許可批准中"
|
||||
enterEmoji: "輸入表情符號"
|
||||
renote: "轉發"
|
||||
unrenote: "取消轉發"
|
||||
renoted: "轉發成功"
|
||||
renoted: "轉傳成功"
|
||||
cantRenote: "無法轉發此貼文。"
|
||||
cantReRenote: "無法轉發之前已經轉發過的內容。"
|
||||
cantReRenote: "無法轉傳之前已經轉傳過的內容。"
|
||||
quote: "引用"
|
||||
pinnedNote: "已置頂的貼文"
|
||||
pinned: "置頂"
|
||||
@@ -129,7 +130,7 @@ customEmojis: "自訂表情符號"
|
||||
emoji: "表情符號"
|
||||
emojiName: "表情符號名稱"
|
||||
emojiUrl: "表情符號URL"
|
||||
addEmoji: "新增表情符號"
|
||||
addEmoji: "加入表情符號"
|
||||
settingGuide: "推薦設定"
|
||||
cacheRemoteFiles: "緩存非遠程檔案"
|
||||
cacheRemoteFilesDescription: "禁用此設定會停止遠端檔案的緩存,從而節省儲存空間,但資料會因直接連線從而產生額外連接數據。"
|
||||
@@ -218,7 +219,7 @@ newPasswordRetype: "確認密碼"
|
||||
attachFile: "上傳附件"
|
||||
more: "更多!"
|
||||
featured: "精選"
|
||||
usernameOrUserId: "使用者名稱或用戶ID"
|
||||
usernameOrUserId: "使用者名稱或使用者ID"
|
||||
noSuchUser: "使用者不存在"
|
||||
lookup: "查詢"
|
||||
announcements: "公告"
|
||||
@@ -273,7 +274,7 @@ folderName: "資料夾名稱"
|
||||
createFolder: "新增資料夾"
|
||||
renameFolder: "重新命名資料夾"
|
||||
deleteFolder: "刪除資料夾"
|
||||
addFile: "添加附件"
|
||||
addFile: "加入附件"
|
||||
emptyDrive: "雲端硬碟為空"
|
||||
emptyFolder: "資料夾為空"
|
||||
unableToDelete: "無法刪除"
|
||||
@@ -309,8 +310,6 @@ monthX: "{month}月"
|
||||
yearX: "{year}年"
|
||||
pages: "頁面"
|
||||
integration: "整合"
|
||||
connectSerice: "連線"
|
||||
disconnectSerice: "中斷連線"
|
||||
enableLocalTimeline: "開啟本地時間軸"
|
||||
enableGlobalTimeline: "啟用公開時間軸"
|
||||
disablingTimelinesInfo: "即使您關閉了時間線功能,管理員和協調人仍可以繼續使用,以方便您。"
|
||||
@@ -693,6 +692,7 @@ editCode: "編輯代碼"
|
||||
apply: "套用"
|
||||
receiveAnnouncementFromInstance: "接收由本實例發出的電郵通知"
|
||||
emailNotification: "郵件通知"
|
||||
publish: "發佈"
|
||||
inChannelSearch: "頻道内搜尋"
|
||||
useReactionPickerForContextMenu: "點擊右鍵開啟回應工具欄"
|
||||
typingUsers: "{users}輸入中..."
|
||||
@@ -730,6 +730,11 @@ switch: "切換"
|
||||
noMaintainerInformationWarning: "尚未設定管理員信息。"
|
||||
noBotProtectionWarning: "尚未設定Bot防護。"
|
||||
configure: "設定"
|
||||
expiration: "期限"
|
||||
middle: "中"
|
||||
emailNotConfiguredWarning: "沒有設定電子郵件地址"
|
||||
_ad:
|
||||
back: "返回"
|
||||
_gallery:
|
||||
unlike: "收回喜歡"
|
||||
_email:
|
||||
@@ -1473,7 +1478,7 @@ _notification:
|
||||
reply: "回覆"
|
||||
renote: "轉發貼文"
|
||||
quote: "引用"
|
||||
reaction: "情感"
|
||||
reaction: "反應"
|
||||
pollVote: "統計已投票數"
|
||||
receiveFollowRequest: "已收到追隨請求"
|
||||
followRequestAccepted: "追隨請求已接受"
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||
|
||||
export class passwordReset1619942102890 implements MigrationInterface {
|
||||
name = 'passwordReset1619942102890'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE TABLE "password_reset_request" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "token" character varying(256) NOT NULL, "userId" character varying(32) NOT NULL, CONSTRAINT "PK_fcf4b02eae1403a2edaf87fd074" PRIMARY KEY ("id"))`);
|
||||
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_0b575fa9a4cfe638a925949285" ON "password_reset_request" ("token") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_4bb7fd4a34492ae0e6cc8d30ac" ON "password_reset_request" ("userId") `);
|
||||
await queryRunner.query(`ALTER TABLE "password_reset_request" ADD CONSTRAINT "FK_4bb7fd4a34492ae0e6cc8d30ac8" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "password_reset_request" DROP CONSTRAINT "FK_4bb7fd4a34492ae0e6cc8d30ac8"`);
|
||||
await queryRunner.query(`DROP INDEX "IDX_4bb7fd4a34492ae0e6cc8d30ac"`);
|
||||
await queryRunner.query(`DROP INDEX "IDX_0b575fa9a4cfe638a925949285"`);
|
||||
await queryRunner.query(`DROP TABLE "password_reset_request"`);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||
|
||||
export class ad1620019354680 implements MigrationInterface {
|
||||
name = 'ad1620019354680'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE TABLE "ad" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "expiresAt" TIMESTAMP WITH TIME ZONE NOT NULL, "place" character varying(32) NOT NULL, "priority" character varying(32) NOT NULL, "url" character varying(1024) NOT NULL, "imageUrl" character varying(1024) NOT NULL, "memo" character varying(8192) NOT NULL, CONSTRAINT "PK_0193d5ef09746e88e9ea92c634d" PRIMARY KEY ("id")); COMMENT ON COLUMN "ad"."createdAt" IS 'The created date of the Ad.'; COMMENT ON COLUMN "ad"."expiresAt" IS 'The expired date of the Ad.'`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_1129c2ef687fc272df040bafaa" ON "ad" ("createdAt") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_2da24ce20ad209f1d9dc032457" ON "ad" ("expiresAt") `);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP INDEX "IDX_2da24ce20ad209f1d9dc032457"`);
|
||||
await queryRunner.query(`DROP INDEX "IDX_1129c2ef687fc272df040bafaa"`);
|
||||
await queryRunner.query(`DROP TABLE "ad"`);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||
|
||||
export class ad21620364649428 implements MigrationInterface {
|
||||
name = 'ad21620364649428'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "ad" ADD "ratio" integer NOT NULL DEFAULT '1'`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "ad" DROP COLUMN "ratio"`);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||
|
||||
export class addNoteIndexes1621479946000 implements MigrationInterface {
|
||||
name = 'addNoteIndexes1621479946000'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE INDEX "IDX_NOTE_MENTIONS" ON "note" USING gin ("mentions")`, undefined);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_NOTE_VISIBLE_USER_IDS" ON "note" USING gin ("visibleUserIds")`, undefined);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP INDEX "IDX_NOTE_MENTIONS"`, undefined);
|
||||
await queryRunner.query(`DROP INDEX "IDX_NOTE_VISIBLE_USER_IDS"`, undefined);
|
||||
}
|
||||
|
||||
}
|
||||
+54
-51
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"author": "syuilo <syuilotan@yahoo.co.jp>",
|
||||
"version": "12.79.1",
|
||||
"version": "12.82.0",
|
||||
"codename": "indigo",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -30,52 +30,52 @@
|
||||
"format": "gulp format"
|
||||
},
|
||||
"resolutions": {
|
||||
"mfm-js/twemoji-parser": "13.1.x",
|
||||
"chokidar": "^3.3.1",
|
||||
"constantinople": "^4.0.1",
|
||||
"gulp/gulp-cli/yargs/yargs-parser": "5.0.0-security.0",
|
||||
"jsonld/rdf-canonize/node-forge": "0.10.0",
|
||||
"lodash": "^4.17.20"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-runtime": "7.13.15",
|
||||
"@babel/plugin-transform-runtime": "7.14.3",
|
||||
"@elastic/elasticsearch": "7.11.0",
|
||||
"@koa/cors": "3.1.0",
|
||||
"@koa/multer": "3.0.0",
|
||||
"@koa/router": "9.0.1",
|
||||
"@sentry/browser": "5.29.2",
|
||||
"@sentry/tracing": "5.29.2",
|
||||
"@sinonjs/fake-timers": "7.0.5",
|
||||
"@sinonjs/fake-timers": "7.1.2",
|
||||
"@syuilo/aiscript": "0.11.1",
|
||||
"@types/bcryptjs": "2.4.2",
|
||||
"@types/bull": "3.15.1",
|
||||
"@types/cbor": "5.0.1",
|
||||
"@types/cbor": "6.0.0",
|
||||
"@types/dateformat": "3.0.1",
|
||||
"@types/escape-regexp": "0.0.0",
|
||||
"@types/glob": "7.1.3",
|
||||
"@types/gulp": "4.0.8",
|
||||
"@types/gulp-rename": "2.0.0",
|
||||
"@types/is-url": "1.2.28",
|
||||
"@types/is-url": "1.2.29",
|
||||
"@types/js-yaml": "4.0.1",
|
||||
"@types/jsdom": "16.2.10",
|
||||
"@types/jsonld": "1.5.5",
|
||||
"@types/katex": "0.11.0",
|
||||
"@types/koa": "2.13.1",
|
||||
"@types/koa": "2.13.3",
|
||||
"@types/koa-bodyparser": "4.3.0",
|
||||
"@types/koa-cors": "0.0.0",
|
||||
"@types/koa-favicon": "2.0.19",
|
||||
"@types/koa-logger": "3.1.1",
|
||||
"@types/koa-mount": "4.0.0",
|
||||
"@types/koa-send": "4.1.2",
|
||||
"@types/koa-views": "2.0.4",
|
||||
"@types/koa-views": "7.0.0",
|
||||
"@types/koa__cors": "3.0.2",
|
||||
"@types/koa__multer": "2.0.2",
|
||||
"@types/koa__router": "8.0.4",
|
||||
"@types/markdown-it": "12.0.1",
|
||||
"@types/matter-js": "0.14.11",
|
||||
"@types/matter-js": "0.14.12",
|
||||
"@types/mocha": "8.2.2",
|
||||
"@types/node": "14.14.41",
|
||||
"@types/node": "15.6.1",
|
||||
"@types/node-fetch": "2.5.10",
|
||||
"@types/nodemailer": "6.4.1",
|
||||
"@types/nodemailer": "6.4.2",
|
||||
"@types/nprogress": "0.2.0",
|
||||
"@types/oauth": "0.9.1",
|
||||
"@types/parse5": "6.0.0",
|
||||
@@ -86,12 +86,12 @@
|
||||
"@types/qrcode": "1.4.0",
|
||||
"@types/random-seed": "0.3.3",
|
||||
"@types/ratelimiter": "3.4.1",
|
||||
"@types/redis": "2.8.28",
|
||||
"@types/rename": "1.0.2",
|
||||
"@types/redis": "2.8.29",
|
||||
"@types/rename": "1.0.3",
|
||||
"@types/request-stats": "3.0.0",
|
||||
"@types/rimraf": "3.0.0",
|
||||
"@types/seedrandom": "2.4.28",
|
||||
"@types/sharp": "0.28.0",
|
||||
"@types/sharp": "0.28.2",
|
||||
"@types/sinonjs__fake-timers": "6.0.2",
|
||||
"@types/speakeasy": "2.0.5",
|
||||
"@types/throttle-debounce": "2.1.0",
|
||||
@@ -102,46 +102,46 @@
|
||||
"@types/webpack": "5.28.0",
|
||||
"@types/webpack-stream": "3.2.12",
|
||||
"@types/websocket": "1.0.2",
|
||||
"@types/ws": "7.4.1",
|
||||
"@typescript-eslint/parser": "4.22.0",
|
||||
"@types/ws": "7.4.4",
|
||||
"@typescript-eslint/parser": "4.25.0",
|
||||
"@vue/compiler-sfc": "3.0.11",
|
||||
"abort-controller": "3.0.0",
|
||||
"apexcharts": "3.26.1",
|
||||
"apexcharts": "3.26.3",
|
||||
"autobind-decorator": "2.4.0",
|
||||
"autosize": "4.0.2",
|
||||
"autosize": "4.0.4",
|
||||
"autwh": "0.1.0",
|
||||
"aws-sdk": "2.892.0",
|
||||
"aws-sdk": "2.918.0",
|
||||
"bcryptjs": "2.4.3",
|
||||
"blurhash": "1.1.3",
|
||||
"broadcast-channel": "3.5.3",
|
||||
"bull": "3.22.3",
|
||||
"broadcast-channel": "3.6.0",
|
||||
"bull": "3.22.6",
|
||||
"cafy": "15.2.1",
|
||||
"cbor": "7.0.5",
|
||||
"chalk": "4.1.1",
|
||||
"chart.js": "2.9.4",
|
||||
"cli-highlight": "2.1.11",
|
||||
"commander": "7.2.0",
|
||||
"concurrently": "6.0.2",
|
||||
"concurrently": "6.2.0",
|
||||
"content-disposition": "0.5.3",
|
||||
"core-js": "3.11.0",
|
||||
"core-js": "3.13.1",
|
||||
"crc-32": "1.2.0",
|
||||
"css-loader": "5.2.4",
|
||||
"cssnano": "5.0.1",
|
||||
"css-loader": "5.2.6",
|
||||
"cssnano": "5.0.5",
|
||||
"dateformat": "4.5.1",
|
||||
"diskusage": "1.1.3",
|
||||
"escape-regexp": "0.0.1",
|
||||
"eslint": "7.25.0",
|
||||
"eslint-plugin-vue": "7.9.0",
|
||||
"eslint": "7.27.0",
|
||||
"eslint-plugin-vue": "7.10.0",
|
||||
"eventemitter3": "4.0.7",
|
||||
"feed": "4.2.2",
|
||||
"file-type": "16.3.0",
|
||||
"file-type": "16.5.0",
|
||||
"fluent-ffmpeg": "2.1.2",
|
||||
"glob": "7.1.6",
|
||||
"glob": "7.1.7",
|
||||
"got": "11.8.2",
|
||||
"gulp": "4.0.2",
|
||||
"gulp-cssnano": "2.1.3",
|
||||
"gulp-rename": "2.0.0",
|
||||
"gulp-replace": "1.1.1",
|
||||
"gulp-replace": "1.1.3",
|
||||
"gulp-terser": "2.0.1",
|
||||
"gulp-tslint": "8.1.4",
|
||||
"hard-source-webpack-plugin": "0.13.1",
|
||||
@@ -149,17 +149,17 @@
|
||||
"http-proxy-agent": "4.0.1",
|
||||
"http-signature": "1.3.5",
|
||||
"https-proxy-agent": "5.0.0",
|
||||
"idb-keyval": "5.0.5",
|
||||
"idb-keyval": "5.0.6",
|
||||
"insert-text-at-cursor": "0.3.0",
|
||||
"is-root": "2.1.0",
|
||||
"is-svg": "4.3.1",
|
||||
"js-yaml": "4.1.0",
|
||||
"jsdom": "16.5.3",
|
||||
"jsdom": "16.6.0",
|
||||
"json5": "2.2.0",
|
||||
"json5-loader": "4.0.1",
|
||||
"jsonld": "4.0.1",
|
||||
"jsrsasign": "8.0.20",
|
||||
"katex": "0.13.3",
|
||||
"katex": "0.13.11",
|
||||
"koa": "2.13.1",
|
||||
"koa-bodyparser": "4.3.0",
|
||||
"koa-favicon": "2.1.0",
|
||||
@@ -174,23 +174,24 @@
|
||||
"markdown-it": "12.0.6",
|
||||
"markdown-it-anchor": "7.1.0",
|
||||
"matter-js": "0.17.1",
|
||||
"mfm-js": "0.16.3",
|
||||
"mocha": "8.3.2",
|
||||
"mfm-js": "0.16.4",
|
||||
"misskey-js": "0.0.2",
|
||||
"mocha": "8.4.0",
|
||||
"moji": "0.5.1",
|
||||
"ms": "2.1.3",
|
||||
"multer": "1.4.2",
|
||||
"nested-property": "4.0.0",
|
||||
"node-fetch": "2.6.1",
|
||||
"nodemailer": "6.5.0",
|
||||
"nodemailer": "6.6.1",
|
||||
"object-assign-deep": "0.4.0",
|
||||
"os-utils": "0.0.14",
|
||||
"parse5": "6.0.1",
|
||||
"pg": "8.6.0",
|
||||
"portscanner": "2.2.0",
|
||||
"postcss": "8.2.12",
|
||||
"postcss-loader": "5.2.0",
|
||||
"postcss": "8.3.0",
|
||||
"postcss-loader": "5.3.0",
|
||||
"prismjs": "1.23.0",
|
||||
"probe-image-size": "7.1.0",
|
||||
"probe-image-size": "7.1.1",
|
||||
"promise-limit": "2.7.0",
|
||||
"promise-sequential": "1.1.1",
|
||||
"pug": "3.0.2",
|
||||
@@ -199,7 +200,7 @@
|
||||
"qrcode": "1.4.4",
|
||||
"random-seed": "0.3.0",
|
||||
"ratelimiter": "3.4.1",
|
||||
"re2": "1.15.9",
|
||||
"re2": "1.16.0",
|
||||
"reconnecting-websocket": "4.4.0",
|
||||
"redis": "3.1.2",
|
||||
"redis-lock": "0.1.4",
|
||||
@@ -211,30 +212,31 @@
|
||||
"rimraf": "3.0.2",
|
||||
"rndstr": "1.0.0",
|
||||
"s-age": "1.1.2",
|
||||
"sass": "1.32.11",
|
||||
"sass-loader": "11.0.1",
|
||||
"sass": "1.34.0",
|
||||
"sass-loader": "11.1.1",
|
||||
"seedrandom": "3.0.5",
|
||||
"sharp": "0.28.1",
|
||||
"sharp": "0.28.3",
|
||||
"speakeasy": "2.0.0",
|
||||
"stringz": "2.1.0",
|
||||
"style-loader": "2.0.0",
|
||||
"summaly": "2.4.0",
|
||||
"syslog-pro": "1.0.0",
|
||||
"systeminformation": "5.6.12",
|
||||
"systeminformation": "5.7.4",
|
||||
"syuilo-password-strength": "0.0.1",
|
||||
"textarea-caret": "3.1.0",
|
||||
"three": "0.117.1",
|
||||
"throttle-debounce": "3.0.1",
|
||||
"tinycolor2": "1.4.2",
|
||||
"tmp": "0.2.1",
|
||||
"ts-loader": "9.1.1",
|
||||
"ts-node": "9.1.1",
|
||||
"tsc-alias": "1.2.10",
|
||||
"ts-loader": "9.2.2",
|
||||
"ts-node": "10.0.0",
|
||||
"tsc-alias": "1.2.11",
|
||||
"tsconfig-paths": "3.9.0",
|
||||
"tslint": "6.1.3",
|
||||
"tslint-sonarts": "1.9.0",
|
||||
"twemoji-parser": "13.1.0",
|
||||
"typeorm": "0.2.32",
|
||||
"typescript": "4.2.4",
|
||||
"typescript": "4.3.2",
|
||||
"ulid": "2.3.0",
|
||||
"uuid": "8.3.2",
|
||||
"v-debounce": "0.1.2",
|
||||
@@ -249,13 +251,14 @@
|
||||
"vue-svg-loader": "0.17.0-beta.2",
|
||||
"vuedraggable": "4.0.1",
|
||||
"web-push": "3.4.4",
|
||||
"webpack": "5.35.1",
|
||||
"webpack-cli": "4.6.0",
|
||||
"webpack": "5.38.1",
|
||||
"webpack-cli": "4.7.0",
|
||||
"websocket": "1.0.34",
|
||||
"ws": "7.4.5",
|
||||
"ws": "7.4.6",
|
||||
"xev": "2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@redocly/openapi-core": "1.0.0-beta.44",
|
||||
"@types/chai": "4.2.16",
|
||||
"@types/fluent-ffmpeg": "2.1.17",
|
||||
"chai": "4.3.4",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { defineComponent, PropType } from 'vue';
|
||||
|
||||
type Captcha = {
|
||||
render(container: string | Node, options: {
|
||||
@@ -32,7 +32,7 @@ declare global {
|
||||
export default defineComponent({
|
||||
props: {
|
||||
provider: {
|
||||
type: String,
|
||||
type: String as PropType<CaptchaProvider>,
|
||||
required: true,
|
||||
},
|
||||
sitekey: {
|
||||
@@ -51,19 +51,25 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
computed: {
|
||||
loaded() {
|
||||
return !!window[this.provider as CaptchaProvider];
|
||||
variable(): string {
|
||||
switch (this.provider) {
|
||||
case 'hcaptcha': return 'hcaptcha';
|
||||
case 'recaptcha': return 'grecaptcha';
|
||||
}
|
||||
},
|
||||
src() {
|
||||
loaded(): boolean {
|
||||
return !!window[this.variable];
|
||||
},
|
||||
src(): string {
|
||||
const endpoint = ({
|
||||
hcaptcha: 'https://hcaptcha.com/1',
|
||||
recaptcha: 'https://www.recaptcha.net/recaptcha',
|
||||
} as Record<PropertyKey, unknown>)[this.provider];
|
||||
} as Record<CaptchaProvider, string>)[this.provider];
|
||||
|
||||
return `${typeof endpoint == 'string' ? endpoint : 'about:invalid'}/api.js?render=explicit`;
|
||||
return `${typeof endpoint === 'string' ? endpoint : 'about:invalid'}/api.js?render=explicit`;
|
||||
},
|
||||
captcha() {
|
||||
return window[this.provider as CaptchaProvider] || {} as unknown as Captcha;
|
||||
captcha(): Captcha {
|
||||
return window[this.variable] || {} as unknown as Captcha;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -94,7 +100,7 @@ export default defineComponent({
|
||||
|
||||
methods: {
|
||||
reset() {
|
||||
this.captcha?.reset();
|
||||
if (this.captcha?.reset) this.captcha.reset();
|
||||
},
|
||||
requestRender() {
|
||||
if (this.captcha.render && this.$refs.captcha instanceof Element) {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, h, TransitionGroup } from 'vue';
|
||||
import { defineComponent, h, PropType, TransitionGroup } from 'vue';
|
||||
import MkAd from '@client/components/global/ad.vue';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
items: {
|
||||
type: Array,
|
||||
type: Array as PropType<{ id: string; createdAt: string; _shouldInsertAd_: boolean; }[]>,
|
||||
required: true,
|
||||
},
|
||||
direction: {
|
||||
@@ -22,6 +23,11 @@ export default defineComponent({
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
ad: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
@@ -58,11 +64,7 @@ export default defineComponent({
|
||||
|
||||
if (
|
||||
i != this.items.length - 1 &&
|
||||
new Date(item.createdAt).getDate() != new Date(this.items[i + 1].createdAt).getDate() &&
|
||||
!item._prId_ &&
|
||||
!this.items[i + 1]._prId_ &&
|
||||
!item._featuredId_ &&
|
||||
!this.items[i + 1]._featuredId_
|
||||
new Date(item.createdAt).getDate() != new Date(this.items[i + 1].createdAt).getDate()
|
||||
) {
|
||||
const separator = h('div', {
|
||||
class: 'separator',
|
||||
@@ -86,7 +88,15 @@ export default defineComponent({
|
||||
|
||||
return [el, separator];
|
||||
} else {
|
||||
return el;
|
||||
if (this.ad && item._shouldInsertAd_) {
|
||||
return [h(MkAd, {
|
||||
class: 'a', // advertiseの意(ブロッカー対策)
|
||||
key: item.id + ':ad',
|
||||
prefer: ['horizontal', 'horizontal-big'],
|
||||
}), el];
|
||||
} else {
|
||||
return el;
|
||||
}
|
||||
}
|
||||
}));
|
||||
},
|
||||
@@ -95,6 +105,10 @@ export default defineComponent({
|
||||
|
||||
<style lang="scss">
|
||||
.sqadhkmv {
|
||||
> *:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> *:not(:last-child) {
|
||||
margin-bottom: var(--margin);
|
||||
}
|
||||
|
||||
@@ -81,12 +81,16 @@ export default defineComponent({
|
||||
getMenu() {
|
||||
return [{
|
||||
text: this.$ts.rename,
|
||||
icon: faICursor,
|
||||
icon: 'fas fa-i-cursor',
|
||||
action: this.rename
|
||||
}, {
|
||||
text: this.file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,
|
||||
icon: this.file.isSensitive ? 'fas fa-eye' : 'fas fa-eye-slash',
|
||||
action: this.toggleSensitive
|
||||
}, {
|
||||
text: this.$ts.describeFile,
|
||||
icon: 'fas fa-i-cursor',
|
||||
action: this.describe
|
||||
}, null, {
|
||||
text: this.$ts.copyUrl,
|
||||
icon: 'fas fa-link',
|
||||
@@ -150,6 +154,26 @@ export default defineComponent({
|
||||
});
|
||||
},
|
||||
|
||||
describe() {
|
||||
os.popup(import('@client/components/media-caption.vue'), {
|
||||
title: this.$ts.describeFile,
|
||||
input: {
|
||||
placeholder: this.$ts.inputNewDescription,
|
||||
default: this.file.comment !== null ? this.file.comment : '',
|
||||
},
|
||||
image: this.file
|
||||
}, {
|
||||
done: result => {
|
||||
if (!result || result.canceled) return;
|
||||
let comment = result.result;
|
||||
os.api('drive/files/update', {
|
||||
fileId: this.file.id,
|
||||
comment: comment.length == 0 ? null : comment
|
||||
});
|
||||
}
|
||||
}, 'closed');
|
||||
},
|
||||
|
||||
toggleSensitive() {
|
||||
os.api('drive/files/update', {
|
||||
fileId: this.file.id,
|
||||
|
||||
@@ -247,7 +247,7 @@ export default defineComponent({
|
||||
}
|
||||
}, null, {
|
||||
text: this.$ts.rename,
|
||||
icon: faICursor,
|
||||
icon: 'fas fa-i-cursor',
|
||||
action: this.rename
|
||||
}, null, {
|
||||
text: this.$ts.delete,
|
||||
|
||||
@@ -139,7 +139,7 @@ export default defineComponent({
|
||||
});
|
||||
}
|
||||
|
||||
this.connection = os.stream.useSharedConnection('drive');
|
||||
this.connection = os.stream.useChannel('drive');
|
||||
|
||||
this.connection.on('fileCreated', this.onStreamDriveFileCreated);
|
||||
this.connection.on('fileUpdated', this.onStreamDriveFileUpdated);
|
||||
@@ -301,7 +301,7 @@ export default defineComponent({
|
||||
}
|
||||
}).then(({ canceled, result: url }) => {
|
||||
if (canceled) return;
|
||||
os.api('drive/files/upload_from_url', {
|
||||
os.api('drive/files/upload-from-url', {
|
||||
url: url,
|
||||
folderId: this.folder ? this.folder.id : undefined
|
||||
});
|
||||
@@ -614,7 +614,7 @@ export default defineComponent({
|
||||
type: 'label'
|
||||
}, this.folder ? {
|
||||
text: this.$ts.renameFolder,
|
||||
icon: faICursor,
|
||||
icon: 'fas fa-i-cursor',
|
||||
action: () => { this.renameFolder(this.folder); }
|
||||
} : undefined, this.folder ? {
|
||||
text: this.$ts.deleteFolder,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<MkModal ref="modal" :manual-showing="manualShowing" :src="src" @click="$refs.modal.close()" @opening="opening" @close="$emit('close')" @closed="$emit('closed')">
|
||||
<MkModal ref="modal" :manual-showing="manualShowing" :src="src" :front="true" @click="$refs.modal.close()" @opening="opening" @close="$emit('close')" @closed="$emit('closed')">
|
||||
<MkEmojiPicker :show-pinned="showPinned" :as-reaction-picker="asReactionPicker" @chosen="chosen" ref="picker"/>
|
||||
</MkModal>
|
||||
</template>
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
class="_button"
|
||||
@click="chosen(emoji, $event)"
|
||||
tabindex="0"
|
||||
:key="emoji"
|
||||
>
|
||||
<MkEmoji :emoji="emoji" :normal="true"/>
|
||||
</button>
|
||||
@@ -104,7 +105,7 @@ export default defineComponent({
|
||||
return {
|
||||
emojilist: markRaw(emojilist),
|
||||
getStaticImageUrl,
|
||||
pinned: this.$store.state.reactions,
|
||||
pinned: this.$store.reactiveState.reactions,
|
||||
width: this.asReactionPicker ? this.$store.state.reactionPickerWidth : 3,
|
||||
height: this.asReactionPicker ? this.$store.state.reactionPickerHeight : 2,
|
||||
big: this.asReactionPicker ? isDeviceTouch : false,
|
||||
|
||||
@@ -71,7 +71,7 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.connection = os.stream.useSharedConnection('main');
|
||||
this.connection = os.stream.useChannel('main');
|
||||
|
||||
this.connection.on('follow', this.onFollowChange);
|
||||
this.connection.on('unfollow', this.onFollowChange);
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<XModalWindow ref="dialog"
|
||||
:width="370"
|
||||
:height="400"
|
||||
@close="$refs.dialog.close()"
|
||||
@closed="$emit('closed')"
|
||||
>
|
||||
<template #header>{{ $ts.forgotPassword }}</template>
|
||||
|
||||
<form class="_monolithic_" @submit.prevent="onSubmit" v-if="$instance.enableEmail">
|
||||
<div class="_section">
|
||||
<MkInput v-model:value="username" type="text" pattern="^[a-zA-Z0-9_]+$" spellcheck="false" autofocus required>
|
||||
<span>{{ $ts.username }}</span>
|
||||
<template #prefix>@</template>
|
||||
</MkInput>
|
||||
|
||||
<MkInput v-model:value="email" type="email" spellcheck="false" required>
|
||||
<span>{{ $ts.emailAddress }}</span>
|
||||
<template #desc>{{ $ts._forgotPassword.enterEmail }}</template>
|
||||
</MkInput>
|
||||
|
||||
<MkButton type="submit" :disabled="processing" primary style="margin: 0 auto;">{{ $ts.send }}</MkButton>
|
||||
</div>
|
||||
<div class="_section">
|
||||
<MkA to="/about" class="_link">{{ $ts._forgotPassword.ifNoEmail }}</MkA>
|
||||
</div>
|
||||
</form>
|
||||
<div v-else>
|
||||
{{ $ts._forgotPassword.contactAdmin }}
|
||||
</div>
|
||||
</XModalWindow>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import XModalWindow from '@client/components/ui/modal-window.vue';
|
||||
import MkButton from '@client/components/ui/button.vue';
|
||||
import MkInput from '@client/components/ui/input.vue';
|
||||
import * as os from '@client/os';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
XModalWindow,
|
||||
MkButton,
|
||||
MkInput,
|
||||
},
|
||||
|
||||
emits: ['done', 'closed'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
username: '',
|
||||
email: '',
|
||||
processing: false,
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
async onSubmit() {
|
||||
this.processing = true;
|
||||
await os.apiWithDialog('request-reset-password', {
|
||||
username: this.username,
|
||||
email: this.email,
|
||||
});
|
||||
|
||||
this.$emit('done');
|
||||
this.$refs.dialog.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,200 @@
|
||||
<template>
|
||||
<div class="qiivuoyo" v-if="ad">
|
||||
<div class="main" :class="ad.place" v-if="!showMenu">
|
||||
<a :href="ad.url" target="_blank">
|
||||
<img :src="ad.imageUrl">
|
||||
<button class="_button menu" @click.prevent.stop="toggleMenu"><span class="fas fa-info-circle"></span></button>
|
||||
</a>
|
||||
</div>
|
||||
<div class="menu" v-else>
|
||||
<div class="body">
|
||||
<div>Ads by {{ host }}</div>
|
||||
<!--<MkButton class="button" primary>{{ $ts._ad.like }}</MkButton>-->
|
||||
<MkButton v-if="ad.ratio !== 0" class="button" @click="reduceFrequency">{{ $ts._ad.reduceFrequencyOfThisAd }}</MkButton>
|
||||
<button class="_textButton" @click="toggleMenu">{{ $ts._ad.back }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { Instance, instance } from '@client/instance';
|
||||
import { host } from '@client/config';
|
||||
import MkButton from '@client/components/ui/button.vue';
|
||||
import { defaultStore } from '@client/store';
|
||||
import * as os from '@client/os';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
MkButton
|
||||
},
|
||||
|
||||
props: {
|
||||
prefer: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
specify: {
|
||||
type: Object,
|
||||
required: false
|
||||
},
|
||||
},
|
||||
|
||||
setup(props) {
|
||||
const showMenu = ref(false);
|
||||
const toggleMenu = () => {
|
||||
showMenu.value = !showMenu.value;
|
||||
};
|
||||
|
||||
const choseAd = (): Instance['ads'][number] | null => {
|
||||
if (props.specify) {
|
||||
return props.specify as Instance['ads'][number];
|
||||
}
|
||||
|
||||
const allAds = instance.ads.map(ad => defaultStore.state.mutedAds.includes(ad.id) ? {
|
||||
...ad,
|
||||
ratio: 0
|
||||
} : ad);
|
||||
|
||||
let ads = allAds.filter(ad => props.prefer.includes(ad.place));
|
||||
|
||||
if (ads.length === 0) {
|
||||
ads = allAds.filter(ad => ad.place === 'square');
|
||||
}
|
||||
|
||||
const lowPriorityAds = ads.filter(ad => ad.ratio === 0);
|
||||
ads = ads.filter(ad => ad.ratio !== 0);
|
||||
|
||||
if (ads.length === 0) {
|
||||
if (lowPriorityAds.length !== 0) {
|
||||
return lowPriorityAds[Math.floor(Math.random() * lowPriorityAds.length)];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const totalFactor = ads.reduce((a, b) => a + b.ratio, 0);
|
||||
const r = Math.random() * totalFactor;
|
||||
|
||||
let stackedFactor = 0;
|
||||
for (const ad of ads) {
|
||||
if (r >= stackedFactor && r <= stackedFactor + ad.ratio) {
|
||||
return ad;
|
||||
} else {
|
||||
stackedFactor += ad.ratio;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const chosen = ref(choseAd());
|
||||
|
||||
const reduceFrequency = () => {
|
||||
if (chosen.value == null) return;
|
||||
if (defaultStore.state.mutedAds.includes(chosen.value.id)) return;
|
||||
defaultStore.push('mutedAds', chosen.value.id);
|
||||
os.success();
|
||||
chosen.value = choseAd();
|
||||
showMenu.value = false;
|
||||
};
|
||||
|
||||
return {
|
||||
ad: chosen,
|
||||
showMenu,
|
||||
toggleMenu,
|
||||
host,
|
||||
reduceFrequency,
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.qiivuoyo {
|
||||
background-size: auto auto;
|
||||
background-image: repeating-linear-gradient(45deg, transparent, transparent 8px, var(--ad) 8px, var(--ad) 14px );
|
||||
|
||||
> .main {
|
||||
text-align: center;
|
||||
|
||||
> a {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
vertical-align: bottom;
|
||||
|
||||
&:hover {
|
||||
> img {
|
||||
filter: contrast(120%);
|
||||
}
|
||||
}
|
||||
|
||||
> img {
|
||||
display: block;
|
||||
object-fit: contain;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
> .menu {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
background: var(--panel);
|
||||
}
|
||||
}
|
||||
|
||||
&.square {
|
||||
> a ,
|
||||
> a > img {
|
||||
max-width: min(300px, 100%);
|
||||
max-height: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
&.horizontal {
|
||||
padding: 8px;
|
||||
|
||||
> a ,
|
||||
> a > img {
|
||||
max-width: min(600px, 100%);
|
||||
max-height: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
&.horizontal-big {
|
||||
padding: 8px;
|
||||
|
||||
> a ,
|
||||
> a > img {
|
||||
max-width: min(600px, 100%);
|
||||
max-height: 250px;
|
||||
}
|
||||
}
|
||||
|
||||
&.vertical {
|
||||
> a ,
|
||||
> a > img {
|
||||
max-width: min(100px, 100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .menu {
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
|
||||
> .body {
|
||||
padding: 8px;
|
||||
margin: 0 auto;
|
||||
max-width: 400px;
|
||||
border: solid 1px var(--divider);
|
||||
|
||||
> .button {
|
||||
margin: 8px auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -113,8 +113,6 @@ export default defineComponent({
|
||||
> .icon {
|
||||
padding-left: 2px;
|
||||
font-size: .9em;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
> .self {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<MkModal ref="modal" @click="$refs.modal.close()" @closed="$emit('closed')">
|
||||
<div class="xubzgfga">
|
||||
<header>{{ image.name }}</header>
|
||||
<img :src="image.url" :alt="image.name" :title="image.name" @click="$refs.modal.close()"/>
|
||||
<img :src="image.url" :alt="image.comment" :title="image.comment" @click="$refs.modal.close()"/>
|
||||
<footer>
|
||||
<span>{{ image.type }}</span>
|
||||
<span>{{ bytes(image.size) }}</span>
|
||||
|
||||
@@ -12,8 +12,10 @@ import url from './global/url.vue';
|
||||
import i18n from './global/i18n';
|
||||
import loading from './global/loading.vue';
|
||||
import error from './global/error.vue';
|
||||
import ad from './global/ad.vue';
|
||||
|
||||
export default function(app: App) {
|
||||
app.component('I18n', i18n);
|
||||
app.component('Mfm', mfm);
|
||||
app.component('MkA', a);
|
||||
app.component('MkAcct', acct);
|
||||
@@ -25,5 +27,5 @@ export default function(app: App) {
|
||||
app.component('MkUrl', url);
|
||||
app.component('MkLoading', loading);
|
||||
app.component('MkError', error);
|
||||
app.component('I18n', i18n);
|
||||
app.component('MkAd', ad);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
<template>
|
||||
<MkModal ref="modal" @click="done(true)" @closed="$emit('closed')">
|
||||
<div class="container">
|
||||
<div class="fullwidth top-caption">
|
||||
<div class="mk-dialog">
|
||||
<header v-if="title"><Mfm :text="title"/></header>
|
||||
<textarea autofocus v-model="inputValue" :placeholder="input.placeholder" @keydown="onInputKeydown"></textarea>
|
||||
<div class="buttons" v-if="(showOkButton || showCancelButton)">
|
||||
<MkButton inline @click="ok" primary>{{ $ts.ok }}</MkButton>
|
||||
<MkButton inline @click="cancel" >{{ $ts.cancel }}</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hdrwpsaf fullwidth">
|
||||
<header>{{ image.name }}</header>
|
||||
<img :src="image.url" :alt="image.comment" :title="image.comment" @click="$refs.modal.close()"/>
|
||||
<footer>
|
||||
<span>{{ image.type }}</span>
|
||||
<span>{{ bytes(image.size) }}</span>
|
||||
<span v-if="image.properties && image.properties.width">{{ number(image.properties.width) }}px × {{ number(image.properties.height) }}px</span>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</MkModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import MkModal from '@client/components/ui/modal.vue';
|
||||
import MkButton from '@client/components/ui/button.vue';
|
||||
import bytes from '@client/filters/bytes';
|
||||
import number from '@client/filters/number';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
MkModal,
|
||||
MkButton,
|
||||
},
|
||||
|
||||
props: {
|
||||
image: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
input: {
|
||||
required: true
|
||||
},
|
||||
showOkButton: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showCancelButton: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
cancelableByBgClick: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
},
|
||||
|
||||
emits: ['done', 'closed'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
inputValue: this.input.default ? this.input.default : null
|
||||
};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
document.addEventListener('keydown', this.onKeydown);
|
||||
},
|
||||
|
||||
beforeUnmount() {
|
||||
document.removeEventListener('keydown', this.onKeydown);
|
||||
},
|
||||
|
||||
methods: {
|
||||
bytes,
|
||||
number,
|
||||
|
||||
done(canceled, result?) {
|
||||
this.$emit('done', { canceled, result });
|
||||
this.$refs.modal.close();
|
||||
},
|
||||
|
||||
async ok() {
|
||||
if (!this.showOkButton) return;
|
||||
|
||||
const result = this.inputValue;
|
||||
this.done(false, result);
|
||||
},
|
||||
|
||||
cancel() {
|
||||
this.done(true);
|
||||
},
|
||||
|
||||
onBgClick() {
|
||||
if (this.cancelableByBgClick) {
|
||||
this.cancel();
|
||||
}
|
||||
},
|
||||
|
||||
onKeydown(e) {
|
||||
if (e.which === 27) { // ESC
|
||||
this.cancel();
|
||||
}
|
||||
},
|
||||
|
||||
onInputKeydown(e) {
|
||||
if (e.which === 13) { // Enter
|
||||
if (e.ctrlKey) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
flex-direction: row;
|
||||
}
|
||||
@media (max-width: 850px) {
|
||||
.container {
|
||||
flex-direction: column;
|
||||
}
|
||||
.top-caption {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
}
|
||||
.fullwidth {
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
.mk-dialog {
|
||||
position: relative;
|
||||
padding: 32px;
|
||||
min-width: 320px;
|
||||
max-width: 480px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
background: var(--panel);
|
||||
border-radius: var(--radius);
|
||||
margin: auto;
|
||||
|
||||
> header {
|
||||
margin: 0 0 8px 0;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
> .buttons {
|
||||
margin-top: 16px;
|
||||
|
||||
> * {
|
||||
margin: 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
> textarea {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
padding: 0 24px;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
color: var(--fg);
|
||||
font-family: inherit;
|
||||
max-width: 100%;
|
||||
min-width: 100%;
|
||||
min-height: 90px;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
.hdrwpsaf {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
|
||||
> header,
|
||||
> footer {
|
||||
align-self: center;
|
||||
display: inline-block;
|
||||
padding: 6px 9px;
|
||||
font-size: 90%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
border-radius: 6px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
> header {
|
||||
margin-bottom: 8px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
> img {
|
||||
display: block;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
object-fit: contain;
|
||||
width: 100%;
|
||||
cursor: zoom-out;
|
||||
image-orientation: from-image;
|
||||
}
|
||||
|
||||
> footer {
|
||||
margin-top: 8px;
|
||||
opacity: 0.8;
|
||||
|
||||
> span + span {
|
||||
margin-left: 0.5em;
|
||||
padding-left: 0.5em;
|
||||
border-left: solid 1px rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="qjewsnkg" v-if="hide" @click="hide = false">
|
||||
<ImgWithBlurhash class="bg" :hash="image.blurhash" :title="image.name"/>
|
||||
<ImgWithBlurhash class="bg" :hash="image.blurhash" :title="image.comment" :alt="image.comment"/>
|
||||
<div class="text">
|
||||
<div>
|
||||
<b><i class="fas fa-exclamation-triangle"></i> {{ $ts.sensitive }}</b>
|
||||
@@ -9,15 +9,15 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="gqnyydlz" :style="{ background: color }" v-else>
|
||||
<i class="fas fa-eye-slash" @click="hide = true"></i>
|
||||
<a
|
||||
:href="image.url"
|
||||
:title="image.name"
|
||||
@click.prevent="onClick"
|
||||
>
|
||||
<ImgWithBlurhash :hash="image.blurhash" :src="url" :alt="image.name" :title="image.name" :cover="false"/>
|
||||
<ImgWithBlurhash :hash="image.blurhash" :src="url" :alt="image.comment" :title="image.comment" :cover="false"/>
|
||||
<div class="gif" v-if="image.type === 'image/gif'">GIF</div>
|
||||
</a>
|
||||
<i class="fas fa-eye-slash" @click="hide = true"></i>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="yohlumlk">
|
||||
<div class="yohlumlk" v-size="{ min: [350, 500] }">
|
||||
<MkAvatar class="avatar" :user="note.user"/>
|
||||
<div class="main">
|
||||
<XNoteHeader class="header" :note="note" :mini="true"/>
|
||||
@@ -50,18 +50,19 @@ export default defineComponent({
|
||||
display: flex;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
overflow: clip;
|
||||
font-size: 0.95em;
|
||||
|
||||
> .avatar {
|
||||
|
||||
@media (min-width: 350px) {
|
||||
&.min-width_350px {
|
||||
> .avatar {
|
||||
margin: 0 10px 0 0;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 500px) {
|
||||
&.min-width_500px {
|
||||
> .avatar {
|
||||
margin: 0 12px 0 0;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</MkButton>
|
||||
</div>
|
||||
|
||||
<XList ref="notes" :items="notes" v-slot="{ item: note }" :direction="reversed ? 'up' : 'down'" :reversed="reversed" :no-gap="noGap">
|
||||
<XList ref="notes" :items="notes" v-slot="{ item: note }" :direction="reversed ? 'up' : 'down'" :reversed="reversed" :no-gap="noGap" :ad="true">
|
||||
<XNote :note="note" class="_block" @update:note="updated(note, $event)" :key="note._featuredId_ || note._prId_ || note.id"/>
|
||||
</XList>
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ export default defineComponent({
|
||||
|
||||
this.readObserver.observe(this.$el);
|
||||
|
||||
this.connection = os.stream.useSharedConnection('main');
|
||||
this.connection = os.stream.useChannel('main');
|
||||
this.connection.on('readAllNotifications', () => this.readObserver.unobserve(this.$el));
|
||||
}
|
||||
},
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
<XNotification v-else :notification="notification" :with-time="true" :full="true" class="_panel notification" :key="notification.id"/>
|
||||
</XList>
|
||||
|
||||
<button class="_buttonPrimary" v-appear="$store.state.enableInfiniteScroll ? fetchMore : null" @click="fetchMore" v-show="more" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }">
|
||||
<MkButton primary style="margin: var(--margin) auto;" v-appear="$store.state.enableInfiniteScroll ? fetchMore : null" @click="fetchMore" v-show="more" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }">
|
||||
<template v-if="!moreFetching">{{ $ts.loadMore }}</template>
|
||||
<template v-if="moreFetching"><MkLoading inline/></template>
|
||||
</button>
|
||||
</MkButton>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
@@ -28,12 +28,14 @@ import XList from './date-separated-list.vue';
|
||||
import XNote from './note.vue';
|
||||
import { notificationTypes } from '../../types';
|
||||
import * as os from '@client/os';
|
||||
import MkButton from '@client/components/ui/button.vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
XNotification,
|
||||
XList,
|
||||
XNote,
|
||||
MkButton,
|
||||
},
|
||||
|
||||
mixins: [
|
||||
@@ -87,7 +89,7 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.connection = os.stream.useSharedConnection('main');
|
||||
this.connection = os.stream.useChannel('main');
|
||||
this.connection.on('notification', this.onNotification);
|
||||
},
|
||||
|
||||
|
||||
@@ -89,16 +89,41 @@ export default defineComponent({
|
||||
file.name = result;
|
||||
});
|
||||
},
|
||||
|
||||
async describe(file) {
|
||||
os.popup(import("@client/components/media-caption.vue"), {
|
||||
title: this.$ts.describeFile,
|
||||
input: {
|
||||
placeholder: this.$ts.inputNewDescription,
|
||||
default: file.comment !== null ? file.comment : "",
|
||||
},
|
||||
image: file
|
||||
}, {
|
||||
done: result => {
|
||||
if (!result || result.canceled) return;
|
||||
let comment = result.result;
|
||||
os.api('drive/files/update', {
|
||||
fileId: file.id,
|
||||
comment: comment.length == 0 ? null : comment
|
||||
});
|
||||
}
|
||||
}, 'closed');
|
||||
},
|
||||
|
||||
showFileMenu(file, ev: MouseEvent) {
|
||||
if (this.menu) return;
|
||||
this.menu = os.modalMenu([{
|
||||
text: this.$ts.renameFile,
|
||||
icon: faICursor,
|
||||
icon: 'fas fa-i-cursor',
|
||||
action: () => { this.rename(file) }
|
||||
}, {
|
||||
text: file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,
|
||||
icon: file.isSensitive ? 'fas fa-eye-slash' : 'fas fa-eye',
|
||||
action: () => { this.toggleSensitive(file) }
|
||||
}, {
|
||||
text: this.$ts.describeFile,
|
||||
icon: 'fas fa-i-cursor',
|
||||
action: () => { this.describe(file) }
|
||||
}, {
|
||||
text: this.$ts.attachCancel,
|
||||
icon: 'fas fa-times-circle',
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<MkInput v-model:value="password" type="password" :with-password-toggle="true" v-if="!user || user && !user.usePasswordLessLogin" required>
|
||||
<span>{{ $ts.password }}</span>
|
||||
<template #prefix><i class="fas fa-lock"></i></template>
|
||||
<template #desc><button class="_textButton" @click="resetPassword">{{ $ts.forgotPassword }}</button></template>
|
||||
</MkInput>
|
||||
<MkButton type="submit" primary :disabled="signing" style="margin: 0 auto;">{{ signing ? $ts.loggingIn : $ts.login }}</MkButton>
|
||||
</div>
|
||||
@@ -49,8 +50,8 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { toUnicode } from 'punycode/';
|
||||
import MkButton from './ui/button.vue';
|
||||
import MkInput from './ui/input.vue';
|
||||
import MkButton from '@client/components/ui/button.vue';
|
||||
import MkInput from '@client/components/ui/input.vue';
|
||||
import { apiUrl, host } from '@client/config';
|
||||
import { byteify, hexify } from '@client/scripts/2fa';
|
||||
import * as os from '@client/os';
|
||||
@@ -197,6 +198,11 @@ export default defineComponent({
|
||||
this.signing = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
resetPassword() {
|
||||
os.popup(import('@client/components/forgot-password.vue'), {}, {
|
||||
}, 'closed');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -92,33 +92,33 @@ export default defineComponent({
|
||||
this.query = {
|
||||
antennaId: this.antenna
|
||||
};
|
||||
this.connection = os.stream.connectToChannel('antenna', {
|
||||
this.connection = os.stream.useChannel('antenna', {
|
||||
antennaId: this.antenna
|
||||
});
|
||||
this.connection.on('note', prepend);
|
||||
} else if (this.src == 'home') {
|
||||
endpoint = 'notes/timeline';
|
||||
this.connection = os.stream.useSharedConnection('homeTimeline');
|
||||
this.connection = os.stream.useChannel('homeTimeline');
|
||||
this.connection.on('note', prepend);
|
||||
|
||||
this.connection2 = os.stream.useSharedConnection('main');
|
||||
this.connection2 = os.stream.useChannel('main');
|
||||
this.connection2.on('follow', onChangeFollowing);
|
||||
this.connection2.on('unfollow', onChangeFollowing);
|
||||
} else if (this.src == 'local') {
|
||||
endpoint = 'notes/local-timeline';
|
||||
this.connection = os.stream.useSharedConnection('localTimeline');
|
||||
this.connection = os.stream.useChannel('localTimeline');
|
||||
this.connection.on('note', prepend);
|
||||
} else if (this.src == 'social') {
|
||||
endpoint = 'notes/hybrid-timeline';
|
||||
this.connection = os.stream.useSharedConnection('hybridTimeline');
|
||||
this.connection = os.stream.useChannel('hybridTimeline');
|
||||
this.connection.on('note', prepend);
|
||||
} else if (this.src == 'global') {
|
||||
endpoint = 'notes/global-timeline';
|
||||
this.connection = os.stream.useSharedConnection('globalTimeline');
|
||||
this.connection = os.stream.useChannel('globalTimeline');
|
||||
this.connection.on('note', prepend);
|
||||
} else if (this.src == 'mentions') {
|
||||
endpoint = 'notes/mentions';
|
||||
this.connection = os.stream.useSharedConnection('main');
|
||||
this.connection = os.stream.useChannel('main');
|
||||
this.connection.on('mention', prepend);
|
||||
} else if (this.src == 'directs') {
|
||||
endpoint = 'notes/mentions';
|
||||
@@ -130,14 +130,14 @@ export default defineComponent({
|
||||
prepend(note);
|
||||
}
|
||||
};
|
||||
this.connection = os.stream.useSharedConnection('main');
|
||||
this.connection = os.stream.useChannel('main');
|
||||
this.connection.on('mention', onNote);
|
||||
} else if (this.src == 'list') {
|
||||
endpoint = 'notes/user-list-timeline';
|
||||
this.query = {
|
||||
listId: this.list
|
||||
};
|
||||
this.connection = os.stream.connectToChannel('userList', {
|
||||
this.connection = os.stream.useChannel('userList', {
|
||||
listId: this.list
|
||||
});
|
||||
this.connection.on('note', prepend);
|
||||
@@ -148,7 +148,7 @@ export default defineComponent({
|
||||
this.query = {
|
||||
channelId: this.channel
|
||||
};
|
||||
this.connection = os.stream.connectToChannel('channel', {
|
||||
this.connection = os.stream.useChannel('channel', {
|
||||
channelId: this.channel
|
||||
});
|
||||
this.connection.on('note', prepend);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<transition :name="$store.state.animation ? popup ? 'modal-popup' : 'modal' : ''" :duration="$store.state.animation ? popup ? 500 : 300 : 0" appear @after-leave="onClosed" @enter="$emit('opening')" @after-enter="childRendered">
|
||||
<div v-show="manualShowing != null ? manualShowing : showing" class="mk-modal" v-hotkey.global="keymap" :style="{ pointerEvents: (manualShowing != null ? manualShowing : showing) ? 'auto' : 'none', '--transformOrigin': transformOrigin }">
|
||||
<div v-show="manualShowing != null ? manualShowing : showing" class="qzhlnise" :class="{ front }" v-hotkey.global="keymap" :style="{ pointerEvents: (manualShowing != null ? manualShowing : showing) ? 'auto' : 'none', '--transformOrigin': transformOrigin }">
|
||||
<div class="bg _modalBg" @click="onBgClick" @contextmenu.prevent.stop="() => {}"></div>
|
||||
<div class="content" :class="{ popup, fixed, top: position === 'top' }" @click.self="onBgClick" ref="content">
|
||||
<slot></slot>
|
||||
@@ -41,6 +41,11 @@ export default defineComponent({
|
||||
},
|
||||
position: {
|
||||
required: false
|
||||
},
|
||||
front: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
emits: ['opening', 'click', 'esc', 'close', 'closed'],
|
||||
@@ -224,7 +229,7 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
.mk-modal {
|
||||
.qzhlnise {
|
||||
> .bg {
|
||||
z-index: 10000;
|
||||
}
|
||||
@@ -269,5 +274,19 @@ export default defineComponent({
|
||||
position: fixed;
|
||||
}
|
||||
}
|
||||
|
||||
&.front {
|
||||
> .bg {
|
||||
z-index: 20000;
|
||||
}
|
||||
|
||||
> .content:not(.popup) {
|
||||
z-index: 20000;
|
||||
}
|
||||
|
||||
> .content.popup {
|
||||
z-index: 20000;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -8,33 +8,35 @@
|
||||
@closed="$emit('closed')"
|
||||
>
|
||||
<template #header>{{ $ts.selectUser }}</template>
|
||||
<div class="tbhwbxda _section">
|
||||
<div class="inputs">
|
||||
<MkInput v-model:value="username" class="input" @update:value="search" ref="username"><span>{{ $ts.username }}</span><template #prefix>@</template></MkInput>
|
||||
<MkInput v-model:value="host" class="input" @update:value="search"><span>{{ $ts.host }}</span><template #prefix>@</template></MkInput>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tbhwbxda _section result" v-if="username != '' || host != ''" :class="{ hit: users.length > 0 }">
|
||||
<div class="users" v-if="users.length > 0">
|
||||
<div class="user" v-for="user in users" :key="user.id" :class="{ selected: selected && selected.id === user.id }" @click="selected = user" @dblclick="ok()">
|
||||
<MkAvatar :user="user" class="avatar" :show-indicator="true"/>
|
||||
<div class="body">
|
||||
<MkUserName :user="user" class="name"/>
|
||||
<MkAcct :user="user" class="acct"/>
|
||||
</div>
|
||||
<div class="tbhwbxda _monolithic_">
|
||||
<div class="_section">
|
||||
<div class="inputs">
|
||||
<MkInput v-model:value="username" class="input" @update:value="search" ref="username"><span>{{ $ts.username }}</span><template #prefix>@</template></MkInput>
|
||||
<MkInput v-model:value="host" class="input" @update:value="search"><span>{{ $ts.host }}</span><template #prefix>@</template></MkInput>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="empty">
|
||||
<span>{{ $ts.noUsers }}</span>
|
||||
<div class="_section result" v-if="username != '' || host != ''" :class="{ hit: users.length > 0 }">
|
||||
<div class="users" v-if="users.length > 0">
|
||||
<div class="user" v-for="user in users" :key="user.id" :class="{ selected: selected && selected.id === user.id }" @click="selected = user" @dblclick="ok()">
|
||||
<MkAvatar :user="user" class="avatar" :show-indicator="true"/>
|
||||
<div class="body">
|
||||
<MkUserName :user="user" class="name"/>
|
||||
<MkAcct :user="user" class="acct"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="empty">
|
||||
<span>{{ $ts.noUsers }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tbhwbxda _section recent" v-if="username == '' && host == ''">
|
||||
<div class="users">
|
||||
<div class="user" v-for="user in recentUsers" :key="user.id" :class="{ selected: selected && selected.id === user.id }" @click="selected = user" @dblclick="ok()">
|
||||
<MkAvatar :user="user" class="avatar" :show-indicator="true"/>
|
||||
<div class="body">
|
||||
<MkUserName :user="user" class="name"/>
|
||||
<MkAcct :user="user" class="acct"/>
|
||||
<div class="_section recent" v-if="username == '' && host == ''">
|
||||
<div class="users">
|
||||
<div class="user" v-for="user in recentUsers" :key="user.id" :class="{ selected: selected && selected.id === user.id }" @click="selected = user" @dblclick="ok()">
|
||||
<MkAvatar :user="user" class="avatar" :show-indicator="true"/>
|
||||
<div class="body">
|
||||
<MkUserName :user="user" class="name"/>
|
||||
<MkAcct :user="user" class="acct"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -122,76 +124,78 @@ export default defineComponent({
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.tbhwbxda {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
|
||||
&.result.hit {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&.recent {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
> .inputs {
|
||||
> .input {
|
||||
display: inline-block;
|
||||
width: 50%;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
> .users {
|
||||
flex: 1;
|
||||
> ._section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
padding: 8px 0;
|
||||
height: 100%;
|
||||
|
||||
> .user {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px var(--root-margin);
|
||||
font-size: 14px;
|
||||
&.result.hit {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--X7);
|
||||
&.recent {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
> .inputs {
|
||||
> .input {
|
||||
display: inline-block;
|
||||
width: 50%;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
}
|
||||
> .users {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
padding: 8px 0;
|
||||
|
||||
> * {
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
> .user {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px var(--root-margin);
|
||||
font-size: 14px;
|
||||
|
||||
> .avatar {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
}
|
||||
|
||||
> .body {
|
||||
padding: 0 8px;
|
||||
min-width: 0;
|
||||
|
||||
> .name {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
&:hover {
|
||||
background: var(--X7);
|
||||
}
|
||||
|
||||
> .acct {
|
||||
opacity: 0.5;
|
||||
&.selected {
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
> * {
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
> .avatar {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
}
|
||||
|
||||
> .body {
|
||||
padding: 0 8px;
|
||||
min-width: 0;
|
||||
|
||||
> .name {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
> .acct {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .empty {
|
||||
opacity: 0.7;
|
||||
text-align: center;
|
||||
> .empty {
|
||||
opacity: 0.7;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
+1
-7
@@ -163,8 +163,6 @@ fetchInstance().then(() => {
|
||||
initializeSw();
|
||||
});
|
||||
|
||||
stream.init($i);
|
||||
|
||||
const app = createApp(await (
|
||||
window.location.search === '?zen' ? import('@client/ui/zen.vue') :
|
||||
!$i ? import('@client/ui/visitor.vue') :
|
||||
@@ -296,7 +294,7 @@ if ($i) {
|
||||
}
|
||||
}
|
||||
|
||||
const main = stream.useSharedConnection('main', 'System');
|
||||
const main = stream.useChannel('main', null, 'System');
|
||||
|
||||
// 自分の情報が更新されたとき
|
||||
main.on('meUpdated', i => {
|
||||
@@ -358,10 +356,6 @@ if ($i) {
|
||||
sound.play('channel');
|
||||
});
|
||||
|
||||
main.on('readAllAnnouncements', () => {
|
||||
updateAccount({ hasUnreadAnnouncement: false });
|
||||
});
|
||||
|
||||
// トークンが再生成されたとき
|
||||
// このままではMisskeyが利用できないので強制的にサインアウトさせる
|
||||
main.on('myTokenRegenerated', () => {
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
import { computed, reactive } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { api } from './os';
|
||||
|
||||
// TODO: 他のタブと永続化されたstateを同期
|
||||
|
||||
type Instance = {
|
||||
emojis: {
|
||||
category: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
const data = localStorage.getItem('instance');
|
||||
|
||||
// TODO: instanceをリアクティブにするかは再考の余地あり
|
||||
|
||||
export const instance: Instance = reactive(data ? JSON.parse(data) : {
|
||||
export const instance: Misskey.entities.InstanceMetadata = reactive(data ? JSON.parse(data) : {
|
||||
// TODO: set default values
|
||||
});
|
||||
|
||||
|
||||
+14
-12
@@ -3,16 +3,16 @@
|
||||
import { Component, defineAsyncComponent, markRaw, reactive, Ref, ref } from 'vue';
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import insertTextAtCursor from 'insert-text-at-cursor';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
import Stream from '@client/scripts/stream';
|
||||
import { apiUrl, debug } from '@client/config';
|
||||
import { apiUrl, debug, url } from '@client/config';
|
||||
import MkPostFormDialog from '@client/components/post-form-dialog.vue';
|
||||
import MkWaitingDialog from '@client/components/waiting-dialog.vue';
|
||||
import { resolve } from '@client/router';
|
||||
import { $i } from '@client/account';
|
||||
import { defaultStore } from '@client/store';
|
||||
|
||||
export const stream = markRaw(new Stream());
|
||||
export const stream = markRaw(new Misskey.Stream(url, $i));
|
||||
|
||||
export const pendingApiRequestsCount = ref(0);
|
||||
let apiRequestsCount = 0; // for debug
|
||||
@@ -20,7 +20,11 @@ export const apiRequests = ref([]); // for debug
|
||||
|
||||
export const windows = new Map();
|
||||
|
||||
export function api(endpoint: string, data: Record<string, any> = {}, token?: string | null | undefined) {
|
||||
const apiClient = new Misskey.api.APIClient({
|
||||
origin: url,
|
||||
});
|
||||
|
||||
export const api = ((endpoint: string, data: Record<string, any> = {}, token?: string | null | undefined) => {
|
||||
pendingApiRequestsCount.value++;
|
||||
|
||||
const onFinally = () => {
|
||||
@@ -56,7 +60,7 @@ export function api(endpoint: string, data: Record<string, any> = {}, token?: st
|
||||
if (res.status === 200) {
|
||||
resolve(body);
|
||||
if (debug) {
|
||||
log!.res = markRaw(body);
|
||||
log!.res = markRaw(JSON.parse(JSON.stringify(body)));
|
||||
log!.state = 'success';
|
||||
}
|
||||
} else if (res.status === 204) {
|
||||
@@ -90,17 +94,15 @@ export function api(endpoint: string, data: Record<string, any> = {}, token?: st
|
||||
promise.then(onFinally, onFinally);
|
||||
|
||||
return promise;
|
||||
}
|
||||
}) as typeof apiClient.request;
|
||||
|
||||
export function apiWithDialog(
|
||||
export const apiWithDialog = ((
|
||||
endpoint: string,
|
||||
data: Record<string, any> = {},
|
||||
token?: string | null | undefined,
|
||||
onSuccess?: (res: any) => void,
|
||||
onFailure?: (e: Error) => void,
|
||||
) {
|
||||
) => {
|
||||
const promise = api(endpoint, data, token);
|
||||
promiseDialog(promise, onSuccess, onFailure ? onFailure : (e) => {
|
||||
promiseDialog(promise, null, (e) => {
|
||||
dialog({
|
||||
type: 'error',
|
||||
text: e.message + '\n' + (e as any).id,
|
||||
@@ -108,7 +110,7 @@ export function apiWithDialog(
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
}) as typeof api;
|
||||
|
||||
export function promiseDialog<T extends Promise<any>>(
|
||||
promise: T,
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
<template>
|
||||
<FormBase>
|
||||
<FormSuspense :p="init">
|
||||
<FormInput v-model:value="title">
|
||||
<span>{{ $ts.title }}</span>
|
||||
</FormInput>
|
||||
|
||||
<FormTextarea v-model:value="description" :max="500">
|
||||
<span>{{ $ts.description }}</span>
|
||||
</FormTextarea>
|
||||
|
||||
<FormGroup>
|
||||
<div v-for="file in files" :key="file.id" class="_formItem _formPanel wqugxsfx" :style="{ backgroundImage: file ? `url(${ file.thumbnailUrl })` : null }">
|
||||
<div class="name">{{ file.name }}</div>
|
||||
<button class="remove _button" @click="remove(file)" v-tooltip="$ts.remove"><i class="fas fa-times"></i></button>
|
||||
</div>
|
||||
<FormButton @click="selectFile" primary><i class="fas fa-plus"></i> {{ $ts.attachFile }}</FormButton>
|
||||
</FormGroup>
|
||||
|
||||
<FormSwitch v-model:value="isSensitive">{{ $ts.markAsSensitive }}</FormSwitch>
|
||||
|
||||
<FormButton v-if="postId" @click="save" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
|
||||
<FormButton v-else @click="save" primary><i class="fas fa-save"></i> {{ $ts.publish }}</FormButton>
|
||||
|
||||
<FormButton v-if="postId" @click="del" danger><i class="fas fa-trash-alt"></i> {{ $ts.delete }}</FormButton>
|
||||
</FormSuspense>
|
||||
</FormBase>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import FormButton from '@client/components/form/button.vue';
|
||||
import FormInput from '@client/components/form/input.vue';
|
||||
import FormTextarea from '@client/components/form/textarea.vue';
|
||||
import FormSwitch from '@client/components/form/switch.vue';
|
||||
import FormTuple from '@client/components/form/tuple.vue';
|
||||
import FormBase from '@client/components/form/base.vue';
|
||||
import FormGroup from '@client/components/form/group.vue';
|
||||
import FormSuspense from '@client/components/form/suspense.vue';
|
||||
import { selectFile } from '@client/scripts/select-file';
|
||||
import * as os from '@client/os';
|
||||
import * as symbols from '@client/symbols';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
FormButton,
|
||||
FormInput,
|
||||
FormTextarea,
|
||||
FormSwitch,
|
||||
FormBase,
|
||||
FormGroup,
|
||||
FormSuspense,
|
||||
},
|
||||
|
||||
props: {
|
||||
postId: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
[symbols.PAGE_INFO]: computed(() => this.postId ? {
|
||||
title: this.$ts.edit,
|
||||
icon: 'fas fa-pencil-alt'
|
||||
} : {
|
||||
title: this.$ts.postToGallery,
|
||||
icon: 'fas fa-pencil-alt'
|
||||
}),
|
||||
init: null,
|
||||
files: [],
|
||||
description: null,
|
||||
title: null,
|
||||
isSensitive: false,
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
postId: {
|
||||
handler() {
|
||||
this.init = () => this.postId ? os.api('gallery/posts/show', {
|
||||
postId: this.postId
|
||||
}).then(post => {
|
||||
this.files = post.files;
|
||||
this.title = post.title;
|
||||
this.description = post.description;
|
||||
this.isSensitive = post.isSensitive;
|
||||
}) : Promise.resolve(null);
|
||||
},
|
||||
immediate: true,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
selectFile(e) {
|
||||
selectFile(e.currentTarget || e.target, null, true).then(files => {
|
||||
this.files = this.files.concat(files);
|
||||
});
|
||||
},
|
||||
|
||||
remove(file) {
|
||||
this.files = this.files.filter(f => f.id !== file.id);
|
||||
},
|
||||
|
||||
async save() {
|
||||
if (this.postId) {
|
||||
await os.apiWithDialog('gallery/posts/update', {
|
||||
postId: this.postId,
|
||||
title: this.title,
|
||||
description: this.description,
|
||||
fileIds: this.files.map(file => file.id),
|
||||
isSensitive: this.isSensitive,
|
||||
});
|
||||
this.$router.push(`/gallery/${this.postId}`);
|
||||
} else {
|
||||
const post = await os.apiWithDialog('gallery/posts/create', {
|
||||
title: this.title,
|
||||
description: this.description,
|
||||
fileIds: this.files.map(file => file.id),
|
||||
isSensitive: this.isSensitive,
|
||||
});
|
||||
this.$router.push(`/gallery/${post.id}`);
|
||||
}
|
||||
},
|
||||
|
||||
async del() {
|
||||
const { canceled } = await os.dialog({
|
||||
type: 'warning',
|
||||
text: this.$ts.deleteConfirm,
|
||||
showCancelButton: true
|
||||
});
|
||||
if (canceled) return;
|
||||
await os.apiWithDialog('gallery/posts/delete', {
|
||||
postId: this.postId,
|
||||
});
|
||||
this.$router.push(`/gallery`);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wqugxsfx {
|
||||
height: 200px;
|
||||
background-size: contain;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
position: relative;
|
||||
|
||||
> .name {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 9px;
|
||||
padding: 8px;
|
||||
background: var(--panel);
|
||||
}
|
||||
|
||||
> .remove {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 9px;
|
||||
padding: 8px;
|
||||
background: var(--panel);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,110 +0,0 @@
|
||||
<template>
|
||||
<FormBase>
|
||||
<FormInput v-model:value="title">
|
||||
<span>{{ $ts.title }}</span>
|
||||
</FormInput>
|
||||
|
||||
<FormTextarea v-model:value="description" :max="500">
|
||||
<span>{{ $ts.description }}</span>
|
||||
</FormTextarea>
|
||||
|
||||
<FormGroup>
|
||||
<div v-for="file in files" :key="file.id" class="_formItem _formPanel wqugxsfx" :style="{ backgroundImage: file ? `url(${ file.thumbnailUrl })` : null }">
|
||||
<div class="name">{{ file.name }}</div>
|
||||
<button class="remove _button" @click="remove(file)" v-tooltip="$ts.remove"><i class="fas fa-times"></i></button>
|
||||
</div>
|
||||
<FormButton @click="selectFile" primary><i class="fas fa-plus"></i> {{ $ts.attachFile }}</FormButton>
|
||||
</FormGroup>
|
||||
|
||||
<FormSwitch v-model:value="isSensitive">{{ $ts.markAsSensitive }}</FormSwitch>
|
||||
|
||||
<FormButton @click="publish" primary><i class="fas fa-save"></i> {{ $ts.publish }}</FormButton>
|
||||
</FormBase>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import FormButton from '@client/components/form/button.vue';
|
||||
import FormInput from '@client/components/form/input.vue';
|
||||
import FormTextarea from '@client/components/form/textarea.vue';
|
||||
import FormSwitch from '@client/components/form/switch.vue';
|
||||
import FormTuple from '@client/components/form/tuple.vue';
|
||||
import FormBase from '@client/components/form/base.vue';
|
||||
import FormGroup from '@client/components/form/group.vue';
|
||||
import { selectFile } from '@client/scripts/select-file';
|
||||
import * as os from '@client/os';
|
||||
import * as symbols from '@client/symbols';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
FormButton,
|
||||
FormInput,
|
||||
FormTextarea,
|
||||
FormSwitch,
|
||||
FormBase,
|
||||
FormGroup,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
[symbols.PAGE_INFO]: {
|
||||
title: this.$ts.postToGallery,
|
||||
icon: 'fas fa-pencil-alt'
|
||||
},
|
||||
files: [],
|
||||
description: null,
|
||||
title: null,
|
||||
isSensitive: false,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
selectFile(e) {
|
||||
selectFile(e.currentTarget || e.target, null, true).then(files => {
|
||||
this.files = this.files.concat(files);
|
||||
});
|
||||
},
|
||||
|
||||
remove(file) {
|
||||
this.files = this.files.filter(f => f.id !== file.id);
|
||||
},
|
||||
|
||||
async publish() {
|
||||
const post = await os.apiWithDialog('gallery/posts/create', {
|
||||
title: this.title,
|
||||
description: this.description,
|
||||
fileIds: this.files.map(file => file.id),
|
||||
isSensitive: this.isSensitive,
|
||||
});
|
||||
|
||||
this.$router.push(`/gallery/${post.id}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wqugxsfx {
|
||||
height: 200px;
|
||||
background-size: contain;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
position: relative;
|
||||
|
||||
> .name {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 9px;
|
||||
padding: 8px;
|
||||
background: var(--panel);
|
||||
}
|
||||
|
||||
> .remove {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 9px;
|
||||
padding: 8px;
|
||||
background: var(--panel);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -19,6 +19,7 @@
|
||||
<MkButton class="button" @click="like()" v-else v-tooltip="$ts._gallery.like"><i class="far fa-heart"></i><span class="count" v-if="post.likedCount > 0">{{ post.likedCount }}</span></MkButton>
|
||||
</div>
|
||||
<div class="other">
|
||||
<button v-if="$i && $i.id === post.user.id" class="_button" @click="edit" v-tooltip="$ts.edit" v-click-anime><i class="fas fa-pencil-alt fa-fw"></i></button>
|
||||
<button class="_button" @click="shareWithNote" v-tooltip="$ts.shareWithNote" v-click-anime><i class="fas fa-retweet fa-fw"></i></button>
|
||||
<button class="_button" @click="share" v-tooltip="$ts.share" v-click-anime><i class="fas fa-share-alt fa-fw"></i></button>
|
||||
</div>
|
||||
@@ -32,6 +33,7 @@
|
||||
<MkFollowButton v-if="!$i || $i.id != post.user.id" :user="post.user" :inline="true" :transparent="false" :full="true" large class="koudoku"/>
|
||||
</div>
|
||||
</div>
|
||||
<MkAd :prefer="['horizontal', 'horizontal-big']"/>
|
||||
<MkContainer :max-height="300" :foldable="true" class="other">
|
||||
<template #header><i class="fas fa-clock"></i> {{ $ts.recentPosts }}</template>
|
||||
<MkPagination :pagination="otherPostsPagination" #default="{items}">
|
||||
@@ -84,6 +86,11 @@ export default defineComponent({
|
||||
title: this.post.title,
|
||||
text: this.post.description,
|
||||
},
|
||||
actions: [{
|
||||
icon: 'fas fa-pencil-alt',
|
||||
text: this.$ts.edit,
|
||||
handler: this.edit
|
||||
}]
|
||||
} : null),
|
||||
otherPostsPagination: {
|
||||
endpoint: 'users/gallery/posts',
|
||||
@@ -154,6 +161,10 @@ export default defineComponent({
|
||||
this.post.likedCount--;
|
||||
});
|
||||
},
|
||||
|
||||
edit() {
|
||||
this.$router.push(`/gallery/${this.post.id}/edit`);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<div class="uqshojas">
|
||||
<MkButton @click="add()" primary style="margin: 0 auto 16px auto;"><i class="fas fa-plus"></i> {{ $ts.add }}</MkButton>
|
||||
<section class="_card _gap ads" v-for="ad in ads">
|
||||
<div class="_content ad">
|
||||
<MkAd v-if="ad.url" :specify="ad"/>
|
||||
<MkInput v-model:value="ad.url" type="url">
|
||||
<span>URL</span>
|
||||
</MkInput>
|
||||
<MkInput v-model:value="ad.imageUrl">
|
||||
<span>{{ $ts.imageUrl }}</span>
|
||||
</MkInput>
|
||||
<div style="margin: 32px 0;">
|
||||
<MkRadio v-model="ad.place" value="square">square</MkRadio>
|
||||
<MkRadio v-model="ad.place" value="horizontal">horizontal</MkRadio>
|
||||
<MkRadio v-model="ad.place" value="horizontal-big">horizontal-big</MkRadio>
|
||||
</div>
|
||||
<!--
|
||||
<div style="margin: 32px 0;">
|
||||
{{ $ts.priority }}
|
||||
<MkRadio v-model="ad.priority" value="high">{{ $ts.high }}</MkRadio>
|
||||
<MkRadio v-model="ad.priority" value="middle">{{ $ts.middle }}</MkRadio>
|
||||
<MkRadio v-model="ad.priority" value="low">{{ $ts.low }}</MkRadio>
|
||||
</div>
|
||||
-->
|
||||
<MkInput v-model:value="ad.ratio" type="number">
|
||||
<span>{{ $ts.ratio }}</span>
|
||||
</MkInput>
|
||||
<MkInput v-model:value="ad.expiresAt" type="date">
|
||||
<span>{{ $ts.expiration }}</span>
|
||||
</MkInput>
|
||||
<MkTextarea v-model:value="ad.memo">
|
||||
<span>{{ $ts.memo }}</span>
|
||||
</MkTextarea>
|
||||
<div class="buttons">
|
||||
<MkButton class="button" inline @click="save(ad)" primary><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
|
||||
<MkButton class="button" inline @click="remove(ad)" danger><i class="fas fa-trash-alt"></i> {{ $ts.remove }}</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import MkButton from '@client/components/ui/button.vue';
|
||||
import MkInput from '@client/components/ui/input.vue';
|
||||
import MkTextarea from '@client/components/ui/textarea.vue';
|
||||
import MkRadio from '@client/components/ui/radio.vue';
|
||||
import * as os from '@client/os';
|
||||
import * as symbols from '@client/symbols';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
MkButton,
|
||||
MkInput,
|
||||
MkTextarea,
|
||||
MkRadio,
|
||||
},
|
||||
|
||||
emits: ['info'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
[symbols.PAGE_INFO]: {
|
||||
title: this.$ts.ads,
|
||||
icon: 'fas fa-audio-description'
|
||||
},
|
||||
ads: [],
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
os.api('admin/ad/list').then(ads => {
|
||||
this.ads = ads;
|
||||
});
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$emit('info', this[symbols.PAGE_INFO]);
|
||||
},
|
||||
|
||||
methods: {
|
||||
add() {
|
||||
this.ads.unshift({
|
||||
id: null,
|
||||
memo: '',
|
||||
place: 'square',
|
||||
priority: 'middle',
|
||||
ratio: 1,
|
||||
url: '',
|
||||
imageUrl: null,
|
||||
expiresAt: null,
|
||||
});
|
||||
},
|
||||
|
||||
remove(ad) {
|
||||
os.dialog({
|
||||
type: 'warning',
|
||||
text: this.$t('removeAreYouSure', { x: ad.url }),
|
||||
showCancelButton: true
|
||||
}).then(({ canceled }) => {
|
||||
if (canceled) return;
|
||||
this.ads = this.ads.filter(x => x != ad);
|
||||
os.apiWithDialog('admin/ad/delete', {
|
||||
id: ad.id
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
save(ad) {
|
||||
if (ad.id == null) {
|
||||
os.apiWithDialog('admin/ad/create', {
|
||||
...ad,
|
||||
expiresAt: new Date(ad.expiresAt).getTime()
|
||||
});
|
||||
} else {
|
||||
os.apiWithDialog('admin/ad/update', {
|
||||
...ad,
|
||||
expiresAt: new Date(ad.expiresAt).getTime()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.uqshojas {
|
||||
margin: var(--margin);
|
||||
}
|
||||
</style>
|
||||
@@ -23,6 +23,7 @@
|
||||
<FormLink :active="page === 'queue'" replace to="/instance/queue"><template #icon><i class="fas fa-clipboard-list"></i></template>{{ $ts.jobQueue }}</FormLink>
|
||||
<FormLink :active="page === 'files'" replace to="/instance/files"><template #icon><i class="fas fa-cloud"></i></template>{{ $ts.files }}</FormLink>
|
||||
<FormLink :active="page === 'announcements'" replace to="/instance/announcements"><template #icon><i class="fas fa-broadcast-tower"></i></template>{{ $ts.announcements }}</FormLink>
|
||||
<FormLink :active="page === 'ads'" replace to="/instance/ads"><template #icon><i class="fas fa-audio-description"></i></template>{{ $ts.ads }}</FormLink>
|
||||
<FormLink :active="page === 'abuses'" replace to="/instance/abuses"><template #icon><i class="fas fa-exclamation-circle"></i></template>{{ $ts.abuseReports }}</FormLink>
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
@@ -42,6 +43,7 @@
|
||||
<FormGroup>
|
||||
<template #label>{{ $ts.info }}</template>
|
||||
<FormLink :active="page === 'database'" replace to="/instance/database"><template #icon><i class="fas fa-database"></i></template>{{ $ts.database }}</FormLink>
|
||||
<FormLink :active="page === 'logs'" replace to="/instance/logs"><template #icon><i class="fas fa-stream"></i></template>{{ $ts.logs }}</FormLink>
|
||||
</FormGroup>
|
||||
</FormBase>
|
||||
</div>
|
||||
@@ -102,7 +104,9 @@ export default defineComponent({
|
||||
case 'queue': return defineAsyncComponent(() => import('./queue.vue'));
|
||||
case 'files': return defineAsyncComponent(() => import('./files.vue'));
|
||||
case 'announcements': return defineAsyncComponent(() => import('./announcements.vue'));
|
||||
case 'ads': return defineAsyncComponent(() => import('./ads.vue'));
|
||||
case 'database': return defineAsyncComponent(() => import('./database.vue'));
|
||||
case 'logs': return defineAsyncComponent(() => import('./logs.vue'));
|
||||
case 'abuses': return defineAsyncComponent(() => import('./abuses.vue'));
|
||||
case 'settings': return defineAsyncComponent(() => import('./settings.vue'));
|
||||
case 'files-settings': return defineAsyncComponent(() => import('./files-settings.vue'));
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { defineComponent, markRaw } from 'vue';
|
||||
import Chart from 'chart.js';
|
||||
import XModalWindow from '@client/components/ui/modal-window.vue';
|
||||
import MkUsersDialog from '@client/components/users-dialog.vue';
|
||||
@@ -280,7 +280,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
Chart.defaults.global.defaultFontColor = getComputedStyle(document.documentElement).getPropertyValue('--fg');
|
||||
this.chartInstance = new Chart(this.canvas, {
|
||||
this.chartInstance = markRaw(new Chart(this.canvas, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: new Array(chartLimit).fill(0).map((_, i) => this.getDate(i).toLocaleString()).slice().reverse(),
|
||||
@@ -331,7 +331,7 @@ export default defineComponent({
|
||||
mode: 'index',
|
||||
}
|
||||
}
|
||||
});
|
||||
}));
|
||||
},
|
||||
|
||||
getDate(ago: number) {
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
<span>{{ $ts.domain }}</span>
|
||||
</MkInput>
|
||||
<MkSelect v-model:value="logLevel">
|
||||
<template #label>{{ $ts.level }}</template>
|
||||
<option value="all">{{ $ts.levels.all }}</option>
|
||||
<option value="info">{{ $ts.levels.info }}</option>
|
||||
<option value="success">{{ $ts.levels.success }}</option>
|
||||
<option value="warning">{{ $ts.levels.warning }}</option>
|
||||
<option value="error">{{ $ts.levels.error }}</option>
|
||||
<option value="debug">{{ $ts.levels.debug }}</option>
|
||||
<template #label>Level</template>
|
||||
<option value="all">All</option>
|
||||
<option value="info">Info</option>
|
||||
<option value="success">Success</option>
|
||||
<option value="warning">Warning</option>
|
||||
<option value="error">Error</option>
|
||||
<option value="debug">Debug</option>
|
||||
</MkSelect>
|
||||
</div>
|
||||
|
||||
@@ -45,6 +45,8 @@ export default defineComponent({
|
||||
MkTextarea,
|
||||
},
|
||||
|
||||
emits: ['info'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
[symbols.PAGE_INFO]: {
|
||||
@@ -72,6 +74,10 @@ export default defineComponent({
|
||||
this.fetchLogs();
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$emit('info', this[symbols.PAGE_INFO]);
|
||||
},
|
||||
|
||||
methods: {
|
||||
fetchLogs() {
|
||||
os.api('admin/logs', {
|
||||
|
||||
@@ -90,7 +90,7 @@ export default defineComponent({
|
||||
stats: null,
|
||||
serverInfo: null,
|
||||
connection: null,
|
||||
queueConnection: os.stream.useSharedConnection('queueStats'),
|
||||
queueConnection: os.stream.useChannel('queueStats'),
|
||||
memUsage: 0,
|
||||
chartCpuMem: null,
|
||||
chartNet: null,
|
||||
@@ -121,7 +121,7 @@ export default defineComponent({
|
||||
os.api('admin/server-info', {}).then(res => {
|
||||
this.serverInfo = res;
|
||||
|
||||
this.connection = os.stream.useSharedConnection('serverStats');
|
||||
this.connection = os.stream.useChannel('serverStats');
|
||||
this.connection.on('stats', this.onStats);
|
||||
this.connection.on('statsLog', this.onStatsLog);
|
||||
this.connection.send('requestLog', {
|
||||
|
||||
@@ -92,6 +92,7 @@ export default defineComponent({
|
||||
version,
|
||||
url,
|
||||
stats: null,
|
||||
meta: null,
|
||||
fetchStats: () => os.api('stats', {}),
|
||||
fetchServerInfo: () => os.api('admin/server-info', {}),
|
||||
fetchJobs: () => os.api('admin/queue/deliver-delayed', {}),
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { defineComponent, markRaw } from 'vue';
|
||||
import Chart from 'chart.js';
|
||||
import number from '../../filters/number';
|
||||
|
||||
@@ -69,7 +69,7 @@ export default defineComponent({
|
||||
|
||||
Chart.defaults.global.defaultFontColor = getComputedStyle(document.documentElement).getPropertyValue('--fg');
|
||||
|
||||
this.chart = new Chart(this.$refs.chart, {
|
||||
this.chart = markRaw(new Chart(this.$refs.chart, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [],
|
||||
@@ -152,7 +152,7 @@ export default defineComponent({
|
||||
mode: 'index',
|
||||
}
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
this.connection.on('stats', this.onStats);
|
||||
this.connection.on('statsLog', this.onStatsLog);
|
||||
|
||||
@@ -35,7 +35,7 @@ export default defineComponent({
|
||||
title: this.$ts.jobQueue,
|
||||
icon: 'fas fa-clipboard-list',
|
||||
},
|
||||
connection: os.stream.useSharedConnection('queueStats'),
|
||||
connection: os.stream.useChannel('queueStats'),
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ export default defineComponent({
|
||||
endpoint: 'notes/mentions',
|
||||
limit: 10,
|
||||
},
|
||||
faAt
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.connection = os.stream.useSharedConnection('messagingIndex');
|
||||
this.connection = os.stream.useChannel('messagingIndex');
|
||||
|
||||
this.connection.on('message', this.onMessage);
|
||||
this.connection.on('read', this.onRead);
|
||||
|
||||
@@ -141,7 +141,7 @@ const Component = defineComponent({
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
this.connection = os.stream.connectToChannel('messaging', {
|
||||
this.connection = os.stream.useChannel('messaging', {
|
||||
otherparty: this.user ? this.user.id : undefined,
|
||||
group: this.group ? this.group.id : undefined,
|
||||
});
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
<div><i class="far fa-clock"></i> {{ $ts.createdAt }}: <MkTime :time="page.createdAt" mode="detail"/></div>
|
||||
<div v-if="page.createdAt != page.updatedAt"><i class="far fa-clock"></i> {{ $ts.updatedAt }}: <MkTime :time="page.updatedAt" mode="detail"/></div>
|
||||
</div>
|
||||
<MkAd :prefer="['horizontal', 'horizontal-big']"/>
|
||||
<MkContainer :max-height="300" :foldable="true" class="other">
|
||||
<template #header><i class="fas fa-clock"></i> {{ $ts.recentPosts }}</template>
|
||||
<MkPagination :pagination="otherPostsPagination" #default="{items}">
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<FormBase v-if="token">
|
||||
<FormInput v-model:value="password" type="password">
|
||||
<template #prefix><i class="fas fa-lock"></i></template>
|
||||
<span>{{ $ts.newPassword }}</span>
|
||||
</FormInput>
|
||||
|
||||
<FormButton primary @click="save">{{ $ts.save }}</FormButton>
|
||||
</FormBase>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import FormLink from '@client/components/form/link.vue';
|
||||
import FormBase from '@client/components/form/base.vue';
|
||||
import FormGroup from '@client/components/form/group.vue';
|
||||
import FormInput from '@client/components/form/input.vue';
|
||||
import FormButton from '@client/components/form/button.vue';
|
||||
import * as os from '@client/os';
|
||||
import * as symbols from '@client/symbols';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
FormBase,
|
||||
FormGroup,
|
||||
FormLink,
|
||||
FormInput,
|
||||
FormButton,
|
||||
},
|
||||
|
||||
props: {
|
||||
token: {
|
||||
type: String,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
[symbols.PAGE_INFO]: {
|
||||
title: this.$ts.resetPassword,
|
||||
icon: 'fas fa-lock'
|
||||
},
|
||||
password: '',
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
if (this.token == null) {
|
||||
os.popup(import('@client/components/forgot-password.vue'), {}, {}, 'closed');
|
||||
this.$router.push('/');
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
async save() {
|
||||
await os.apiWithDialog('reset-password', {
|
||||
token: this.token,
|
||||
password: this.password,
|
||||
});
|
||||
this.$router.push('/');
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
@@ -157,7 +157,6 @@ export default defineComponent({
|
||||
maps: maps,
|
||||
form: null,
|
||||
messages: [],
|
||||
fasCircle, farCircle
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ export default defineComponent({
|
||||
if (this.connection) {
|
||||
this.connection.dispose();
|
||||
}
|
||||
this.connection = os.stream.connectToChannel('gamesReversiGame', {
|
||||
this.connection = os.stream.useChannel('gamesReversiGame', {
|
||||
gameId: this.game.id
|
||||
});
|
||||
this.connection.on('started', this.onStarted);
|
||||
|
||||
@@ -92,7 +92,7 @@ export default defineComponent({
|
||||
|
||||
mounted() {
|
||||
if (this.$i) {
|
||||
this.connection = os.stream.useSharedConnection('gamesReversi');
|
||||
this.connection = os.stream.useChannel('gamesReversi');
|
||||
|
||||
this.connection.on('invited', this.onInvited);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
</div>
|
||||
<FormLink :active="page === 'accounts'" replace to="/settings/accounts"><template #icon><i class="fas fa-users"></i></template>{{ $ts.accounts }}</FormLink>
|
||||
</FormGroup>
|
||||
<FormInfo v-if="emailNotConfigured" warn>{{ $ts.emailNotConfiguredWarning }} <MkA to="/settings/email" class="_link">{{ $ts.configure }}</MkA></FormInfo>
|
||||
<FormGroup>
|
||||
<template #label>{{ $ts.basicSettings }}</template>
|
||||
<FormLink :active="page === 'profile'" replace to="/settings/profile"><template #icon><i class="fas fa-user"></i></template>{{ $ts.profile }}</FormLink>
|
||||
@@ -58,10 +59,13 @@ import FormLink from '@client/components/form/link.vue';
|
||||
import FormGroup from '@client/components/form/group.vue';
|
||||
import FormBase from '@client/components/form/base.vue';
|
||||
import FormButton from '@client/components/form/button.vue';
|
||||
import FormInfo from '@client/components/form/info.vue';
|
||||
import { scroll } from '@client/scripts/scroll';
|
||||
import { signout } from '@client/account';
|
||||
import { unisonReload } from '@client/scripts/unison-reload';
|
||||
import * as symbols from '@client/symbols';
|
||||
import { instance } from '@client/instance';
|
||||
import { $i } from '@client/account';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@@ -69,6 +73,7 @@ export default defineComponent({
|
||||
FormLink,
|
||||
FormGroup,
|
||||
FormButton,
|
||||
FormInfo,
|
||||
},
|
||||
|
||||
props: {
|
||||
@@ -173,6 +178,8 @@ export default defineComponent({
|
||||
}
|
||||
});
|
||||
|
||||
const emailNotConfigured = computed(() => instance.enableEmail && ($i.email == null || !$i.emailVerified));
|
||||
|
||||
return {
|
||||
[symbols.PAGE_INFO]: INFO,
|
||||
page,
|
||||
@@ -182,6 +189,7 @@ export default defineComponent({
|
||||
onInfo,
|
||||
pageProps,
|
||||
component,
|
||||
emailNotConfigured,
|
||||
logout: () => {
|
||||
signout();
|
||||
},
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<div class="_formLabel"><i class="fab fa-twitter"></i> Twitter</div>
|
||||
<div class="_formPanel" style="padding: 16px;">
|
||||
<p v-if="integrations.twitter">{{ $ts.connectedTo }}: <a :href="`https://twitter.com/${integrations.twitter.screenName}`" rel="nofollow noopener" target="_blank">@{{ integrations.twitter.screenName }}</a></p>
|
||||
<MkButton v-if="integrations.twitter" @click="disconnectTwitter" danger>{{ $ts.disconnectSerice }}</MkButton>
|
||||
<MkButton v-else @click="connectTwitter" primary>{{ $ts.connectSerice }}</MkButton>
|
||||
<MkButton v-if="integrations.twitter" @click="disconnectTwitter" danger>{{ $ts.disconnectService }}</MkButton>
|
||||
<MkButton v-else @click="connectTwitter" primary>{{ $ts.connectService }}</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
<div class="_formLabel"><i class="fab fa-discord"></i> Discord</div>
|
||||
<div class="_formPanel" style="padding: 16px;">
|
||||
<p v-if="integrations.discord">{{ $ts.connectedTo }}: <a :href="`https://discord.com/users/${integrations.discord.id}`" rel="nofollow noopener" target="_blank">@{{ integrations.discord.username }}#{{ integrations.discord.discriminator }}</a></p>
|
||||
<MkButton v-if="integrations.discord" @click="disconnectDiscord" danger>{{ $ts.disconnectSerice }}</MkButton>
|
||||
<MkButton v-else @click="connectDiscord" primary>{{ $ts.connectSerice }}</MkButton>
|
||||
<MkButton v-if="integrations.discord" @click="disconnectDiscord" danger>{{ $ts.disconnectService }}</MkButton>
|
||||
<MkButton v-else @click="connectDiscord" primary>{{ $ts.connectService }}</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
<div class="_formLabel"><i class="fab fa-github"></i> GitHub</div>
|
||||
<div class="_formPanel" style="padding: 16px;">
|
||||
<p v-if="integrations.github">{{ $ts.connectedTo }}: <a :href="`https://github.com/${integrations.github.login}`" rel="nofollow noopener" target="_blank">@{{ integrations.github.login }}</a></p>
|
||||
<MkButton v-if="integrations.github" @click="disconnectGithub" danger>{{ $ts.disconnectSerice }}</MkButton>
|
||||
<MkButton v-else @click="connectGithub" primary>{{ $ts.connectSerice }}</MkButton>
|
||||
<MkButton v-if="integrations.github" @click="disconnectGithub" danger>{{ $ts.disconnectService }}</MkButton>
|
||||
<MkButton v-else @click="connectGithub" primary>{{ $ts.connectService }}</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
</FormBase>
|
||||
|
||||
@@ -161,15 +161,15 @@
|
||||
</dl>
|
||||
</div>
|
||||
<div class="status">
|
||||
<MkA :to="userPage(user)" :class="{ active: page === 'index' }">
|
||||
<MkA :to="userPage(user)" :class="{ active: page === 'index' }" v-click-anime>
|
||||
<b>{{ number(user.notesCount) }}</b>
|
||||
<span>{{ $ts.notes }}</span>
|
||||
</MkA>
|
||||
<MkA :to="userPage(user, 'following')" :class="{ active: page === 'following' }">
|
||||
<MkA :to="userPage(user, 'following')" :class="{ active: page === 'following' }" v-click-anime>
|
||||
<b>{{ number(user.followingCount) }}</b>
|
||||
<span>{{ $ts.following }}</span>
|
||||
</MkA>
|
||||
<MkA :to="userPage(user, 'followers')" :class="{ active: page === 'followers' }">
|
||||
<MkA :to="userPage(user, 'followers')" :class="{ active: page === 'followers' }" v-click-anime>
|
||||
<b>{{ number(user.followersCount) }}</b>
|
||||
<span>{{ $ts.followers }}</span>
|
||||
</MkA>
|
||||
|
||||
@@ -70,6 +70,8 @@ export default defineComponent({
|
||||
border-radius: var(--radius);
|
||||
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
max-width: 500px;
|
||||
margin: 32px auto;
|
||||
|
||||
> h1 {
|
||||
margin: 0;
|
||||
|
||||
@@ -23,6 +23,7 @@ export const router = createRouter({
|
||||
{ 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/:page(.*)?', name: 'settings', component: page('settings/index'), props: route => ({ initialPage: route.params.page || null }) },
|
||||
{ path: '/reset-password/:token?', component: page('reset-password'), props: route => ({ token: route.params.token }) },
|
||||
{ path: '/announcements', component: page('announcements') },
|
||||
{ path: '/about', component: page('about') },
|
||||
{ path: '/about-misskey', component: page('about-misskey') },
|
||||
@@ -38,7 +39,8 @@ export const router = createRouter({
|
||||
{ path: '/pages/new', component: page('page-editor/page-editor') },
|
||||
{ path: '/pages/edit/:pageId', component: page('page-editor/page-editor'), props: route => ({ initPageId: route.params.pageId }) },
|
||||
{ path: '/gallery', component: page('gallery/index') },
|
||||
{ path: '/gallery/new', component: page('gallery/new') },
|
||||
{ path: '/gallery/new', component: page('gallery/edit') },
|
||||
{ path: '/gallery/:postId/edit', component: page('gallery/edit'), props: route => ({ postId: route.params.postId }) },
|
||||
{ path: '/gallery/:postId', component: page('gallery/post'), props: route => ({ postId: route.params.postId }) },
|
||||
{ path: '/channels', component: page('channels') },
|
||||
{ path: '/channels/new', component: page('channel-editor') },
|
||||
|
||||
@@ -3,6 +3,11 @@ import * as url from '../../prelude/url';
|
||||
|
||||
export function getStaticImageUrl(baseUrl: string): string {
|
||||
const u = new URL(baseUrl);
|
||||
if (u.href.startsWith(`${instanceUrl}/proxy/`)) {
|
||||
// もう既にproxyっぽそうだったらsearchParams付けるだけ
|
||||
u.searchParams.set('static', '1');
|
||||
return u.href;
|
||||
}
|
||||
const dummy = `${u.host}${u.pathname}`; // 拡張子がないとキャッシュしてくれないCDNがあるので
|
||||
return `${instanceUrl}/proxy/${dummy}?${url.query({
|
||||
url: u.href,
|
||||
|
||||
@@ -91,8 +91,10 @@ export default (opts) => ({
|
||||
...params,
|
||||
limit: this.pagination.noPaging ? (this.pagination.limit || 10) : (this.pagination.limit || 10) + 1,
|
||||
}).then(items => {
|
||||
for (const item of items) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
markRaw(item);
|
||||
if (i === 3) item._shouldInsertAd_ = true;
|
||||
}
|
||||
if (!this.pagination.noPaging && (items.length > (this.pagination.limit || 10))) {
|
||||
items.pop();
|
||||
@@ -128,8 +130,10 @@ export default (opts) => ({
|
||||
untilId: this.pagination.reversed ? this.items[0].id : this.items[this.items.length - 1].id,
|
||||
}),
|
||||
}).then(items => {
|
||||
for (const item of items) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
markRaw(item);
|
||||
if (i === 10) item._shouldInsertAd_ = true;
|
||||
}
|
||||
if (items.length > SECOND_FETCH_LIMIT) {
|
||||
items.pop();
|
||||
|
||||
@@ -47,7 +47,7 @@ export function selectFile(src: any, label: string | null, multiple = false) {
|
||||
|
||||
const marker = Math.random().toString(); // TODO: UUIDとか使う
|
||||
|
||||
const connection = os.stream.useSharedConnection('main');
|
||||
const connection = os.stream.useChannel('main');
|
||||
connection.on('urlUploadFinished', data => {
|
||||
if (data.marker === marker) {
|
||||
res(multiple ? [data.file] : data.file);
|
||||
@@ -55,7 +55,7 @@ export function selectFile(src: any, label: string | null, multiple = false) {
|
||||
}
|
||||
});
|
||||
|
||||
os.api('drive/files/upload_from_url', {
|
||||
os.api('drive/files/upload-from-url', {
|
||||
url: url,
|
||||
marker
|
||||
});
|
||||
|
||||
@@ -1,312 +0,0 @@
|
||||
import autobind from 'autobind-decorator';
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import ReconnectingWebsocket from 'reconnecting-websocket';
|
||||
import { markRaw } from 'vue';
|
||||
import { debug, wsUrl } from '@client/config';
|
||||
import { query as urlQuery } from '../../prelude/url';
|
||||
|
||||
/**
|
||||
* Misskey stream connection
|
||||
*/
|
||||
export default class Stream extends EventEmitter {
|
||||
private stream: ReconnectingWebsocket;
|
||||
public state: 'initializing' | 'reconnecting' | 'connected' = 'initializing';
|
||||
private sharedConnectionPools: Pool[] = [];
|
||||
private sharedConnections: SharedConnection[] = [];
|
||||
private nonSharedConnections: NonSharedConnection[] = [];
|
||||
|
||||
@autobind
|
||||
public init(user): void {
|
||||
const query = urlQuery({
|
||||
i: user?.token,
|
||||
_t: Date.now(),
|
||||
});
|
||||
|
||||
this.stream = new ReconnectingWebsocket(`${wsUrl}?${query}`, '', { minReconnectionDelay: 1 }); // https://github.com/pladaria/reconnecting-websocket/issues/91
|
||||
this.stream.addEventListener('open', this.onOpen);
|
||||
this.stream.addEventListener('close', this.onClose);
|
||||
this.stream.addEventListener('message', this.onMessage);
|
||||
}
|
||||
|
||||
@autobind
|
||||
public useSharedConnection(channel: string, name?: string): SharedConnection {
|
||||
let pool = this.sharedConnectionPools.find(p => p.channel === channel);
|
||||
|
||||
if (pool == null) {
|
||||
pool = new Pool(this, channel);
|
||||
this.sharedConnectionPools.push(pool);
|
||||
}
|
||||
|
||||
const connection = markRaw(new SharedConnection(this, channel, pool, name));
|
||||
this.sharedConnections.push(connection);
|
||||
return connection;
|
||||
}
|
||||
|
||||
@autobind
|
||||
public removeSharedConnection(connection: SharedConnection) {
|
||||
this.sharedConnections = this.sharedConnections.filter(c => c !== connection);
|
||||
}
|
||||
|
||||
@autobind
|
||||
public removeSharedConnectionPool(pool: Pool) {
|
||||
this.sharedConnectionPools = this.sharedConnectionPools.filter(p => p !== pool);
|
||||
}
|
||||
|
||||
@autobind
|
||||
public connectToChannel(channel: string, params?: any): NonSharedConnection {
|
||||
const connection = markRaw(new NonSharedConnection(this, channel, params));
|
||||
this.nonSharedConnections.push(connection);
|
||||
return connection;
|
||||
}
|
||||
|
||||
@autobind
|
||||
public disconnectToChannel(connection: NonSharedConnection) {
|
||||
this.nonSharedConnections = this.nonSharedConnections.filter(c => c !== connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback of when open connection
|
||||
*/
|
||||
@autobind
|
||||
private onOpen() {
|
||||
const isReconnect = this.state === 'reconnecting';
|
||||
|
||||
this.state = 'connected';
|
||||
this.emit('_connected_');
|
||||
|
||||
// チャンネル再接続
|
||||
if (isReconnect) {
|
||||
for (const p of this.sharedConnectionPools)
|
||||
p.connect();
|
||||
for (const c of this.nonSharedConnections)
|
||||
c.connect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback of when close connection
|
||||
*/
|
||||
@autobind
|
||||
private onClose() {
|
||||
if (this.state === 'connected') {
|
||||
this.state = 'reconnecting';
|
||||
this.emit('_disconnected_');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback of when received a message from connection
|
||||
*/
|
||||
@autobind
|
||||
private onMessage(message) {
|
||||
const { type, body } = JSON.parse(message.data);
|
||||
|
||||
if (type === 'channel') {
|
||||
const id = body.id;
|
||||
|
||||
let connections: Connection[];
|
||||
|
||||
connections = this.sharedConnections.filter(c => c.id === id);
|
||||
|
||||
if (connections.length === 0) {
|
||||
connections = [this.nonSharedConnections.find(c => c.id === id)];
|
||||
}
|
||||
|
||||
for (const c of connections.filter(c => c != null)) {
|
||||
c.emit(body.type, Object.freeze(body.body));
|
||||
if (debug) c.inCount++;
|
||||
}
|
||||
} else {
|
||||
this.emit(type, Object.freeze(body));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to connection
|
||||
*/
|
||||
@autobind
|
||||
public send(typeOrPayload, payload?) {
|
||||
const data = payload === undefined ? typeOrPayload : {
|
||||
type: typeOrPayload,
|
||||
body: payload
|
||||
};
|
||||
|
||||
this.stream.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Close this connection
|
||||
*/
|
||||
@autobind
|
||||
public close() {
|
||||
this.stream.removeEventListener('open', this.onOpen);
|
||||
this.stream.removeEventListener('message', this.onMessage);
|
||||
}
|
||||
}
|
||||
|
||||
let idCounter = 0;
|
||||
|
||||
class Pool {
|
||||
public channel: string;
|
||||
public id: string;
|
||||
protected stream: Stream;
|
||||
public users = 0;
|
||||
private disposeTimerId: any;
|
||||
private isConnected = false;
|
||||
|
||||
constructor(stream: Stream, channel: string) {
|
||||
this.channel = channel;
|
||||
this.stream = stream;
|
||||
|
||||
this.id = (++idCounter).toString();
|
||||
|
||||
this.stream.on('_disconnected_', this.onStreamDisconnected);
|
||||
}
|
||||
|
||||
@autobind
|
||||
private onStreamDisconnected() {
|
||||
this.isConnected = false;
|
||||
}
|
||||
|
||||
@autobind
|
||||
public inc() {
|
||||
if (this.users === 0 && !this.isConnected) {
|
||||
this.connect();
|
||||
}
|
||||
|
||||
this.users++;
|
||||
|
||||
// タイマー解除
|
||||
if (this.disposeTimerId) {
|
||||
clearTimeout(this.disposeTimerId);
|
||||
this.disposeTimerId = null;
|
||||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
public dec() {
|
||||
this.users--;
|
||||
|
||||
// そのコネクションの利用者が誰もいなくなったら
|
||||
if (this.users === 0) {
|
||||
// また直ぐに再利用される可能性があるので、一定時間待ち、
|
||||
// 新たな利用者が現れなければコネクションを切断する
|
||||
this.disposeTimerId = setTimeout(() => {
|
||||
this.disconnect();
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
public connect() {
|
||||
if (this.isConnected) return;
|
||||
this.isConnected = true;
|
||||
this.stream.send('connect', {
|
||||
channel: this.channel,
|
||||
id: this.id
|
||||
});
|
||||
}
|
||||
|
||||
@autobind
|
||||
private disconnect() {
|
||||
this.stream.off('_disconnected_', this.onStreamDisconnected);
|
||||
this.stream.send('disconnect', { id: this.id });
|
||||
this.stream.removeSharedConnectionPool(this);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Connection extends EventEmitter {
|
||||
public channel: string;
|
||||
protected stream: Stream;
|
||||
public abstract id: string;
|
||||
|
||||
public name?: string; // for debug
|
||||
public inCount: number = 0; // for debug
|
||||
public outCount: number = 0; // for debug
|
||||
|
||||
constructor(stream: Stream, channel: string, name?: string) {
|
||||
super();
|
||||
|
||||
this.stream = stream;
|
||||
this.channel = channel;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@autobind
|
||||
public send(id: string, typeOrPayload, payload?) {
|
||||
const type = payload === undefined ? typeOrPayload.type : typeOrPayload;
|
||||
const body = payload === undefined ? typeOrPayload.body : payload;
|
||||
|
||||
this.stream.send('ch', {
|
||||
id: id,
|
||||
type: type,
|
||||
body: body
|
||||
});
|
||||
|
||||
if (debug) this.outCount++;
|
||||
}
|
||||
|
||||
public abstract dispose(): void;
|
||||
}
|
||||
|
||||
class SharedConnection extends Connection {
|
||||
private pool: Pool;
|
||||
|
||||
public get id(): string {
|
||||
return this.pool.id;
|
||||
}
|
||||
|
||||
constructor(stream: Stream, channel: string, pool: Pool, name?: string) {
|
||||
super(stream, channel, name);
|
||||
|
||||
this.pool = pool;
|
||||
this.pool.inc();
|
||||
}
|
||||
|
||||
@autobind
|
||||
public send(typeOrPayload, payload?) {
|
||||
super.send(this.pool.id, typeOrPayload, payload);
|
||||
}
|
||||
|
||||
@autobind
|
||||
public dispose() {
|
||||
this.pool.dec();
|
||||
this.removeAllListeners();
|
||||
this.stream.removeSharedConnection(this);
|
||||
}
|
||||
}
|
||||
|
||||
class NonSharedConnection extends Connection {
|
||||
public id: string;
|
||||
protected params: any;
|
||||
|
||||
constructor(stream: Stream, channel: string, params?: any) {
|
||||
super(stream, channel);
|
||||
|
||||
this.params = params;
|
||||
this.id = (++idCounter).toString();
|
||||
|
||||
this.connect();
|
||||
}
|
||||
|
||||
@autobind
|
||||
public connect() {
|
||||
this.stream.send('connect', {
|
||||
channel: this.channel,
|
||||
id: this.id,
|
||||
params: this.params
|
||||
});
|
||||
}
|
||||
|
||||
@autobind
|
||||
public send(typeOrPayload, payload?) {
|
||||
super.send(this.id, typeOrPayload, payload);
|
||||
}
|
||||
|
||||
@autobind
|
||||
public dispose() {
|
||||
this.removeAllListeners();
|
||||
this.stream.send('disconnect', { id: this.id });
|
||||
this.stream.disconnectToChannel(this);
|
||||
}
|
||||
}
|
||||
@@ -18,9 +18,11 @@ export const builtinThemes = [
|
||||
require('@client/themes/l-light.json5'),
|
||||
require('@client/themes/l-apricot.json5'),
|
||||
require('@client/themes/l-rainy.json5'),
|
||||
require('@client/themes/l-vivid.json5'),
|
||||
|
||||
require('@client/themes/d-dark.json5'),
|
||||
require('@client/themes/d-persimmon.json5'),
|
||||
require('@client/themes/d-astro.json5'),
|
||||
require('@client/themes/d-black.json5'),
|
||||
] as Theme[];
|
||||
|
||||
|
||||
@@ -55,6 +55,10 @@ export const defaultStore = markRaw(new Storage('base', {
|
||||
where: 'account',
|
||||
default: []
|
||||
},
|
||||
mutedAds: {
|
||||
where: 'account',
|
||||
default: [] as string[]
|
||||
},
|
||||
|
||||
menu: {
|
||||
where: 'deviceAccount',
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
@media (max-width: 500px) {
|
||||
--margin: var(--marginHalf);
|
||||
}
|
||||
|
||||
//--ad: rgb(255 169 0 / 10%);
|
||||
}
|
||||
|
||||
::selection {
|
||||
@@ -144,6 +146,7 @@ hr {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--modalBg);
|
||||
-webkit-backdrop-filter: var(--modalBgFilter);
|
||||
backdrop-filter: var(--modalBgFilter);
|
||||
}
|
||||
|
||||
@@ -337,7 +340,7 @@ hr {
|
||||
}
|
||||
|
||||
._monolithic_ {
|
||||
._section {
|
||||
._section:not(:empty) {
|
||||
box-sizing: border-box;
|
||||
padding: var(--root-margin, 32px);
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
{
|
||||
id: '080a01c5-377d-4fbb-88cc-6bb5d04977ea',
|
||||
base: 'dark',
|
||||
name: 'Mi Astro',
|
||||
author: 'syuilo',
|
||||
props: {
|
||||
bg: '#232125',
|
||||
fg: '#efdab9',
|
||||
cwBg: '#687390',
|
||||
cwFg: '#393f4f',
|
||||
link: '#78b0a0',
|
||||
warn: '#ecb637',
|
||||
badge: '#31b1ce',
|
||||
error: '#ec4137',
|
||||
focus: ':alpha<0.3<@accent',
|
||||
navBg: '@panel',
|
||||
navFg: '@fg',
|
||||
panel: '#2a272b',
|
||||
accent: '#81c08b',
|
||||
header: ':alpha<0.7<@bg',
|
||||
infoBg: '#253142',
|
||||
infoFg: '#fff',
|
||||
renote: '#659CC8',
|
||||
shadow: 'rgba(0, 0, 0, 0.3)',
|
||||
divider: 'rgba(255, 255, 255, 0.1)',
|
||||
hashtag: '#ff9156',
|
||||
mention: '#ffd152',
|
||||
modalBg: 'rgba(0, 0, 0, 0.5)',
|
||||
success: '#86b300',
|
||||
buttonBg: 'rgba(255, 255, 255, 0.05)',
|
||||
acrylicBg: ':alpha<0.5<@bg',
|
||||
cwHoverBg: '#707b97',
|
||||
indicator: '@accent',
|
||||
mentionMe: '#fb5d38',
|
||||
messageBg: ':lighten<5<@bg',
|
||||
navActive: '@accent',
|
||||
infoWarnBg: '#42321c',
|
||||
infoWarnFg: '#ffbd3e',
|
||||
navHoverFg: ':lighten<17<@fg',
|
||||
dateLabelFg: '@fg',
|
||||
inputBorder: '#959da2',
|
||||
panelBorder: 'rgba(0, 0, 0, 0)',
|
||||
panelShadow: '" 0 8px 24px rgba(0, 0, 0, 0.12)',
|
||||
accentDarken: ':darken<10<@accent',
|
||||
acrylicPanel: ':alpha<0.5<@panel',
|
||||
navIndicator: '@accent',
|
||||
accentLighten: ':lighten<10<@accent',
|
||||
buttonHoverBg: 'rgba(255, 255, 255, 0.1)',
|
||||
driveFolderBg: ':alpha<0.3<@accent',
|
||||
fgHighlighted: ':lighten<3<@fg',
|
||||
panelHeaderBg: ':lighten<3<@panel',
|
||||
panelHeaderFg: '@fg',
|
||||
htmlThemeColor: '@bg',
|
||||
panelHighlight: ':lighten<3<@panel',
|
||||
listItemHoverBg: 'rgba(255, 255, 255, 0.03)',
|
||||
scrollbarHandle: 'rgba(255, 255, 255, 0.2)',
|
||||
wallpaperOverlay: 'rgba(0, 0, 0, 0.5)',
|
||||
panelHeaderDivider: 'rgba(0, 0, 0, 0)',
|
||||
scrollbarHandleHover: 'rgba(255, 255, 255, 0.4)',
|
||||
X2: ':darken<2<@panel',
|
||||
X3: 'rgba(255, 255, 255, 0.05)',
|
||||
X4: 'rgba(255, 255, 255, 0.1)',
|
||||
X5: 'rgba(255, 255, 255, 0.05)',
|
||||
X6: 'rgba(255, 255, 255, 0.15)',
|
||||
X7: 'rgba(255, 255, 255, 0.05)',
|
||||
X8: ':lighten<5<@accent',
|
||||
X9: ':darken<5<@accent',
|
||||
X10: ':alpha<0.4<@accent',
|
||||
X11: 'rgba(0, 0, 0, 0.3)',
|
||||
X12: 'rgba(255, 255, 255, 0.1)',
|
||||
X13: 'rgba(255, 255, 255, 0.15)',
|
||||
X14: ':alpha<0.5<@navBg',
|
||||
X15: ':alpha<0<@panel',
|
||||
X16: ':alpha<0.7<@panel',
|
||||
},
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
props: {
|
||||
bg: '#f9f9f9',
|
||||
fg: '#676767',
|
||||
divider: 'rgb(223, 223, 223)',
|
||||
divider: '#e8e8e8',
|
||||
header: ':alpha<0.7<@panel',
|
||||
navBg: '#fff',
|
||||
panel: '#fff',
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
{
|
||||
id: '6128c2a9-5c54-43fe-a47d-17942356470b',
|
||||
|
||||
name: 'Mi Vivid',
|
||||
author: 'syuilo',
|
||||
|
||||
base: 'light',
|
||||
|
||||
props: {
|
||||
bg: '#fafafa',
|
||||
fg: '#444',
|
||||
cwBg: '#b1b9c1',
|
||||
cwFg: '#fff',
|
||||
link: '#ff9400',
|
||||
warn: '#ecb637',
|
||||
badge: '#31b1ce',
|
||||
error: '#ec4137',
|
||||
focus: ':alpha<0.3<@accent',
|
||||
navBg: '@panel',
|
||||
navFg: '@fg',
|
||||
panel: '#fff',
|
||||
accent: '#008cff',
|
||||
header: ':alpha<0.7<@panel',
|
||||
infoBg: '#e5f5ff',
|
||||
infoFg: '#72818a',
|
||||
renote: '@accent',
|
||||
shadow: 'rgba(0, 0, 0, 0.1)',
|
||||
divider: 'rgba(0, 0, 0, 0.08)',
|
||||
hashtag: '#92d400',
|
||||
mention: '@accent',
|
||||
modalBg: 'rgba(0, 0, 0, 0.3)',
|
||||
success: '#86b300',
|
||||
buttonBg: 'rgba(0, 0, 0, 0.05)',
|
||||
acrylicBg: ':alpha<0.5<@bg',
|
||||
cwHoverBg: '#bbc4ce',
|
||||
indicator: '@accent',
|
||||
mentionMe: '@mention',
|
||||
messageBg: '@panel',
|
||||
navActive: '@accent',
|
||||
infoWarnBg: '#fff0db',
|
||||
infoWarnFg: '#573c08',
|
||||
navHoverFg: ':darken<17<@fg',
|
||||
dateLabelFg: '@fg',
|
||||
inputBorder: '#dae0e4',
|
||||
panelBorder: 'rgba(0, 0, 0, 0)',
|
||||
panelShadow: '" 0 8px 24px rgb(21 43 75 / 8%)',
|
||||
accentDarken: ':darken<10<@accent',
|
||||
acrylicPanel: ':alpha<0.5<@panel',
|
||||
navIndicator: '@accent',
|
||||
accentLighten: ':lighten<10<@accent',
|
||||
buttonHoverBg: 'rgba(0, 0, 0, 0.1)',
|
||||
driveFolderBg: ':alpha<0.3<@accent',
|
||||
fgHighlighted: ':darken<3<@fg',
|
||||
fgTransparent: ':alpha<0.5<@fg',
|
||||
panelHeaderBg: ':lighten<3<@panel',
|
||||
panelHeaderFg: '@fg',
|
||||
htmlThemeColor: '@bg',
|
||||
panelHighlight: ':darken<3<@panel',
|
||||
listItemHoverBg: 'rgba(0, 0, 0, 0.03)',
|
||||
scrollbarHandle: 'rgba(0, 0, 0, 0.2)',
|
||||
wallpaperOverlay: 'rgba(255, 255, 255, 0.5)',
|
||||
fgTransparentWeak: ':alpha<0.75<@fg',
|
||||
panelHeaderDivider: '@divider',
|
||||
scrollbarHandleHover: 'rgba(0, 0, 0, 0.4)',
|
||||
X2: ':darken<2<@panel',
|
||||
X3: 'rgba(0, 0, 0, 0.05)',
|
||||
X4: 'rgba(0, 0, 0, 0.1)',
|
||||
X5: 'rgba(0, 0, 0, 0.05)',
|
||||
X6: 'rgba(0, 0, 0, 0.25)',
|
||||
X7: 'rgba(0, 0, 0, 0.05)',
|
||||
X8: ':lighten<5<@accent',
|
||||
X9: ':darken<5<@accent',
|
||||
X10: ':alpha<0.4<@accent',
|
||||
X11: 'rgba(0, 0, 0, 0.1)',
|
||||
X12: 'rgba(0, 0, 0, 0.1)',
|
||||
X13: 'rgba(0, 0, 0, 0.15)',
|
||||
X14: ':alpha<0.5<@navBg',
|
||||
X15: ':alpha<0<@panel',
|
||||
X16: ':alpha<0.7<@panel',
|
||||
X17: ':alpha<0.8<@bg',
|
||||
},
|
||||
}
|
||||
@@ -43,7 +43,7 @@ export default defineComponent({
|
||||
};
|
||||
|
||||
if ($i) {
|
||||
const connection = stream.useSharedConnection('main', 'UI');
|
||||
const connection = stream.useChannel('main', null, 'UI');
|
||||
connection.on('notification', onNotification);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,11 +42,7 @@ export default defineComponent({
|
||||
|
||||
if (
|
||||
i != this.items.length - 1 &&
|
||||
new Date(item.createdAt).getDate() != new Date(this.items[i + 1].createdAt).getDate() &&
|
||||
!item._prId_ &&
|
||||
!this.items[i + 1]._prId_ &&
|
||||
!item._featuredId_ &&
|
||||
!this.items[i + 1]._featuredId_
|
||||
new Date(item.createdAt).getDate() != new Date(this.items[i + 1].createdAt).getDate()
|
||||
) {
|
||||
const separator = h('div', {
|
||||
class: 'separator',
|
||||
|
||||
@@ -313,7 +313,7 @@ export default defineComponent({
|
||||
}
|
||||
};
|
||||
if (isLink(e.target)) return;
|
||||
if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO'].includes(e.target.tagName) || e.target.attributes['contenteditable']) return;
|
||||
if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes(e.target.tagName) || e.target.attributes['contenteditable']) return;
|
||||
if (window.getSelection().toString() !== '') return;
|
||||
const path = this.$route.path;
|
||||
os.contextMenu([{
|
||||
|
||||
@@ -121,33 +121,33 @@ export default defineComponent({
|
||||
this.query = {
|
||||
antennaId: this.antenna
|
||||
};
|
||||
this.connection = os.stream.connectToChannel('antenna', {
|
||||
this.connection = os.stream.useChannel('antenna', {
|
||||
antennaId: this.antenna
|
||||
});
|
||||
this.connection.on('note', prepend);
|
||||
} else if (this.src == 'home') {
|
||||
endpoint = 'notes/timeline';
|
||||
this.connection = os.stream.useSharedConnection('homeTimeline');
|
||||
this.connection = os.stream.useChannel('homeTimeline');
|
||||
this.connection.on('note', prepend);
|
||||
|
||||
this.connection2 = os.stream.useSharedConnection('main');
|
||||
this.connection2 = os.stream.useChannel('main');
|
||||
this.connection2.on('follow', onChangeFollowing);
|
||||
this.connection2.on('unfollow', onChangeFollowing);
|
||||
} else if (this.src == 'local') {
|
||||
endpoint = 'notes/local-timeline';
|
||||
this.connection = os.stream.useSharedConnection('localTimeline');
|
||||
this.connection = os.stream.useChannel('localTimeline');
|
||||
this.connection.on('note', prepend);
|
||||
} else if (this.src == 'social') {
|
||||
endpoint = 'notes/hybrid-timeline';
|
||||
this.connection = os.stream.useSharedConnection('hybridTimeline');
|
||||
this.connection = os.stream.useChannel('hybridTimeline');
|
||||
this.connection.on('note', prepend);
|
||||
} else if (this.src == 'global') {
|
||||
endpoint = 'notes/global-timeline';
|
||||
this.connection = os.stream.useSharedConnection('globalTimeline');
|
||||
this.connection = os.stream.useChannel('globalTimeline');
|
||||
this.connection.on('note', prepend);
|
||||
} else if (this.src == 'mentions') {
|
||||
endpoint = 'notes/mentions';
|
||||
this.connection = os.stream.useSharedConnection('main');
|
||||
this.connection = os.stream.useChannel('main');
|
||||
this.connection.on('mention', prepend);
|
||||
} else if (this.src == 'directs') {
|
||||
endpoint = 'notes/mentions';
|
||||
@@ -159,14 +159,14 @@ export default defineComponent({
|
||||
prepend(note);
|
||||
}
|
||||
};
|
||||
this.connection = os.stream.useSharedConnection('main');
|
||||
this.connection = os.stream.useChannel('main');
|
||||
this.connection.on('mention', onNote);
|
||||
} else if (this.src == 'list') {
|
||||
endpoint = 'notes/user-list-timeline';
|
||||
this.query = {
|
||||
listId: this.list
|
||||
};
|
||||
this.connection = os.stream.connectToChannel('userList', {
|
||||
this.connection = os.stream.useChannel('userList', {
|
||||
listId: this.list
|
||||
});
|
||||
this.connection.on('note', prepend);
|
||||
@@ -178,7 +178,7 @@ export default defineComponent({
|
||||
this.query = {
|
||||
channelId: this.channel
|
||||
};
|
||||
this.connection = os.stream.connectToChannel('channel', {
|
||||
this.connection = os.stream.useChannel('channel', {
|
||||
channelId: this.channel
|
||||
});
|
||||
this.connection.on('note', prepend);
|
||||
|
||||
@@ -64,7 +64,7 @@ export default defineComponent({
|
||||
}
|
||||
};
|
||||
if (isLink(e.target)) return;
|
||||
if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO'].includes(e.target.tagName) || e.target.attributes['contenteditable']) return;
|
||||
if (['INPUT', 'TEXTAREA', 'IMG', 'VIDEO', 'CANVAS'].includes(e.target.tagName) || e.target.attributes['contenteditable']) return;
|
||||
if (window.getSelection().toString() !== '') return;
|
||||
const path = this.$route.path;
|
||||
os.contextMenu([{
|
||||
|
||||
@@ -36,7 +36,6 @@ export default defineComponent({
|
||||
endpoint: 'notes/mentions',
|
||||
limit: 10,
|
||||
},
|
||||
faAt
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user