diff --git a/.config/ci.yml b/.config/ci.yml deleted file mode 100644 index 8730ccab3a..0000000000 --- a/.config/ci.yml +++ /dev/null @@ -1,236 +0,0 @@ -#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -# Misskey configuration -#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -# ┌─────┐ -#───┘ URL └───────────────────────────────────────────────────── - -# Final accessible URL seen by a user. -url: http://misskey.local - -# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE -# URL SETTINGS AFTER THAT! - -# ┌───────────────────────┐ -#───┘ Port and TLS settings └─────────────────────────────────── - -# -# Misskey requires a reverse proxy to support HTTPS connections. -# -# +----- https://example.tld/ ------------+ -# +------+ |+-------------+ +----------------+| -# | User | ---> || Proxy (443) | ---> | Misskey (3000) || -# +------+ |+-------------+ +----------------+| -# +---------------------------------------+ -# -# You need to set up a reverse proxy. (e.g. nginx) -# An encrypted connection with HTTPS is highly recommended -# because tokens may be transferred in GET requests. - -# The port that your Misskey server should listen on. -port: 3000 - -# ┌──────────────────────────┐ -#───┘ PostgreSQL configuration └──────────────────────────────── - -db: - host: postgres - port: 5432 - - # Database name - db: postgres - - # Auth - user: postgres - pass: ci - - # Whether disable Caching queries - #disableCache: true - - # Extra Connection options - #extra: - # ssl: true - -dbReplications: false - -# You can configure any number of replicas here -#dbSlaves: -# - -# host: -# port: -# db: -# user: -# pass: -# - -# host: -# port: -# db: -# user: -# pass: - -# ┌─────────────────────┐ -#───┘ Redis configuration └───────────────────────────────────── - -redis: - host: redis - port: 6379 - #family: 0 # 0=Both, 4=IPv4, 6=IPv6 - #pass: example-pass - #prefix: example-prefix - #db: 1 - -#redisForPubsub: -# host: redis -# port: 6379 -# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 -# #pass: example-pass -# #prefix: example-prefix -# #db: 1 - -#redisForJobQueue: -# host: redis -# port: 6379 -# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 -# #pass: example-pass -# #prefix: example-prefix -# #db: 1 - -#redisForTimelines: -# host: redis -# port: 6379 -# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 -# #pass: example-pass -# #prefix: example-prefix -# #db: 1 - -# ┌───────────────────────────┐ -#───┘ MeiliSearch configuration └───────────────────────────── - -# You can set scope to local (default value) or global -# (include notes from remote). - -#meilisearch: -# host: meilisearch -# port: 7700 -# apiKey: '' -# ssl: true -# index: '' -# scope: global - -# ┌───────────────┐ -#───┘ ID generation └─────────────────────────────────────────── - -# You can select the ID generation method. -# You don't usually need to change this setting, but you can -# change it according to your preferences. - -# Available methods: -# aid ... Short, Millisecond accuracy -# aidx ... Millisecond accuracy -# meid ... Similar to ObjectID, Millisecond accuracy -# ulid ... Millisecond accuracy -# objectid ... This is left for backward compatibility - -# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE -# ID SETTINGS AFTER THAT! - -id: 'aidx' - -# ┌─────────────────────┐ -#───┘ Other configuration └───────────────────────────────────── - -# Whether disable HSTS -#disableHsts: true - -# Number of worker processes -#clusterLimit: 1 - -# Job concurrency per worker -# deliverJobConcurrency: 128 -# inboxJobConcurrency: 16 -# relashionshipJobConcurrency: 16 -# What's relashionshipJob?: -# Follow, unfollow, block and unblock(ings) while following-imports, etc. or account migrations. - -# Job rate limiter -# deliverJobPerSec: 128 -# inboxJobPerSec: 32 -# relashionshipJobPerSec: 64 - -# Job attempts -# deliverJobMaxAttempts: 12 -# inboxJobMaxAttempts: 8 - -# Local address used for outgoing requests -#outgoingAddress: 127.0.0.1 - -# IP address family used for outgoing request (ipv4, ipv6 or dual) -#outgoingAddressFamily: ipv4 - -# Amount of characters that can be used when writing notes. Longer notes will be rejected. (minimum: 1) -#maxNoteLength: 3000 -# Amount of characters that will be saved for remote notes. Longer notes will be truncated to this length. (minimum: 1) -#maxRemoteNoteLength: 100000 -# Amount of characters that can be used when writing content warnings. Longer warnings will be rejected. (minimum: 1) -#maxCwLength: 500 -# Amount of characters that will be saved for remote content warnings. Longer warnings will be truncated to this length. (minimum: 1) -#maxRemoteCwLength: 5000 -# Amount of characters that can be used when writing media descriptions (alt text). Longer descriptions will be rejected. (minimum: 1) -#maxAltTextLength: 20000 -# Amount of characters that will be saved for remote media descriptions (alt text). Longer descriptions will be truncated to this length. (minimum: 1) -#maxRemoteAltTextLength: 100000 - -# Proxy for HTTP/HTTPS -#proxy: http://127.0.0.1:3128 - -proxyBypassHosts: - - api.deepl.com - - api-free.deepl.com - - www.recaptcha.net - - hcaptcha.com - - challenges.cloudflare.com - -# Proxy for SMTP/SMTPS -#proxySmtp: http://127.0.0.1:3128 # use HTTP/1.1 CONNECT -#proxySmtp: socks4://127.0.0.1:1080 # use SOCKS4 -#proxySmtp: socks5://127.0.0.1:1080 # use SOCKS5 - -# Media Proxy -#mediaProxy: https://example.com/proxy - -# Proxy remote files (default: true) -# Proxy remote files by this instance or mediaProxy to prevent remote files from running in remote domains. -proxyRemoteFiles: true - -# Movie Thumbnail Generation URL -# There is no reference implementation. -# For example, Misskey will point to the following URL: -# https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4 -#videoThumbnailGenerator: https://example.com - -# Sign outgoing ActivityPub GET request (default: true) -signToActivityPubGet: true -# Sign outgoing ActivityPub Activities (default: true) -# Linked Data signatures are cryptographic signatures attached to each activity to provide proof of authenticity. -# When using authorized fetch, this is often undesired as any signed activity can be forwarded to a blocked instance by relays and other instances. -# This setting allows admins to disable LD signatures for increased privacy, at the expense of fewer relayed activities and additional inbound fetch (GET) requests. -attachLdSignatureForRelays: true -# check that inbound ActivityPub GET requests are signed ("authorized fetch") -checkActivityPubGetSignature: false - -# For security reasons, uploading attachments from the intranet is prohibited, -# but exceptions can be made from the following settings. Default value is "undefined". -# Read changelog to learn more (Improvements of 12.90.0 (2021/09/04)). -#allowedPrivateNetworks: [ -# '127.0.0.1/32' -#] - -#customMOTD: ['Hello World', 'The sharks rule all', 'Shonks'] - -# Upload or download file size limits (bytes) -#maxFileSize: 262144000 - -# CHMod-style permission bits to apply to uploaded files. -# Permission bits are specified as a base-8 string representing User/Group/Other permissions. -# This setting is only useful for custom deployments, such as using a reverse proxy to serve media. -#filePermissionBits: '644' diff --git a/.config/cypress-devcontainer.yml b/.config/cypress-devcontainer.yml deleted file mode 100644 index 342b0f43da..0000000000 --- a/.config/cypress-devcontainer.yml +++ /dev/null @@ -1,229 +0,0 @@ -#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -# Misskey configuration -#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -# ┌─────┐ -#───┘ URL └───────────────────────────────────────────────────── - -# Final accessible URL seen by a user. -url: 'http://misskey.local' - -# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE -# URL SETTINGS AFTER THAT! - -# ┌───────────────────────┐ -#───┘ Port and TLS settings └─────────────────────────────────── - -# -# Misskey requires a reverse proxy to support HTTPS connections. -# -# +----- https://example.tld/ ------------+ -# +------+ |+-------------+ +----------------+| -# | User | ---> || Proxy (443) | ---> | Misskey (3000) || -# +------+ |+-------------+ +----------------+| -# +---------------------------------------+ -# -# You need to set up a reverse proxy. (e.g. nginx) -# An encrypted connection with HTTPS is highly recommended -# because tokens may be transferred in GET requests. - -# The port that your Misskey server should listen on. -port: 61812 - -# ┌──────────────────────────┐ -#───┘ PostgreSQL configuration └──────────────────────────────── - -db: - host: db - port: 5432 - - # Database name - db: misskey - - # Auth - user: postgres - pass: postgres - - # Whether disable Caching queries - #disableCache: true - - # Extra Connection options - #extra: - # ssl: true - -dbReplications: false - -# You can configure any number of replicas here -#dbSlaves: -# - -# host: -# port: -# db: -# user: -# pass: -# - -# host: -# port: -# db: -# user: -# pass: - -# ┌─────────────────────┐ -#───┘ Redis configuration └───────────────────────────────────── - -redis: - host: redis - port: 6379 - #family: 0 # 0=Both, 4=IPv4, 6=IPv6 - #pass: example-pass - #prefix: example-prefix - #db: 1 - -#redisForPubsub: -# host: redis -# port: 6379 -# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 -# #pass: example-pass -# #prefix: example-prefix -# #db: 1 - -#redisForJobQueue: -# host: redis -# port: 6379 -# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 -# #pass: example-pass -# #prefix: example-prefix -# #db: 1 - -#redisForTimelines: -# host: redis -# port: 6379 -# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 -# #pass: example-pass -# #prefix: example-prefix -# #db: 1 - -#redisForReactions: -# host: redis -# port: 6379 -# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 -# #pass: example-pass -# #prefix: example-prefix -# #db: 1 - -# ┌───────────────────────────┐ -#───┘ MeiliSearch configuration └───────────────────────────── - -#meilisearch: -# host: meilisearch -# port: 7700 -# apiKey: '' -# ssl: true -# index: '' - -# ┌───────────────┐ -#───┘ ID generation └─────────────────────────────────────────── - -# You can select the ID generation method. -# You don't usually need to change this setting, but you can -# change it according to your preferences. - -# Available methods: -# aid ... Short, Millisecond accuracy -# aidx ... Millisecond accuracy -# meid ... Similar to ObjectID, Millisecond accuracy -# ulid ... Millisecond accuracy -# objectid ... This is left for backward compatibility - -# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE -# ID SETTINGS AFTER THAT! - -id: 'aidx' - -# ┌────────────────┐ -#───┘ Error tracking └────────────────────────────────────────── - -# Sentry is available for error tracking. -# See the Sentry documentation for more details on options. - -#sentryForBackend: -# enableNodeProfiling: true -# options: -# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' - -#sentryForFrontend: -# options: -# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' - -# ┌─────────────────────┐ -#───┘ Other configuration └───────────────────────────────────── - -# Whether disable HSTS -#disableHsts: true - -# Number of worker processes -#clusterLimit: 1 - -# Job concurrency per worker -# deliverJobConcurrency: 128 -# inboxJobConcurrency: 16 - -# Job rate limiter -# deliverJobPerSec: 128 -# inboxJobPerSec: 32 - -# Job attempts -# deliverJobMaxAttempts: 12 -# inboxJobMaxAttempts: 8 - -# IP address family used for outgoing request (ipv4, ipv6 or dual) -#outgoingAddressFamily: ipv4 - -# Amount of characters that can be used when writing notes. Longer notes will be rejected. (minimum: 1) -#maxNoteLength: 3000 -# Amount of characters that will be saved for remote notes. Longer notes will be truncated to this length. (minimum: 1) -#maxRemoteNoteLength: 100000 -# Amount of characters that can be used when writing content warnings. Longer warnings will be rejected. (minimum: 1) -#maxCwLength: 500 -# Amount of characters that will be saved for remote content warnings. Longer warnings will be truncated to this length. (minimum: 1) -#maxRemoteCwLength: 5000 -# Amount of characters that can be used when writing media descriptions (alt text). Longer descriptions will be rejected. (minimum: 1) -#maxAltTextLength: 20000 -# Amount of characters that will be saved for remote media descriptions (alt text). Longer descriptions will be truncated to this length. (minimum: 1) -#maxRemoteAltTextLength: 100000 - -# Proxy for HTTP/HTTPS -#proxy: http://127.0.0.1:3128 - -proxyBypassHosts: - - api.deepl.com - - api-free.deepl.com - - www.recaptcha.net - - hcaptcha.com - - challenges.cloudflare.com - -# Proxy for SMTP/SMTPS -#proxySmtp: http://127.0.0.1:3128 # use HTTP/1.1 CONNECT -#proxySmtp: socks4://127.0.0.1:1080 # use SOCKS4 -#proxySmtp: socks5://127.0.0.1:1080 # use SOCKS5 - -# Media Proxy -#mediaProxy: https://example.com/proxy - -# Proxy remote files (default: true) -proxyRemoteFiles: true - -# Sign to ActivityPub GET request (default: true) -signToActivityPubGet: true - -allowedPrivateNetworks: [ - '127.0.0.1/32' -] - -# Upload or download file size limits (bytes) -#maxFileSize: 262144000 - -# CHMod-style permission bits to apply to uploaded files. -# Permission bits are specified as a base-8 string representing User/Group/Other permissions. -# This setting is only useful for custom deployments, such as using a reverse proxy to serve media. -#filePermissionBits: '644' diff --git a/.config/docker_example.env b/.config/docker_example.env index c61248da2e..7a0261524b 100644 --- a/.config/docker_example.env +++ b/.config/docker_example.env @@ -1,11 +1,4 @@ -# misskey settings -# MISSKEY_URL=https://example.tld/ - # db settings POSTGRES_PASSWORD=example-misskey-pass -# DATABASE_PASSWORD=${POSTGRES_PASSWORD} POSTGRES_USER=example-misskey-user -# DATABASE_USER=${POSTGRES_USER} POSTGRES_DB=misskey -# DATABASE_DB=${POSTGRES_DB} -DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}" diff --git a/.config/docker_example.yml b/.config/docker_example.yml index ce2daf3aec..6d82fdcc79 100644 --- a/.config/docker_example.yml +++ b/.config/docker_example.yml @@ -2,68 +2,10 @@ # Misskey configuration #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -# ┌──────────────────────────────┐ -#───┘ a boring but important thing └──────────────────────────── - -# -# First of all, let me tell you a story that may possibly be -# boring to you and possibly important to you. -# -# Misskey is licensed under the AGPLv3 license. This license is -# known to be often misunderstood. Please read the following -# instructions carefully and select the appropriate option so -# that you do not negligently cause a license violation. -# - -# -------- -# Option 1: If you host Misskey AS-IS (without any changes to -# the source code. forks are not included). -# -# Step 1: Congratulations! You don't need to do anything. - -# -------- -# Option 2: If you have made changes to the source code (forks -# are included) and publish a Git repository of source -# code. There should be no access restrictions on -# this repository. Strictly speaking, it doesn't have -# to be a Git repository, but you'll probably use Git! -# -# Step 1: Build and run the Misskey server first. -# Step 2: Open in -# your browser with the administrator account. -# Step 3: Enter the URL of your Git repository in the -# "Repository URL" field. - -# -------- -# Option 3: If neither of the above applies to you. -# (In this case, the source code should be published -# on the Misskey interface. IT IS NOT ENOUGH TO -# DISCLOSE THE SOURCE CODE WEHN A USER REQUESTS IT BY -# E-MAIL OR OTHER MEANS. If you are not satisfied -# with this, it is recommended that you read the -# license again carefully. Anyway, enabling this -# option will automatically generate and publish a -# tarball at build time, protecting you from -# inadvertent license violations. (There is no legal -# guarantee, of course.) The tarball will generated -# from the root directory of your codebase. So it is -# also recommended to check directory -# once after building and before activating the server -# to avoid ACCIDENTAL LEAKING OF SENSITIVE INFORMATION. -# To prevent certain files from being included in the -# tarball, add a glob pattern after line 15 in -# . DO NOT FORGET TO BUILD AFTER -# ENABLING THIS OPTION!) -# -# Step 1: Uncomment the following line. -# -# publishTarballInsteadOfProvideRepositoryUrl: true - # ┌─────┐ #───┘ URL └───────────────────────────────────────────────────── # Final accessible URL seen by a user. -# You can set url from an environment variable instead. url: https://example.tld/ # ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE @@ -96,11 +38,9 @@ db: port: 5432 # Database name - # You can set db from an environment variable instead. db: misskey # Auth - # You can set user and pass from environment variables instead. user: example-misskey-user pass: example-misskey-pass @@ -163,14 +103,6 @@ redis: # #prefix: example-prefix # #db: 1 -#redisForReactions: -# host: redis -# port: 6379 -# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 -# #pass: example-pass -# #prefix: example-prefix -# #db: 1 - # ┌───────────────────────────┐ #───┘ MeiliSearch configuration └───────────────────────────── @@ -204,21 +136,6 @@ redis: id: 'aidx' -# ┌────────────────┐ -#───┘ Error tracking └────────────────────────────────────────── - -# Sentry is available for error tracking. -# See the Sentry documentation for more details on options. - -#sentryForBackend: -# enableNodeProfiling: true -# options: -# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' - -#sentryForFrontend: -# options: -# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' - # ┌─────────────────────┐ #───┘ Other configuration └───────────────────────────────────── @@ -231,14 +148,14 @@ id: 'aidx' # Job concurrency per worker # deliverJobConcurrency: 128 # inboxJobConcurrency: 16 -# relationshipJobConcurrency: 16 -# What's relationshipJob?: +# relashionshipJobConcurrency: 16 +# What's relashionshipJob?: # Follow, unfollow, block and unblock(ings) while following-imports, etc. or account migrations. # Job rate limiter # deliverJobPerSec: 128 # inboxJobPerSec: 32 -# relationshipJobPerSec: 64 +# relashionshipJobPerSec: 64 # Job attempts # deliverJobMaxAttempts: 12 @@ -250,18 +167,8 @@ id: 'aidx' # IP address family used for outgoing request (ipv4, ipv6 or dual) #outgoingAddressFamily: ipv4 -# Amount of characters that can be used when writing notes. Longer notes will be rejected. (minimum: 1) -#maxNoteLength: 3000 -# Amount of characters that will be saved for remote notes. Longer notes will be truncated to this length. (minimum: 1) -#maxRemoteNoteLength: 100000 -# Amount of characters that can be used when writing content warnings. Longer warnings will be rejected. (minimum: 1) -#maxCwLength: 500 -# Amount of characters that will be saved for remote content warnings. Longer warnings will be truncated to this length. (minimum: 1) -#maxRemoteCwLength: 5000 -# Amount of characters that can be used when writing media descriptions (alt text). Longer descriptions will be rejected. (minimum: 1) -#maxAltTextLength: 20000 -# Amount of characters that will be saved for remote media descriptions (alt text). Longer descriptions will be truncated to this length. (minimum: 1) -#maxRemoteAltTextLength: 100000 +# Amount of characters that can be used when writing notes (maximum: 8192, minimum: 1) +maxNoteLength: 3000 # Proxy for HTTP/HTTPS #proxy: http://127.0.0.1:3128 @@ -291,13 +198,13 @@ proxyRemoteFiles: true # https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4 #videoThumbnailGenerator: https://example.com -# Sign outgoing ActivityPub GET request (default: true) +# Enables the built-in thumbnail generator for remote videos. (default: false) +# Only useful if "Cache remote files" is disabled, and "videoThumbnailGenerator" is unset. +# Without it, remote video files that are not cached will not have any thumbnails. +#enableBuiltinVideoThumbnailGenerator: false + +# Sign to ActivityPub GET request (default: true) signToActivityPubGet: true -# Sign outgoing ActivityPub Activities (default: true) -# Linked Data signatures are cryptographic signatures attached to each activity to provide proof of authenticity. -# When using authorized fetch, this is often undesired as any signed activity can be forwarded to a blocked instance by relays and other instances. -# This setting allows admins to disable LD signatures for increased privacy, at the expense of fewer relayed activities and additional inbound fetch (GET) requests. -attachLdSignatureForRelays: true # check that inbound ActivityPub GET requests are signed ("authorized fetch") checkActivityPubGetSignature: false @@ -312,8 +219,3 @@ checkActivityPubGetSignature: false # Upload or download file size limits (bytes) #maxFileSize: 262144000 - -# CHMod-style permission bits to apply to uploaded files. -# Permission bits are specified as a base-8 string representing User/Group/Other permissions. -# This setting is only useful for custom deployments, such as using a reverse proxy to serve media. -#filePermissionBits: '644' diff --git a/.config/example.yml b/.config/example.yml index 9debb3bf70..183331ef63 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -2,63 +2,6 @@ # Misskey configuration #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -# ┌──────────────────────────────┐ -#───┘ a boring but important thing └──────────────────────────── - -# -# First of all, let me tell you a story that may possibly be -# boring to you and possibly important to you. -# -# Misskey is licensed under the AGPLv3 license. This license is -# known to be often misunderstood. Please read the following -# instructions carefully and select the appropriate option so -# that you do not negligently cause a license violation. -# - -# -------- -# Option 1: If you host Misskey AS-IS (without any changes to -# the source code. forks are not included). -# -# Step 1: Congratulations! You don't need to do anything. - -# -------- -# Option 2: If you have made changes to the source code (forks -# are included) and publish a Git repository of source -# code. There should be no access restrictions on -# this repository. Strictly speaking, it doesn't have -# to be a Git repository, but you'll probably use Git! -# -# Step 1: Build and run the Misskey server first. -# Step 2: Open in -# your browser with the administrator account. -# Step 3: Enter the URL of your Git repository in the -# "Repository URL" field. - -# -------- -# Option 3: If neither of the above applies to you. -# (In this case, the source code should be published -# on the Misskey interface. IT IS NOT ENOUGH TO -# DISCLOSE THE SOURCE CODE WHEN A USER REQUESTS IT BY -# E-MAIL OR OTHER MEANS. If you are not satisfied -# with this, it is recommended that you read the -# license again carefully. Anyway, enabling this -# option will automatically generate and publish a -# tarball at build time, protecting you from -# inadvertent license violations. (There is no legal -# guarantee, of course.) The tarball will generated -# from the root directory of your codebase. So it is -# also recommended to check directory -# once after building and before activating the server -# to avoid ACCIDENTAL LEAKING OF SENSITIVE INFORMATION. -# To prevent certain files from being included in the -# tarball, add a glob pattern after line 15 in -# . DO NOT FORGET TO BUILD AFTER -# ENABLING THIS OPTION!) -# -# Step 1: Uncomment the following line. -# -# publishTarballInsteadOfProvideRepositoryUrl: true - # ┌─────┐ #───┘ URL └───────────────────────────────────────────────────── @@ -99,10 +42,10 @@ db: port: 5432 # Database name - db: sharkey + db: misskey # Auth - user: sharkey + user: example-misskey-user pass: example-misskey-pass # Whether disable Caching queries @@ -172,16 +115,6 @@ redis: # # You can specify more ioredis options... # #username: example-username -#redisForReactions: -# host: localhost -# port: 6379 -# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 -# #pass: example-pass -# #prefix: example-prefix -# #db: 1 -# # You can specify more ioredis options... -# #username: example-username - # ┌───────────────────────────┐ #───┘ MeiliSearch configuration └───────────────────────────── @@ -215,21 +148,6 @@ redis: id: 'aidx' -# ┌────────────────┐ -#───┘ Error tracking └────────────────────────────────────────── - -# Sentry is available for error tracking. -# See the Sentry documentation for more details on options. - -#sentryForBackend: -# enableNodeProfiling: true -# options: -# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' - -#sentryForFrontend: -# options: -# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' - # ┌─────────────────────┐ #───┘ Other configuration └───────────────────────────────────── @@ -242,14 +160,14 @@ id: 'aidx' # Job concurrency per worker #deliverJobConcurrency: 128 #inboxJobConcurrency: 16 -#relationshipJobConcurrency: 16 -# What's relationshipJob?: +#relashionshipJobConcurrency: 16 +# What's relashionshipJob?: # Follow, unfollow, block and unblock(ings) while following-imports, etc. or account migrations. # Job rate limiter #deliverJobPerSec: 128 #inboxJobPerSec: 32 -#relationshipJobPerSec: 64 +#relashionshipJobPerSec: 64 # Job attempts #deliverJobMaxAttempts: 12 @@ -261,18 +179,8 @@ id: 'aidx' # IP address family used for outgoing request (ipv4, ipv6 or dual) #outgoingAddressFamily: ipv4 -# Amount of characters that can be used when writing notes. Longer notes will be rejected. (minimum: 1) -#maxNoteLength: 3000 -# Amount of characters that will be saved for remote notes. Longer notes will be truncated to this length. (minimum: 1) -#maxRemoteNoteLength: 100000 -# Amount of characters that can be used when writing content warnings. Longer warnings will be rejected. (minimum: 1) -#maxCwLength: 500 -# Amount of characters that will be saved for remote content warnings. Longer warnings will be truncated to this length. (minimum: 1) -#maxRemoteCwLength: 5000 -# Amount of characters that can be used when writing media descriptions (alt text). Longer descriptions will be rejected. (minimum: 1) -#maxAltTextLength: 20000 -# Amount of characters that will be saved for remote media descriptions (alt text). Longer descriptions will be truncated to this length. (minimum: 1) -#maxRemoteAltTextLength: 100000 +# Amount of characters that can be used when writing notes (maximum: 8192, minimum: 1) +maxNoteLength: 3000 # Proxy for HTTP/HTTPS #proxy: http://127.0.0.1:3128 @@ -305,13 +213,13 @@ proxyRemoteFiles: true # https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4 #videoThumbnailGenerator: https://example.com -# Sign outgoing ActivityPub GET request (default: true) +# Enables the built-in thumbnail generator for remote videos. (default: false) +# Only useful if "Cache remote files" is disabled, and "videoThumbnailGenerator" is unset. +# Without it, remote video files that are not cached will not have any thumbnails. +#enableBuiltinVideoThumbnailGenerator: false + +# Sign to ActivityPub GET request (default: true) signToActivityPubGet: true -# Sign outgoing ActivityPub Activities (default: true) -# Linked Data signatures are cryptographic signatures attached to each activity to provide proof of authenticity. -# When using authorized fetch, this is often undesired as any signed activity can be forwarded to a blocked instance by relays and other instances. -# This setting allows admins to disable LD signatures for increased privacy, at the expense of fewer relayed activities and additional inbound fetch (GET) requests. -attachLdSignatureForRelays: true # check that inbound ActivityPub GET requests are signed ("authorized fetch") checkActivityPubGetSignature: false @@ -327,15 +235,5 @@ checkActivityPubGetSignature: false # Upload or download file size limits (bytes) #maxFileSize: 262144000 -# timeout and maximum size for imports (e.g. note imports) -#import: -# downloadTimeout: 30 -# maxFileSize: 262144000 - # PID File of master process #pidFile: /tmp/misskey.pid - -# CHMod-style permission bits to apply to uploaded files. -# Permission bits are specified as a base-8 string representing User/Group/Other permissions. -# This setting is only useful for custom deployments, such as using a reverse proxy to serve media. -#filePermissionBits: '644' diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index fbf959d449..e409adf644 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,22 +1,25 @@ { "name": "Misskey", - "dockerComposeFile": "compose.yml", + "dockerComposeFile": "docker-compose.yml", "service": "app", "workspaceFolder": "/workspace", "features": { - "ghcr.io/devcontainers/features/node:1": { - "version": "20.16.0" + "ghcr.io/devcontainers-contrib/features/pnpm:2": { + "version": "8.9.2" }, - "ghcr.io/devcontainers-contrib/features/corepack:1": {} + "ghcr.io/devcontainers/features/node:1": { + "version": "20.10.0" + } }, "forwardPorts": [3000], - "postCreateCommand": "/bin/bash .devcontainer/init.sh", + "postCreateCommand": "sudo chmod 755 .devcontainer/init.sh && .devcontainer/init.sh", "customizations": { "vscode": { "extensions": [ "editorconfig.editorconfig", "dbaeumer.vscode-eslint", "Vue.volar", + "Vue.vscode-typescript-vue-plugin", "Orta.vscode-jest", "dbaeumer.vscode-eslint", "mrmlnc.vscode-json5" diff --git a/.devcontainer/devcontainer.yml b/.devcontainer/devcontainer.yml index 3eb4fc2879..7ea0929469 100644 --- a/.devcontainer/devcontainer.yml +++ b/.devcontainer/devcontainer.yml @@ -103,14 +103,6 @@ redis: # #prefix: example-prefix # #db: 1 -#redisForReactions: -# host: redis -# port: 6379 -# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 -# #pass: example-pass -# #prefix: example-prefix -# #db: 1 - # ┌───────────────────────────┐ #───┘ MeiliSearch configuration └───────────────────────────── @@ -140,21 +132,6 @@ redis: id: 'aidx' -# ┌────────────────┐ -#───┘ Error tracking └────────────────────────────────────────── - -# Sentry is available for error tracking. -# See the Sentry documentation for more details on options. - -#sentryForBackend: -# enableNodeProfiling: true -# options: -# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' - -#sentryForFrontend: -# options: -# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' - # ┌─────────────────────┐ #───┘ Other configuration └───────────────────────────────────── diff --git a/.devcontainer/compose.yml b/.devcontainer/docker-compose.yml similarity index 93% rename from .devcontainer/compose.yml rename to .devcontainer/docker-compose.yml index d02d2a8f4a..2809cd2ca4 100644 --- a/.devcontainer/compose.yml +++ b/.devcontainer/docker-compose.yml @@ -1,3 +1,5 @@ +version: '3.8' + services: app: build: @@ -6,7 +8,6 @@ services: volumes: - ../:/workspace:cached - - node_modules:/workspace/node_modules command: sleep infinity @@ -45,7 +46,6 @@ services: volumes: postgres-data: redis-data: - node_modules: networks: internal_network: diff --git a/.devcontainer/init.sh b/.devcontainer/init.sh index e02a533c15..bcad3e6d85 100755 --- a/.devcontainer/init.sh +++ b/.devcontainer/init.sh @@ -2,16 +2,10 @@ set -xe -sudo chown node node_modules -sudo apt-get update -sudo apt-get -y install libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2 libxtst6 xauth xvfb -git config --global --add safe.directory /workspace +sudo chown -R node /workspace git submodule update --init -corepack install -corepack enable pnpm config set store-dir /home/node/.local/share/pnpm/store pnpm install --frozen-lockfile cp .devcontainer/devcontainer.yml .config/default.yml pnpm build pnpm migrate -pnpm exec cypress install diff --git a/.dockerignore b/.dockerignore index f204349160..1de0c7982b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -7,11 +7,12 @@ Dockerfile build/ built/ db/ -.devcontainer/compose.yml +docker-compose.yml node_modules/ packages/*/node_modules redis/ files/ +misskey-assets/ fluent-emojis/ .pnp.* @@ -27,4 +28,4 @@ fluent-emojis/ .idea/ packages/*/.vscode/ -packages/backend/test/compose.yml +packages/backend/test/docker-compose.yml diff --git a/.forgejo/workflows/docker-develop.yml b/.forgejo/workflows/docker-develop.yml new file mode 100644 index 0000000000..0c8338c4df --- /dev/null +++ b/.forgejo/workflows/docker-develop.yml @@ -0,0 +1,58 @@ +name: Publish Docker image (develop) + +on: + push: + branches: + - develop + paths: + - packages/** + - locales/** + workflow_dispatch: + +env: + REGISTRY: git.joinsharkey.org + +jobs: + push_to_registry: + name: Push Docker image to GHCR + runs-on: docker + steps: + - name: install packages + run: apt-get update && apt-get install -y wget git curl + - uses: https://code.forgejo.org/actions/setup-node@v3 + with: + node-version: 20 + - name: Install docker + run: | + echo deb http://deb.debian.org/debian bullseye-backports main | tee /etc/apt/sources.list.d/backports.list && apt-get -qq update + DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -qq -y -t bullseye-backports docker.io + - name: Check out the repo + uses: actions/checkout@v4.1.1 + - name: Set up Docker Buildx + id: buildx + uses: https://github.com/docker/setup-buildx-action@v3.0.0 + with: + platforms: linux/amd64,linux/arm64 + - name: Docker meta + id: meta + uses: https://github.com/docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/sharkey/sharkey + - name: Log in to GHCR + uses: https://github.com/docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: Marie + password: ${{ secrets.TOKEN }} + - name: Build and Push to GHCR + id: build + uses: https://github.com/docker/build-push-action@v5 + with: + builder: ${{ steps.buildx.outputs.name }} + context: . + push: true + platforms: ${{ steps.buildx.outputs.platforms }} + provenance: false + tags: ${{ env.REGISTRY }}/sharkey/sharkey:develop + labels: develop + build-args: NODE_ENV=development \ No newline at end of file diff --git a/.forgejo/workflows/docker.yml b/.forgejo/workflows/docker.yml new file mode 100644 index 0000000000..155c5f7deb --- /dev/null +++ b/.forgejo/workflows/docker.yml @@ -0,0 +1,62 @@ +name: Publish Docker image + +on: + release: + types: [published] + workflow_dispatch: + +env: + REGISTRY: git.joinsharkey.org + +jobs: + push_to_registry: + name: Push Docker image to GHCR + runs-on: docker + + steps: + - name: install packages + run: apt-get update && apt-get install -y wget git curl + - uses: https://code.forgejo.org/actions/setup-node@v3 + with: + node-version: 20 + - name: Install docker + run: | + echo deb http://deb.debian.org/debian bullseye-backports main | tee /etc/apt/sources.list.d/backports.list && apt-get -qq update + DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -qq -y -t bullseye-backports docker.io + - name: Check out the repo + uses: actions/checkout@v4.1.1 + - name: Set up Docker Buildx + id: buildx + uses: https://github.com/docker/setup-buildx-action@v3.0.0 + with: + platforms: linux/amd64,linux/arm64 + - name: Docker meta + id: meta + uses: https://github.com/docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/sharkey/sharkey + tags: | + type=edge + type=ref,event=pr + type=ref,event=branch + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=raw,value=stable + - name: Log in to GHCR + uses: https://github.com/docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: Marie + password: ${{ secrets.TOKEN }} + - name: Build and Push to GHCR + id: build + uses: https://github.com/docker/build-push-action@v5 + with: + builder: ${{ steps.buildx.outputs.name }} + context: . + push: true + platforms: ${{ steps.buildx.outputs.platforms }} + provenance: false + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/.forgejo/workflows/lint.yml b/.forgejo/workflows/lint.yml new file mode 100644 index 0000000000..0a773d5fb0 --- /dev/null +++ b/.forgejo/workflows/lint.yml @@ -0,0 +1,85 @@ +name: Lint + +on: + push: + branches: + - stable + - develop + paths: + - packages/** + pull_request: + +jobs: + pnpm_install: + runs-on: docker + steps: + - uses: actions/checkout@v4.1.1 + with: + fetch-depth: 0 + submodules: true + - uses: https://github.com/pnpm/action-setup@v2 + with: + version: 8 + run_install: false + - uses: https://code.forgejo.org/actions/setup-node@v4 + with: + node-version-file: '.node-version' + cache: 'pnpm' + - run: corepack enable + - run: pnpm i --frozen-lockfile + + lint: + needs: [pnpm_install] + runs-on: docker + continue-on-error: true + strategy: + matrix: + workspace: + - backend + - frontend + - sw + - misskey-js + steps: + - uses: actions/checkout@v4.1.1 + with: + fetch-depth: 0 + submodules: true + - uses: https://github.com/pnpm/action-setup@v2 + with: + version: 7 + run_install: false + - uses: https://code.forgejo.org/actions/setup-node@v4 + with: + node-version-file: '.node-version' + cache: 'pnpm' + - run: corepack enable + - run: pnpm i --frozen-lockfile + - run: pnpm --filter ${{ matrix.workspace }} run eslint + + typecheck: + needs: [pnpm_install] + runs-on: docker + continue-on-error: true + strategy: + matrix: + workspace: + - backend + - misskey-js + steps: + - uses: actions/checkout@v4.1.1 + with: + fetch-depth: 0 + submodules: true + - uses: https://github.com/pnpm/action-setup@v2 + with: + version: 7 + run_install: false + - uses: https://code.forgejo.org/actions/setup-node@v4 + with: + node-version-file: '.node-version' + cache: 'pnpm' + - run: corepack enable + - run: pnpm i --frozen-lockfile + - run: pnpm --filter misskey-js run build + if: ${{ matrix.workspace == 'backend' }} + - run: pnpm --filter ${{ matrix.workspace }} run typecheck diff --git a/.gitea/ISSUE_TEMPLATE/01_bug-report.yml b/.gitea/ISSUE_TEMPLATE/01_bug-report.yml new file mode 100644 index 0000000000..6282cc43f9 --- /dev/null +++ b/.gitea/ISSUE_TEMPLATE/01_bug-report.yml @@ -0,0 +1,97 @@ +name: 🐛 Bug Report +description: Create a report to help us improve +title: 'bug: ' + +body: + - type: markdown + attributes: + value: | + Thanks for reporting! + First, in order to avoid duplicate Issues, please search to see if the problem you found has already been reported. + Also, If you are NOT owner/admin of server, PLEASE DONT REPORT SERVER SPECIFIC ISSUES TO HERE! (e.g. feature XXX is not working in misskey.example) Please try with another misskey servers, and if your issue is only reproducible with specific server, contact your server's owner/admin first. + + - type: textarea + attributes: + label: 💡 Summary + description: Tell us what the bug is + validations: + required: true + + - type: textarea + attributes: + label: 🥰 Expected Behavior + description: Tell us what should happen + validations: + required: true + + - type: textarea + attributes: + label: 🤬 Actual Behavior + description: | + Tell us what happens instead of the expected behavior. + Please include errors from the developer console and/or server log files if you have access to them. + validations: + required: true + + - type: textarea + attributes: + label: 📝 Steps to Reproduce + placeholder: | + 1. + 2. + 3. + validations: + required: false + + - type: textarea + attributes: + label: 💻 Frontend Environment + description: | + Tell us where on the platform it happens + DO NOT WRITE "latest". Please provide the specific version. + + Examples: + * Model and OS of the device(s): MacBook Pro (14inch, 2021), macOS Ventura 13.4 + * Browser: Chrome 113.0.5672.126 + * Server URL: misskey.io + * Misskey: 13.x.x + value: | + * Model and OS of the device(s): + * Browser: + * Server URL: + * Misskey: + render: markdown + validations: + required: false + + - type: textarea + attributes: + label: 🛰 Backend Environment (for server admin) + description: | + Tell us where on the platform it happens + DO NOT WRITE "latest". Please provide the specific version. + If you are using a managed service, put that after the version. + + Examples: + * Installation Method or Hosting Service: docker compose, k8s/docker, systemd, "Misskey install shell script", development environment + * Misskey: 13.x.x + * Node: 20.x.x + * PostgreSQL: 15.x.x + * Redis: 7.x.x + * OS and Architecture: Ubuntu 22.04.2 LTS aarch64 + value: | + * Installation Method or Hosting Service: + * Misskey: + * Node: + * PostgreSQL: + * Redis: + * OS and Architecture: + render: markdown + validations: + required: false + + - type: checkboxes + attributes: + label: Do you want to address this bug yourself? + options: + - label: Yes, I will patch the bug myself and send a pull request diff --git a/.gitea/ISSUE_TEMPLATE/02_feature-request.yml b/.gitea/ISSUE_TEMPLATE/02_feature-request.yml new file mode 100644 index 0000000000..d3bf64d869 --- /dev/null +++ b/.gitea/ISSUE_TEMPLATE/02_feature-request.yml @@ -0,0 +1,22 @@ +name: ✨ Feature Request +description: Suggest an idea for this project +title: 'feat: ' + +body: + - type: textarea + attributes: + label: Summary + description: Tell us what the suggestion is + validations: + required: true + - type: textarea + attributes: + label: Purpose + description: Describe the specific problem or need you think this feature will solve, and who it will help. + validations: + required: true + - type: checkboxes + attributes: + label: Do you want to implement this feature yourself? + options: + - label: Yes, I will implement this by myself and send a pull request \ No newline at end of file diff --git a/.gitea/ISSUE_TEMPLATE/config.yml b/.gitea/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..b845c1c9ac --- /dev/null +++ b/.gitea/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,4 @@ +contact_links: + - name: 💬 Transfem.org Discord + url: https://discord.gg/HJcAanTR6H + about: Chat freely about Sharkey diff --git a/.gitea/pull_request_template.md b/.gitea/pull_request_template.md new file mode 100644 index 0000000000..63eb2ab623 --- /dev/null +++ b/.gitea/pull_request_template.md @@ -0,0 +1,24 @@ + + +## What + + + +## Why + + + +## Additional info (optional) + + + +## Checklist +- [ ] Read the [contribution guide](https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md) +- [ ] Test working in a local environment +- [ ] (If needed) Add story of storybook +- [ ] (If needed) Update CHANGELOG.md +- [ ] (If possible) Add tests \ No newline at end of file diff --git a/.gitignore b/.gitignore index 7cc7354a4a..4816375a4f 100644 --- a/.gitignore +++ b/.gitignore @@ -23,9 +23,6 @@ packages/sw/.yarn/cache # pnpm .pnpm-store -# eslint -**/.eslintcache - # Cypress cypress/screenshots cypress/videos @@ -38,17 +35,12 @@ coverage !/.config/example.yml !/.config/docker_example.yml !/.config/docker_example.env -!/.config/cypress-devcontainer.yml docker-compose.yml -compose.yml -.devcontainer/compose.yml -!/.devcontainer/compose.yml +!/.devcontainer/docker-compose.yml # misskey /build built -built-test -js-built /data /.cache-loader /db @@ -62,15 +54,13 @@ api-docs.json *.code-workspace .DS_Store /files +/cache ormconfig.json temp /packages/frontend/src/**/*.stories.ts -tsdoc-metadata.json -misskey-assets -# Vite temporary files -vite.config.js.timestamp-* -vite.config.ts.timestamp-* +# Sharkey +/packages/megalodon/lib # blender backups *.blend1 @@ -81,6 +71,3 @@ vite.config.ts.timestamp-* # VSCode addon .favorites.json - -# Sharkey -/packages/megalodon/lib diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 4db8bda32e..0000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,114 +0,0 @@ -stages: - - test - - deploy - -testCommit: - stage: test - image: node:iron - services: - - postgres:15 - - redis - variables: - POSTGRES_PASSWORD: ci - script: - - apt-get update && apt-get install -y git wget curl build-essential python3 ffmpeg - - cp .config/ci.yml .config/default.yml - - cp .config/ci.yml .config/test.yml - - corepack enable - - corepack prepare pnpm@latest --activate - - git submodule update --init - - pnpm install --frozen-lockfile - - pnpm run build - - pnpm run migrate - - pnpm run --filter='!megalodon' test - - pnpm run --filter=backend --filter=misskey-js lint - - pnpm run --filter=frontend --filter=frontend-embed eslint - cache: - key: test - policy: pull-push - when: on_success - paths: - - node_modules/ - - packages/*/node_modules/ - only: - - develop - - merge_requests - - stable - -getImageTag: - stage: deploy - image: ubuntu:latest - script: - - apt-get update && apt-get install -y jq - - | - if test -n "$CI_COMMIT_TAG"; then - tag="$CI_COMMIT_TAG" - elif test "$CI_COMMIT_BRANCH" == "stable"; then - tag="latest" - elif test "$CI_COMMIT_BRANCH" == "develop"; then - tag="develop" - else - tag="$CI_COMMIT_BRANCH" - fi - version=$(cat package.json | jq -r '.version') - - echo "REGISTRY_PUSH_TAG=$tag" >> build.env - - echo "REGISTRY_PUSH_VERSION=$version" >> build.env - artifacts: - reports: - dotenv: build.env - only: - - stable - - develop - - tags - -buildDocker: - stage: deploy - needs: - - job: getImageTag - artifacts: true - parallel: - matrix: - - ARCH: amd64 - - ARCH: arm64 - tags: - - ${ARCH} - image: - name: gcr.io/kaniko-project/executor:debug - entrypoint: [""] - script: - - >- - /kaniko/executor - --context "${CI_PROJECT_DIR}" - --dockerfile "${CI_PROJECT_DIR}/Dockerfile" - --destination "${CI_REGISTRY_IMAGE}:${REGISTRY_PUSH_VERSION}-${ARCH}" - only: - - stable - - develop - - tags - -mergeManifests: - stage: deploy - needs: - - job: buildDocker - artifacts: false - - job: getImageTag - artifacts: true - tags: - - docker - image: - name: mplatform/manifest-tool:alpine - entrypoint: [""] - script: - - >- - manifest-tool - --username=${CI_REGISTRY_USER} - --password=${CI_REGISTRY_PASSWORD} - push from-args - --platforms linux/amd64,linux/arm64 - --tags ${REGISTRY_PUSH_VERSION} - --template ${CI_REGISTRY_IMAGE}:${REGISTRY_PUSH_VERSION}-ARCH - --target ${CI_REGISTRY_IMAGE}:${REGISTRY_PUSH_TAG} - only: - - stable - - develop - - tags diff --git a/.gitlab/issue_templates/bug.md b/.gitlab/issue_templates/bug.md deleted file mode 100644 index a909067269..0000000000 --- a/.gitlab/issue_templates/bug.md +++ /dev/null @@ -1,35 +0,0 @@ - - -# **What happened?** - - -# **What did you expect to happen?** - - -# **Version** - - -# **Instance** - - -# **What type of issue is this?** - - -# **What browser are you using? (Client-side issues only)** - -# **What operating system are you using? (Client-side issues only)** - -# **How do you deploy Sharkey on your server? (Server-side issues only)** - -# **What operating system are you using? (Server-side issues only)** - -# **Relevant log output** - - -# **Contribution Guidelines** -By submitting this issue, you agree to follow our [Contribution Guidelines](https://activitypub.software/TransFem-org/Sharkey/-/blob/develop/CONTRIBUTING.md) -- [ ] I agree to follow this project's Contribution Guidelines -- [ ] I have searched the issue tracker for similar issues, and this is not a duplicate. diff --git a/.gitlab/issue_templates/feature.md b/.gitlab/issue_templates/feature.md deleted file mode 100644 index a77f9335fe..0000000000 --- a/.gitlab/issue_templates/feature.md +++ /dev/null @@ -1,21 +0,0 @@ - - -# **What feature would you like implemented?** - - -# **Why should we add this feature?** - - -# **Version** - - -# **Instance** - - -# **Contribution Guidelines** -By submitting this issue, you agree to follow our [Contribution Guidelines](https://activitypub.software/TransFem-org/Sharkey/-/blob/develop/CONTRIBUTING.md) -- [ ] I agree to follow this project's Contribution Guidelines -- [ ] I have searched the issue tracker for similar requests, and this is not a duplicate. diff --git a/.gitlab/merge_request_templates/default.md b/.gitlab/merge_request_templates/default.md deleted file mode 100644 index e6977def70..0000000000 --- a/.gitlab/merge_request_templates/default.md +++ /dev/null @@ -1,12 +0,0 @@ - - -# **What does this MR do?** - - -# **Contribution Guidelines** -By submitting this merge request, you agree to follow our [Contribution Guidelines](https://activitypub.software/TransFem-org/Sharkey/-/blob/develop/CONTRIBUTING.md) -- [ ] I agree to follow this project's Contribution Guidelines -- [ ] I have made sure to test this merge request - - - diff --git a/.gitmodules b/.gitmodules index 1a68b48180..225a69a652 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ +[submodule "misskey-assets"] + path = misskey-assets + url = https://github.com/misskey-dev/assets.git [submodule "fluent-emojis"] path = fluent-emojis url = https://github.com/misskey-dev/emojis.git -[submodule "tossface-emojis"] - path = tossface-emojis - url = https://activitypub.software/TransFem-org/tossface-emojis.git diff --git a/.node-version b/.node-version index 8ce7030825..d5a159609d 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -20.16.0 +20.10.0 diff --git a/.npmrc b/.npmrc index b949431c77..da702c3af5 100644 --- a/.npmrc +++ b/.npmrc @@ -1,2 +1,2 @@ -@transfem-org:registry=https://activitypub.software/api/v4/packages/npm/ +@sharkey:registry=https://git.joinsharkey.org/api/packages/Sharkey/npm/ engine-strict = true diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 3cdf81e339..baca8db246 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -3,7 +3,9 @@ "editorconfig.editorconfig", "dbaeumer.vscode-eslint", "Vue.volar", + "Vue.vscode-typescript-vue-plugin", "Orta.vscode-jest", + "dbaeumer.vscode-eslint", "mrmlnc.vscode-json5" ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 0ceec23acd..e2a82b1ffe 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,7 +7,7 @@ "*.test.ts": "typescript" }, "jest.jestCommandLine": "pnpm run jest", - "jest.runMode": "on-demand", + "jest.autoRun": "off", "editor.codeActionsOnSave": { "source.fixAll": "explicit" }, diff --git a/CHANGELOG.md b/CHANGELOG.md index cf0437e51a..15845124b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,465 +1,16 @@ -## 2024.9.0 - -### General -- Feat: ノート単体・ユーザーのノート・クリップのノートの埋め込み機能 - - 埋め込みコードやウェブサイトへの実装方法の詳細は https://misskey-hub.net/docs/for-users/features/embed/ をご覧ください -- Feat: パスキーでログインボタンを実装 (#14574) -- Feat: フォローされた際のメッセージを設定できるように -- Feat: 連合をホワイトリスト制にできるように -- Feat: UserWebhookとSystemWebhookのテスト送信機能を追加 (#14445) -- Feat: モデレーターはユーザーにかかわらずファイルが添付されているノートを検索できるように - (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/680) -- Feat: データエクスポートが完了した際に通知を発行するように -- Enhance: ユーザーによるコンテンツインポートの可否をロールポリシーで制御できるように -- Enhance: 依存関係の更新 -- Enhance: l10nの更新 - -### Client -- Enhance: サイズ制限を超過するファイルをアップロードしようとした際にエラーを出すように -- Enhance: アイコンデコレーション管理画面にプレビューを追加 -- Enhance: コントロールパネル内のファイル一覧でセンシティブなファイルを区別しやすく -- Enhance: ScratchpadにUIインスペクターを追加 -- Enhance: Play編集画面の項目の並びを少しリデザイン -- Enhance: 各種メニューをドロワー表示するかどうか設定可能に -- Enhance: AiScriptのMk:C:containerのオプションに`borderStyle`と`borderRadius`を追加 -- Enhance: CWでも絵文字をクリックしてメニューを表示できるように -- Fix: サーバーメトリクスが2つ以上あるとリロード直後の表示がおかしくなる問題を修正 -- Fix: コントロールパネル内のAp requests内のチャートの表示がおかしかった問題を修正 -- Fix: 月の違う同じ日はセパレータが表示されないのを修正 -- Fix: タッチ画面でレンジスライダーを操作するとツールチップが複数表示される問題を修正 - (Cherry-picked from https://github.com/taiyme/misskey/pull/265) -- Fix: 縦横比が極端なカスタム絵文字を表示する際にレイアウトが崩れる箇所があるのを修正 - (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/725) -- Fix: 設定変更時のリロード確認ダイアログが複数個表示されることがある問題を修正 -- Fix: ファイルの詳細ページのファイルの説明で改行が正しく表示されない問題を修正 - (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/commit/bde6bb0bd2e8b0d027e724d2acdb8ae0585a8110) -- Fix: 一部画面のページネーションが動作しにくくなっていたのを修正 ( #12766 , #11449 ) - -### Server -- Feat: Misskey® Reactions Boost Technology™ (RBT)により、リアクションの作成負荷を低減することが可能に -- Fix: アンテナの書き込み時にキーワードが与えられなかった場合のエラーをApiErrorとして投げるように - - この変更により、公式フロントエンドでは入力の不備が内部エラーとして報告される代わりに一般的なエラーダイアログで報告されます -- Fix: ファイルがサイズの制限を超えてアップロードされた際にエラーを返さなかった問題を修正 -- Fix: 外部ページを解析する際に、ページに紐づけられた関連リソースも読み込まれてしまう問題を修正 - (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/commit/26e0412fbb91447c37e8fb06ffb0487346063bb8) -- Fix: Continue importing from file if single emoji import fails -- Fix: `Retry-After`ヘッダーが送信されなかった問題を修正 - (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/commit/8a982c61c01909e7540ff1be9f019df07c3f0624) -- Fix: サーバーサイドのDOM解析完了時にリソースを開放するように - (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/634) -- Fix: ``を追って照会するのはOKレスポンスが返却された場合のみに - (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/633) -- Fix: メールにスタイルが適用されていなかった問題を修正 - -## 2024.8.0 - -### General -- Enhance: モデレーターはすべてのユーザーのフォロー・フォロワーの一覧を見られるように -- Enhance: アカウントの削除のモデレーションログを残すように -- Enhance: 不適切なページ、ギャラリー、Playを管理者権限で削除できるように -- Fix: リモートユーザのフォロー・フォロワーの一覧が非公開設定の場合も表示できてしまう問題を修正 - -### Client -- Enhance: 「自分のPlay」ページにおいてPlayが非公開かどうかが一目でわかるように -- Enhance: 不適切なページ、ギャラリー、Playを通報できるように -- Fix: Play編集時に公開範囲が「パブリック」にリセットされる問題を修正 -- Fix: ページ遷移に失敗することがある問題を修正 -- Fix: iOSでユーザー名などがリンクとして誤検知される現象を抑制 -- Fix: mCaptchaを使用していてもbotプロテクションに関する警告が消えないのを修正 -- Fix: ユーザーのモデレーションページにおいてユーザー名にドットが入っているとシステムアカウントとして表示されてしまう問題を修正 -- Fix: 特定の条件下でノートの削除ボタンが出ないのを修正 - -### Server -- Enhance: 照会時にURLがhtmlかつheadタグ内に`rel="alternate"`, `type="application/activity+json"`の`link`タグがある場合に追ってリンク先を照会できるように -- Enhance: 凍結されたアカウントのフォローリクエストを表示しないように -- Fix: WSの`readAllNotifications` メッセージが `body` を持たない場合に動作しない問題 #14374 - - 通知ページや通知カラム(デッキ)を開いている状態において、新たに発生した通知が既読されない問題が修正されます。 - - これにより、プッシュ通知が有効な同条件下の環境において、プッシュ通知が常に発生してしまう問題も修正されます。 -- Fix: Play各種エンドポイントの返り値に`visibility`が含まれていない問題を修正 -- Fix: サーバー情報取得の際にモデレーター限定の情報が取得できないことがあるのを修正 - (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/582) -- Fix: 公開範囲がダイレクトのノートをユーザーアクティビティのチャート生成に使用しないように - (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/679) -- Fix: ActivityPubのエンティティタイプ判定で不明なタイプを受け取った場合でも処理を継続するように - - キュー処理のつまりが改善される可能性があります -- Fix: リバーシの対局設定の変更が反映されないのを修正 -- Fix: 無制限にストリーミングのチャンネルに接続できる問題を修正 -- Fix: ベースロールのポリシーを変更した際にモデログに記録されないのを修正 - (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/700) -- Fix: Prevent memory leak from memory caches (#14310) -- Fix: More reliable memory cache eviction (#14311) - -## 2024.7.0 - -### Note -- デッキUIの新着ノートをサウンドで通知する機能の追加(v2024.5.0)に伴い、以前から動作しなくなっていたクライアント設定内の「アンテナ受信」「チャンネル通知」サウンドを削除しました。 -- Streaming APIにて入力が不正な場合にはそのメッセージを無視するようになりました。 #14251 - -### General -- Feat: 通報を受けた際、または解決した際に、予め登録した宛先に通知を飛ばせるように(mail or webhook) #13705 -- Feat: ユーザーのアイコン/バナーの変更可否をロールで設定可能に - - 変更不可となっていても、設定済みのものを解除してデフォルト画像に戻すことは出来ます -- Feat: ユーザ作成時にSystemWebhookを送信可能に #14281 -- Feat: メディアサイレンスを実装 #13842 - - メディアサイレンスされたサーバーに所属するアカウントによるファイルはすべてセンシティブとして扱われ、カスタム絵文字が使用できないようになります。 -- Enhance: 管理画面でアーカイブにしたお知らせを表示・編集できるように -- Fix: 配信停止したインスタンス一覧が見れなくなる問題を修正 -- Fix: Dockerコンテナの立ち上げ時に`pnpm`のインストールで固まることがある問題 -- Fix: デフォルトテーマに無効なテーマコードを入力するとUIが使用できなくなる問題を修正 -- 翻訳の更新 -- 依存関係の更新 - -### Client -- Feat: ユーザーページから「このユーザーのノートを検索」できるように (#14128) -- Feat: 検索ページはクエリを受け付けるようになりました (#14128) -- Enhance: 検索ページのUI改善 (#14128) -- Enhance: 内蔵APIドキュメントのデザイン・パフォーマンスを改善 -- Enhance: 非ログイン時に他サーバーに遷移するアクションを追加 -- Enhance: 非ログイン時のハイライトTLのデザインを改善 -- Enhance: フロントエンドのアクセシビリティ改善 - (Based on https://github.com/taiyme/misskey/pull/226) -- Enhance: サーバー情報ページ・お問い合わせページを改善 - (Cherry-picked from https://github.com/taiyme/misskey/pull/238) -- Enhance: AiScriptを0.19.0にアップデート -- Enhance: Allow negative delay for MFM animation elements (`tada`, `jelly`, `twitch`, `shake`, `spin`, `jump`, `bounce`, `rainbow`) -- Enhance: センシティブなメディアを開く際に確認ダイアログを出せるように -- Enhance: 検索(ノート/ユーザー)で `#` から始まる文字列を入力すると、そのハッシュタグのノート/ユーザー一覧ページが表示できるように -- Enhance: 検索(ノート/ユーザー)において、入力に空白が含まれている場合は照会を行わないように -- Enhance: 検索(ノート/ユーザー)において、照会を行うかどうか、ハッシュタグのノート/ユーザー一覧ページを表示するかどうかの確認ダイアログを出すように -- Enhance: 検索(ノート/ユーザー)で `@` から始まる文字列(`@user@host`など)を入力すると、そのユーザーを照会できるように -- Enhance: ドライブのファイル・フォルダをドラッグしなくても移動できるように - (Cherry-picked from https://github.com/nafu-at/misskey/commit/b89c2af6945c6a9f9f10e83f54d2bcf0f240b0b4, https://github.com/nafu-at/misskey/commit/8a7d710c6acb83f50c83f050bd1423c764d60a99) -- Enhance: デッキのアンテナ・リスト選択画面からそれぞれを新規作成できるように -- Enhance: ブラウザのコンテキストメニューを使用できるように -- Enhance: 連合の「連合中」,「購読中」,「配信中」に対してブロックしているサーバー、配信停止しているサーバーを含めないように -- Fix: `/about#federation` ページなどで各インスタンスのチャートが表示されなくなっていた問題を修正 -- Fix: ユーザーページの追加情報のラベルを投稿者のサーバーの絵文字で表示する (#13968) -- Fix: リバーシの対局を正しく共有できないことがある問題を修正 -- Fix: コントロールパネルでベースロールのポリシーを編集してもUI上では変更が反映されない問題を修正 -- Fix: アンテナの編集画面のボタンに隙間を追加 -- Fix: テーマプレビューが見れない問題を修正 -- Fix: ショートカットキーが連打できる問題を修正 - (Cherry-picked from https://github.com/taiyme/misskey/pull/234) -- Fix: MkSignin.vueのcredentialRequestからReactivityを削除(ProxyがPasskey認証処理に渡ることを避けるため) -- Fix: 「アニメーション画像を再生しない」がオンのときでもサーバーのバナー画像・背景画像がアニメーションしてしまう問題を修正 - (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/574) -- Fix: Twitchの埋め込みが開けない問題を修正 -- Fix: 子メニューの高さがウィンドウからはみ出ることがある問題を修正 -- Fix: 個人宛てのダイアログ形式のお知らせが即時表示されない問題を修正 -- Fix: 一部の画像がセンシティブ指定されているときに画面に何も表示されないことがあるのを修正 -- Fix: リアクションしたユーザー一覧のユーザー名がはみ出る問題を修正 - (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/672) -- Fix: `/share`ページにおいて絵文字ピッカーを開くことができない問題を修正 -- Fix: deck uiの通知音が重なる問題 (#14029) -- Fix: ダイレクト投稿の"削除して編集"において、宛先が保持されていなかった問題を修正 -- Fix: 投稿フォームへのURL貼り付けによる引用が下書きに保存されていなかった問題を修正 -- Fix: "削除して編集"や下書きにおいて、リアクションの受け入れ設定が保持/保存されていなかった問題を修正 -- Fix: 照会に `#` から始まる文字列を入力してそのハッシュタグのページを表示する際、入力が `#` のみの場合に「指定されたURLに該当するページはありませんでした。」が表示されてしまう問題を修正 -- Fix: 照会に `@` から始まる文字列を入力してユーザーを照会する際、入力が `@` のみの場合に「問題が発生しました」が表示されてしまう問題を修正 -- Fix: 投稿フォームにノートのURLを貼り付けて"引用として添付"した場合、投稿文を空にすることによるRenote化が出来なかった問題を修正 -- Fix: フォロー中のユーザーに関する"TLに他の人への返信を含める"の設定が分かりづらい問題を修正 -- Fix: タイムラインページを開いた時、`TLに他の人への返信を含める`がオフのときに`ファイル付きのみ`をオンにできない問題を修正 -- Fix: deck uiでタイムラインを切り替えた際にTLの設定項目が更新されず、`TLに他の人への返信を含める`のトグルが表示されない問題を修正 -- Fix: ウィジェットのタイムライン選択欄に無効化されたタイムラインが表示される問題を修正 -- Fix: サウンドにドライブの音声を使用している際にドライブの音声が再生できなくなると設定が変更できなくなる問題を修正 - -### Server -- Feat: レートリミット制限に引っかかったときに`Retry-After`ヘッダーを返すように (#13949) -- Enhance: エンドポイント`clips/update`の必須項目を`clipId`のみに -- Enhance: エンドポイント`admin/roles/update`の必須項目を`roleId`のみに -- Enhance: エンドポイント`pages/update`の必須項目を`pageId`のみに -- Enhance: エンドポイント`gallery/posts/update`の必須項目を`postId`のみに -- Enhance: エンドポイント`i/webhook/update`の必須項目を`webhookId`のみに -- Enhance: エンドポイント`admin/ad/update`の必須項目を`id`のみに -- Enhance: `default.yml`内の`url`, `db.db`, `db.user`, `db.pass`を環境変数から読み込めるように -- Enhance: エンドポイント`api/meta`にプロパティ`noteSearchableScope`が増え、`string`値`local`または`global`を返却します -- Fix: チャート生成時にinstance.suspensionStateに置き換えられたinstance.isSuspendedが参照されてしまう問題を修正 -- Fix: ユーザーのフィードページのMFMをHTMLに展開するように (#14006) -- Fix: アンテナ・クリップ・リスト・ウェブフックがロールポリシーの上限より一つ多く作れてしまうのを修正 (#14036) -- Fix: notRespondingSinceが実装される前に不通になったインスタンスが自動的に配信停止にならない (#14059) -- Fix: FTT有効時、タイムライン用エンドポイントで`sinceId`にキャッシュ内最古のものより古いものを指定した場合に正しく結果が返ってこない問題を修正 -- Fix: 自分以外のクリップ内のノート個数が見えることがあるのを修正 -- Fix: 空文字列のリアクションはフォールバックされるように -- Fix: リノートにリアクションできないように -- Fix: ユーザー名の前後に空白文字列がある場合は省略するように -- Fix: プロフィール編集時に名前を空白文字列のみにできる問題を修正 -- Fix: ユーザ名のサジェスト時に表示される内容と順番を調整(以下の順番になります) #14149 - 1. フォロー中かつアクティブなユーザ - 2. フォロー中かつ非アクティブなユーザ - 3. フォローしていないアクティブなユーザ - 4. フォローしていない非アクティブなユーザ - - また、自分自身のアカウントもサジェストされるようになりました。 -- Fix: 一般ユーザーから見たユーザーのバッジの一覧に公開されていないものが含まれることがある問題を修正 - (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/652) -- Fix: ユーザーのリアクション一覧でミュート/ブロックが機能していなかった問題を修正 -- Fix: FTT有効時にリモートユーザーのノートがHTLにキャッシュされる問題を修正 -- Fix: 一部の通知がローカル上のリモートユーザーに対して行われていた問題を修正 -- Fix: エラーメッセージの誤字を修正 (#14213) -- Fix: ソーシャルタイムラインにローカルタイムラインに表示される自分へのリプライが表示されない問題を修正 -- Fix: リノートのミュートが適用されるまでに時間がかかることがある問題を修正 - (Cherry-picked from https://github.com/Type4ny-Project/Type4ny/commit/e9601029b52e0ad43d9131b555b614e56c84ebc1) -- Fix: Steaming APIが不正なデータを受けた場合の動作が不安定である問題 #14251 -- Fix: `users/search`において `@` から始まる文字列が与えられた際の処理が正しくなかった問題を修正 - - 名前や自己紹介に `@` から始まる文言が含まれるユーザーも検索できるようになります -- Fix: 一部のMisskey以外のソフトウェアからファイルを受け取れない問題 - (Cherry-picked from https://github.com/Secineralyr/misskey.dream/pull/73/commits/652eaff1e8aa00b890d71d2e1e52c263c1e67c76) - - NOTE: `drive_file`の`url`, `uri`, `src`の上限が512から1024に変更されます - Migrationではカラム定義の変更のみが行われます。 - サーバー管理者は各サーバーの必要に応じ`drive_file` `("uri")`に対するインデックスを張りなおすことでより安定しDBの探索が行われる可能性があります。詳細 は [GitHub](https://github.com/misskey-dev/misskey/pull/14323#issuecomment-2257562228)で確認可能です -- Fix: 自分のフォロワー限定投稿に対するリプライがホームタイムラインで見えないことが有る問題を修正 -- Fix: フォローしていないユーザによるフォロワー限定投稿に対するリプライがソーシャルタイムラインで表示されることがある問題を修正 -- Fix: ActivityPubのエンティティタイプ判定で不明なタイプを受け取った場合でも処理を継続するように - - キュー処理のつまりが改善される可能性があります - -### Misskey.js -- Feat: `/drive/files/create` のリクエストに対応(`multipart/form-data`に対応) -- Feat: `/admin/role/create` のロールポリシーの型を修正 - -## 2024.5.0 - -### Note -- コントロールパネル内にあるサマリープロキシの設定個所がセキュリティから全般へ変更となります。 -- 悪意のある第三者がリモートユーザーになりすましたアクティビティを受け取れてしまう問題を修正しました。詳しくは[GitHub security advisory](https://github.com/misskey-dev/misskey/security/advisories/GHSA-2vxv-pv3m-3wvj)をご覧ください。 -- 管理者向け権限 `read:admin:show-users` は `read:admin:show-user` に統合されました。必要に応じてAPIトークンを再発行してください。 - -### General -- Feat: エラートラッキングにSentryを使用できるようになりました -- Enhance: URLプレビューの有効化・無効化を設定できるように #13569 -- Enhance: アンテナでBotによるノートを除外できるように - (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/545) -- Enhance: クリップのノート数を表示するように -- Enhance: コンディショナルロールの条件として以下を新たに追加 (#13667) - - 猫ユーザーか - - botユーザーか - - サスペンド済みユーザーか - - 鍵アカウントユーザーか - - 「アカウントを見つけやすくする」が有効なユーザーか -- Enhance: Goneを出さずに終了したサーバーへの配信停止を自動的に行うように - - もしそのようなサーバーからから配信が届いた場合には自動的に配信を再開します -- Enhance: 配信停止の理由を表示するように -- Enhance: サーバーのお問い合わせ先URLを設定できるようになりました -- Fix: Play作成時に設定した公開範囲が機能していない問題を修正 -- Fix: 正規化されていない状態のhashtagが連合されてきたhtmlに含まれているとhashtagが正しくhashtagに復元されない問題を修正 -- Fix: みつけるのアンケート欄にてチャンネルのアンケートが含まれてしまう問題を修正 - -### Client -- Feat: アップロードするファイルの名前をランダム文字列にできるように -- Feat: 個別のお知らせにリンクで飛べるように - (Based on https://github.com/MisskeyIO/misskey/pull/639) -- Enhance: 自分のノートの添付ファイルから直接ファイルの詳細ページに飛べるように -- Enhance: 広告がMisskeyと同一ドメインの場合はRouterで遷移するように -- Enhance: リアクション・いいねの総数を表示するように -- Enhance: リアクション受け入れが「いいねのみ」の場合はリアクション絵文字一覧を表示しないように -- Enhance: 設定>プラグインのページからプラグインの簡易的なログやエラーを見られるように - - 実装の都合により、プラグインは1つエラーを起こした時に即時停止するようになりました -- Enhance: ページのデザインを変更 -- Enhance: 2要素認証(ワンタイムパスワード)の入力欄を改善 -- Enhance: 「今日誕生日のフォロー中ユーザー」ウィジェットを手動でリロードできるように -- Enhance: 映像・音声の再生にブラウザのネイティブプレイヤーを使用できるように -- Enhance: 映像・音声の再生メニューに「再生速度」「ループ再生」「ピクチャインピクチャ」を追加 -- Enhance: 映像・音声の再生にキーボードショートカットが使えるように -- Enhance: ノートについているリアクションの「もっと!」から、リアクションの一覧を表示できるように -- Enhance: リプライにて引用がある場合テキストが空でもノートできるように - - 引用したいノートのURLをコピーしリプライ投稿画面にペーストして添付することで達成できます -- Enhance: フォローするかどうかの確認ダイアログを出せるように -- Enhance: Playを手動でリロードできるように -- Enhance: 通報のコメント内のリンクをクリックした際、ウィンドウで開くように -- Enhance: `Ui:C:postForm` および `Ui:C:postFormButton` に `localOnly` と `visibility` を設定できるように -- Enhance: AiScriptを0.18.0にバージョンアップ -- Enhance: 通常のノートでも、お気に入りに登録したチャンネルにリノートできるように -- Enhance: 長いテキストをペーストした際にテキストファイルとして添付するかどうかを選択できるように -- Enhance: 新着ノートをサウンドで通知する機能をdeck UIに追加しました -- Enhance: コントロールパネルのクイックアクションからファイルを照会できるように -- Enhance: コントロールパネルのクイックアクションから通常の照会を行えるように -- Fix: 一部のページ内リンクが正しく動作しない問題を修正 -- Fix: 周年の実績が閏年を考慮しない問題を修正 -- Fix: ローカルURLのプレビューポップアップが左上に表示される -- Fix: WebGL2をサポートしないブラウザで「季節に応じた画面の演出」が有効になっているとき、Misskeyが起動できなくなる問題を修正 - (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/459) -- Fix: ページタイトルでローカルユーザーとリモートユーザーの区別がつかない問題を修正 - (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/528) -- Fix: コードブロックのシンタックスハイライトで使用される定義ファイルをCDNから取得するように #13177 - - CDNから取得せずMisskey本体にバンドルする場合は`pacakges/frontend/vite.config.ts`を修正してください。 -- Fix: タイムゾーンによっては、「今日誕生日のフォロー中ユーザー」ウィジェットが正しく動作しない問題を修正 -- Fix: CWのみの引用リノートが詳細ページで純粋なリノートとして誤って扱われてしまう問題を修正 -- Fix: ノート詳細ページにおいてCW付き引用リノートのCWボタンのラベルに「引用」が含まれていない問題を修正 -- Fix: ダイアログの入力で字数制限に違反していてもEnterキーが押せてしまう問題を修正 -- Fix: ダイレクト投稿の宛先が保存されない問題を修正 -- Fix: Playのページを離れたときに、Playが正常に初期化されない問題を修正 -- Fix: ページのOGP URLが間違っているのを修正 -- Fix: リバーシの対局を正しく共有できないことがある問題を修正 -- Fix: 通知をグループ化している際に、人数が正常に表示されないことがある問題を修正 -- Fix: 連合なしの状態の読み書きができない問題を修正 -- Fix: `/share` で日本語等を含むurlがurlエンコードされない問題を修正 -- Fix: ファイルを5つ以上添付してもテキストがないとノートが折りたたまれない問題を修正 - -### Server -- Enhance: エンドポイント`antennas/update`の必須項目を`antennaId`のみに -- Enhance: misskey-dev/summaly@5.1.0の取り込み(プレビュー生成処理の効率化) -- Enhance: ドライブのファイルがNSFWかどうか個別に連合されるように (#13756) - - 可能な場合、ノートの添付ファイルのセンシティブ判定がファイル単位になります -- Fix: リモートから配送されたアクティビティにJSON-LD compactionをかける -- Fix: フォローリクエストを作成する際に既存のものは削除するように - (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/440) -- Fix: エンドポイント`notes/translate`のエラーを改善 -- Fix: CleanRemoteFilesProcessorService report progress from 100% (#13632) -- Fix: 一部の音声ファイルが映像ファイルとして扱われる問題を修正 -- Fix: リプライのみの引用リノートと、CWのみの引用リノートが純粋なリノートとして誤って扱われてしまう問題を修正 -- Fix: 登録にメール認証が必須になっている場合、登録されているメールアドレスを削除できないように - (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/606) -- Fix: Add Cache-Control to Bull Board -- Fix: nginx経由で/files/にRangeリクエストされた場合に正しく応答できないのを修正 -- Fix: 一部のタイムラインのストリーミングでインスタンスミュートが効かない問題を修正 -- Fix: グローバルタイムラインで返信が表示されないことがある問題を修正 -- Fix: リノートをミュートしたユーザの投稿のリノートがミュートされる問題を修正 -- Fix: AP Link等は添付ファイル扱いしないようになど (#13754) -- Fix: FTTが有効かつsinceIdのみを指定した場合に帰って来るレスポンスが逆順である問題を修正 -- Fix: `/i/notifications`に `includeTypes`か`excludeTypes`を指定しているとき、通知が存在するのに空配列を返すことがある問題を修正 -- Fix: 複数idを指定する`users/show`が関係ないユーザを返すことがある問題を修正 -- Fix: `/tags` と `/user-tags` が検索エンジンにインデックスされないように -- Fix: もともとセンシティブではないと連合されていたファイルがセンシティブとして連合された場合にセンシティブとしてそのファイルを扱うように - - センシティブとして連合したファイルは非センシティブとして連合されてもセンシティブとして扱われます - -## 2024.3.1 + ## 2023.12.2 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f2e48ec61d..7f6c1f4f82 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,63 +1,50 @@ # Contribution guide -We're glad you're interested in contributing to Sharkey! In this document you will find the information you need to contribute to the project. +We're glad you're interested in contributing Misskey! In this document you will find the information you need to contribute to the project. + +> **Note** +> This project uses Japanese as its major language, **but you do not need to translate and write the Issues/PRs in Japanese.** +> Also, you might receive comments on your Issue/PR in Japanese, but you do not need to reply to them in Japanese as well.\ +> The accuracy of machine translation into Japanese is not high, so it will be easier for us to understand if you write it in the original language. +> It will also allow the reader to use the translation tool of their preference if necessary. ## Roadmap -See [ROADMAP.md](./ROADMAP.md) for the upstream Misskey roadmap. +See [ROADMAP.md](./ROADMAP.md) ## Issues Before creating an issue, please check the following: - To avoid duplication, please search for similar issues before creating a new issue. - Do not use Issues to ask questions or troubleshooting. - Issues should only be used to feature requests, suggestions, and bug tracking. - - Please ask questions or troubleshooting in [Discord](https://discord.gg/6VgKmEqHNk). + - Please ask questions or troubleshooting in [GitHub Discussions](https://github.com/misskey-dev/misskey/discussions) or [Discord](https://discord.gg/Wp8gVStHW3). -> [!WARNING] +> **Warning** > Do not close issues that are about to be resolved. It should remain open until a commit that actually resolves it is merged. -### Recommended discussing before implementation -We welcome your proposal. +## Before implementation +When you want to add a feature or fix a bug, **first have the design and policy reviewed in an Issue** (if it is not there, please make one). Without this step, there is a high possibility that the PR will not be merged even if it is implemented. -When you want to add a feature or fix a bug, *please open an issue*, -don't just start writing code. We may suggest different approaches, or -show that the "bug" is actually intended behaviour (and offer -work-arounds), or maybe we won't be able to merge your new feature -because it would make it too hard to incorporate future changes from -Misskey. Each of these examples have actually happened! +At this point, you also need to clarify the goals of the PR you will create, and make sure that the other members of the team are aware of them. +PRs that do not have a clear set of do's and don'ts tend to be bloated and difficult to review. -On the other hand, it's very likely that we'll tell you "go -ahead!". We try our best to incorporate improvements from our users! - -Also, when you start implementation, assign yourself to the Issue (if you cannot do it yourself, ask Committer to assign you). -By expressing your intention to work on the Issue, you can prevent conflicts in the work. - -To the Committers: you should not assign someone on it before the Final Decision. - -### How issues are triaged - -The Committers may: -* close an issue that is not reproducible on latest stable release, -* merge an issue into another issue, -* split an issue into multiple issues, -* or re-open that has been closed for some reason which is not applicable anymore. - -@syuilo reserves the Final Decision rights including whether the project will implement feature and how to implement, these rights are not always exercised. +Also, when you start implementation, assign yourself to the Issue (if you cannot do it yourself, ask another member to assign you). By expressing your intention to work the Issue, you can prevent conflicts in the work. ## Well-known branches -- **`stable`** branch is tracking the latest release and used for production purposes. +- **`master`** branch is tracking the latest release and used for production purposes. - **`develop`** branch is where we work for the next release. - When you create a PR, basically target it to this branch. +- **`l10n_develop`** branch is reserved for localization management. ## Creating a PR Thank you for your PR! Before creating a PR, please check the following: - If possible, prefix the title with a keyword that identifies the type of this PR, as shown below. - - `fix` / `refactor` / `feat` / `enhance` / `perf` / `chore` etc - - Also, make sure that the granularity of this PR is appropriate. Please do not include more than one type of change or interest in a single PR. + - `fix` / `refactor` / `feat` / `enhance` / `perf` / `chore` etc + - Also, make sure that the granularity of this PR is appropriate. Please do not include more than one type of change or interest in a single PR. - If there is an Issue which will be resolved by this PR, please include a reference to the Issue in the text. -- Please add the summary of the changes to [`CHANGELOG.md`](CHANGELOG.md). However, this is not necessary for changes that do not affect the users, such as refactoring. +- Please add the summary of the changes to [`CHANGELOG.md`](/CHANGELOG.md). However, this is not necessary for changes that do not affect the users, such as refactoring. - Check if there are any documents that need to be created or updated due to this change. - If you have added a feature or fixed a bug, please add a test case if possible. - Please make sure that tests and Lint are passed in advance. - - You can run it with `pnpm test` and `pnpm lint`. [See more info](#testing) + - You can run it with `pnpm test` and `pnpm lint`. [See more info](#testing) - If this PR includes UI changes, please attach a screenshot in the text. Thanks for your cooperation 🤗 @@ -67,8 +54,8 @@ Be willing to comment on the good points and not just the things you want fixed ### Review perspective - Scope - - Are the goals of the PR clear? - - Is the granularity of the PR appropriate? + - Are the goals of the PR clear? + - Is the granularity of the PR appropriate? - Security - Does merging this PR create a vulnerability? - Performance @@ -79,22 +66,29 @@ Be willing to comment on the good points and not just the things you want fixed - Are there any omissions or gaps? - Does it check for anomalies? +## Deploy +The `/deploy` command by issue comment can be used to deploy the contents of a PR to the preview environment. +``` +/deploy sha= +``` +An actual domain will be assigned so you can test the federation. + ## Merge ## Release ### Release Instructions -1. Commit version changes in the `develop` branch ([package.json](package.json)) +1. Commit version changes in the `develop` branch ([package.json](https://github.com/misskey-dev/misskey/blob/develop/package.json)) 2. Create a release PR. - - Into `stable` from `develop` branch. + - Into `master` from `develop` branch. - The title must be in the format `Release: x.y.z`. - `x.y.z` is the new version you are trying to release. 3. Deploy and perform a simple QA check. Also verify that the tests passed. 4. Merge it. (Do not squash commit) -5. Create a [release](https://activitypub.software/TransFem-org/Sharkey/-/releases) - - The target branch must be `stable` +5. Create a [release of GitHub](https://github.com/misskey-dev/misskey/releases) + - The target branch must be `master` - The tag name must be the version -> [!NOTE] +> **Note** > Why this instruction is necessary: > - To perform final QA checks > - To distribute responsibility @@ -111,34 +105,26 @@ If your language is not listed in Crowdin, please open an issue. ![Crowdin](https://d322cqt584bo4o.cloudfront.net/misskey/localized.svg) -## Icon Font (Shark Font) -Sharkey has its own Icon Font called Shark Font which can be found at https://activitypub.software/TransFem-org/shark-font -Build Instructions can all be found over there in the `README`. - -If you have an Icon Suggestion or want to add an Icon please open an issue/merge request over at that repo. - -When Updating the Font make sure to copy **all generated files** from the `dest` folder into `packages/backend/assets/fonts/sharkey-icons` -For the CSS simply copy the file content and replace the old content in `style.css` and for the WOFF, TTF and SVG simply replace them. - ## Development -### Setup -Before developing, you have to set up environment. Misskey requires Redis, PostgreSQL, and FFmpeg. +During development, it is useful to use the -You would want to install Meilisearch to experiment related features. Technically, meilisearch is not strict requirement, but some features and tests require it. +``` +pnpm dev +``` -There are a few ways to proceed. +command. -#### Use system-wide software -You could install them in system-wide (such as from package manager). - -#### Use `docker compose` -You could obtain middleware container by typing `docker compose -f $PROJECT_ROOT/compose.local-db.yml up -d`. - -#### Use Devcontainer -Devcontainer also has necessary setting. This method can be done by connecting from VSCode. +- Server-side source files and automatically builds them if they are modified. Automatically start the server process(es). +- Vite HMR (just the `vite` command) is available. The behavior may be different from production. +- Service Worker is watched by esbuild. +- The front end can be viewed by accessing `http://localhost:5173`. +- The backend listens on the port configured with `port` in .config/default.yml. +If you have not changed it from the default, it will be "http://localhost:3000". +If "port" in .config/default.yml is set to something other than 3000, you need to change the proxy settings in packages/frontend/vite.config.local-dev.ts. +### Dev Container Instead of running `pnpm` locally, you can use Dev Container to set up your development environment. -To use Dev Container, open the project directory on VSCode with Dev Containers installed. +To use Dev Container, open the project directory on VSCode with Dev Containers installed. **Note:** If you are using Windows, please clone the repository with WSL. Using Git for Windows will result in broken files due to the difference in how newlines are handled. It will run the following command automatically inside the container. @@ -150,38 +136,14 @@ pnpm build pnpm migrate ``` -After finishing the migration, you can proceed. +After finishing the migration, run the `pnpm dev` command to start the development server. -### Start developing -During development, it is useful to use the -``` +``` bash pnpm dev ``` -command. - -- Server-side source files and automatically builds them if they are modified. Automatically start the server process(es). -- Vite HMR (just the `vite` command) is available. The behavior may be different from production. -- Service Worker is watched by esbuild. -- The front end can be viewed by accessing `http://localhost:5173`. -- The backend listens on the port configured with `port` in .config/default.yml. -If you have not changed it from the default, it will be "http://localhost:3000". -If "port" in .config/default.yml is set to something other than 3000, you need to change the proxy settings in packages/frontend/vite.config.local-dev.ts. - -### `MK_DEV_PREFER=backend pnpm dev` -pnpm dev has another mode with `MK_DEV_PREFER=backend`. - -``` -MK_DEV_PREFER=backend pnpm dev -``` - -- This mode is closer to the production environment than the default mode. -- Vite runs behind the backend (the backend will proxy Vite at /vite). -- You can see Misskey by accessing `http://localhost:3000` (Replace `3000` with the port configured with `port` in .config/default.yml). -- To change the port of Vite, specify with `VITE_PORT` environment variable. -- HMR may not work in some environments such as Windows. ## Testing -- Test codes are located in [`/packages/backend/test`](packages/backend/test). +- Test codes are located in [`/packages/backend/test`](/packages/backend/test). ### Run test Create a config file. @@ -190,7 +152,7 @@ cp .github/misskey/test.yml .config/ ``` Prepare DB/Redis for testing. ``` -docker compose -f packages/backend/test/compose.yml up +docker compose -f packages/backend/test/docker-compose.yml up ``` Alternatively, prepare an empty (data can be erased) DB and edit `.config/test.yml`. @@ -213,8 +175,8 @@ TODO - `MISSKEY_WEBFINGER_USE_HTTP`: If it's set true, WebFinger requests will be http instead of https, useful for testing federation between servers in localhost. NEVER USE IN PRODUCTION. ## Continuous integration -Sharkey uses GitLab CI for executing automated tests. -Configuration files are located in [`/.gitlab-ci.yml`](.gitlab-ci.yml). +Misskey uses GitHub Actions for executing automated tests. +Configuration files are located in [`/.github/workflows`](/.github/workflows). ## Vue Misskey uses Vue(v3) as its front-end framework. @@ -229,7 +191,7 @@ niraxは、Misskeyで使用しているオリジナルのフロントエンド ### ルート定義 ルート定義は、以下の形式のオブジェクトの配列です。 -```ts +``` ts { name?: string; path: string; @@ -242,7 +204,7 @@ niraxは、Misskeyで使用しているオリジナルのフロントエンド } ``` -> [!WARNING] +> **Warning** > 現状、ルートは定義された順に評価されます。 > たとえば、`/foo/:id`ルート定義の次に`/foo/bar`ルート定義がされていた場合、後者がマッチすることはありません。 @@ -304,7 +266,7 @@ export const Default = { parameters: { layout: 'centered', }, -} satisfies StoryObj; +} satisfies StoryObj; ``` If you want to opt-out from the automatic generation, create a `MyComponent.stories.impl.ts` file and add the following line to the file. @@ -324,115 +286,24 @@ export const argTypes = { min: 1, max: 4, }, - }, }; ``` Also, you can use msw to mock API requests in the storybook. Creating a `MyComponent.stories.msw.ts` file to define the mock handlers. ```ts -import { HttpResponse, http } from 'msw'; +import { rest } from 'msw'; export const handlers = [ - http.post('/api/notes/timeline', ({ request }) => { - return HttpResponse.json([]); + rest.post('/api/notes/timeline', (req, res, ctx) => { + return res( + ctx.json([]), + ); }), ]; ``` Don't forget to re-run the `.storybook/generate.js` script after adding, editing, or removing the above files. -## Nest - -### Nest Service Circular dependency / Nestでサービスの循環参照でエラーが起きた場合 - -#### forwardRef -まずは簡単に`forwardRef`を試してみる - -```typescript -export class FooService { - constructor( - @Inject(forwardRef(() => BarService)) - private barService: BarService - ) { - } -} -``` - -#### OnModuleInit -できなければ`OnModuleInit`を使う - -```typescript -import { Injectable, OnModuleInit } from '@nestjs/common'; -import { ModuleRef } from '@nestjs/core'; -import { BarService } from '@/core/BarService'; - -@Injectable() -export class FooService implements OnModuleInit { - private barService: BarService // constructorから移動してくる - - constructor( - private moduleRef: ModuleRef, - ) { - } - - async onModuleInit() { - this.barService = this.moduleRef.get(BarService.name); - } - - public async niceMethod() { - return await this.barService.incredibleMethod({ hoge: 'fuga' }); - } -} -``` - -##### Service Unit Test -テストで`onModuleInit`を呼び出す必要がある - -```typescript -// import ... - -describe('test', () => { - let app: TestingModule; - let fooService: FooService; // for test case - let barService: BarService; // for test case - - beforeEach(async () => { - app = await Test.createTestingModule({ - imports: ..., - providers: [ - FooService, - { // mockする (mockは必須ではないかもしれない) - provide: BarService, - useFactory: () => ({ - incredibleMethod: jest.fn(), - }), - }, - { // Provideにする - provide: BarService.name, - useExisting: BarService, - }, - ], - }) - .useMocker(... - .compile(); - - fooService = app.get(FooService); - barService = app.get(BarService) as jest.Mocked; - - // onModuleInitを実行する - await fooService.onModuleInit(); - }); - - test('nice', () => { - await fooService.niceMethod(); - - expect(barService.incredibleMethod).toHaveBeenCalled(); - expect(barService.incredibleMethod.mock.lastCall![0]) - .toEqual({ hoge: 'fuga' }); - }); -}) -``` - ## Notes ### Misskeyのドメイン固有の概念は`Mi`をprefixする @@ -529,21 +400,20 @@ enumの列挙の内容の削除は、その値をもつレコードを全て削 ### Migration作成方法 packages/backendで: ```sh -pnpm run build -pnpm dlx typeorm migration:generate -d ormconfig.js -o migration/ +pnpm dlx typeorm migration:generate -d ormconfig.js -o ``` - 生成後、ファイルをmigration下に移してください - 作成されたスクリプトは不必要な変更を含むため除去してください ### JSON SchemaのobjectでanyOfを使うとき -JSON Schemaで、objectに対してanyOfを使う場合、anyOfの中でpropertiesを定義しないこと。 -バリデーションが効かないため。(SchemaTypeもそのように作られており、objectのanyOf内のpropertiesは捨てられます) +JSON Schemaで、objectに対してanyOfを使う場合、anyOfの中でpropertiesを定義しないこと。 +バリデーションが効かないため。(SchemaTypeもそのように作られており、objectのanyOf内のpropertiesは捨てられます) https://github.com/misskey-dev/misskey/pull/10082 テキストhogeおよびfugaについて、片方を必須としつつ両方の指定もありうる場合: -```ts +``` export const paramDef = { type: 'object', properties: { @@ -573,84 +443,3 @@ marginはそのコンポーネントを使う側が設定する ### indexというファイル名を使うな ESMではディレクトリインポートは廃止されているのと、ディレクトリインポートせずともファイル名が index だと何故か一部のライブラリ?でディレクトリインポートだと見做されてエラーになる - -## CSS Recipe - -### Lighten CSS vars - -``` css -color: hsl(from var(--accent) h s calc(l + 10)); -``` - -### Darken CSS vars - -``` css -color: hsl(from var(--accent) h s calc(l - 10)); -``` - -### Add alpha to CSS vars - -``` css -color: color(from var(--accent) srgb r g b / 0.5); -``` - -## Merging from Misskey into Sharkey - -Make sure you have both remotes in the same clone (`git remote add misskey -https://github.com/misskey-dev/misskey.git`), then: - - git remote update - git checkout develop # this is Sharkey's develop - git checkout -m merge/$(date +%Y-%m-%d) # or whatever - git merge --no-ff misskey/develop - -fix conflicts and *commit*! (conflicts in `pnpm-lock.yaml` can usually -be fixed by running `pnpm install`, it detects conflict markers and -seems to do a decent job) - -*after that commit*, do all the extra work, on the same branch: - -* copy all changes (commit after each step): - * in - `packages/backend/src/core/activitypub/models/ApNoteService.ts`, - from `createNote` to `updateNote` - * from `packages/backend/src/core/NoteCreateService.ts` to - `packages/backend/src/core/NoteEditService.vue` - * from `packages/backend/src/server/api/endpoints/notes/create.ts` - to `packages/backend/src/server/api/endpoints/notes/edit.ts` - * from `packages/frontend/src/components/MkNote*.vue` to - `packages/frontend/src/components/SkNote*.vue` (if sensible) - * from the global timeline to the bubble timeline - (`packages/backend/src/server/api/stream/channels/global-timeline.ts`, - `packages/backend/src/server/api/stream/channels/bubble-timeline.ts`, - `packages/frontend/src/timelines.ts`, - `packages/frontend/src/components/MkTimeline.vue`, - `packages/frontend/src/pages/timeline.vue`, - `packages/frontend/src/ui/deck/tl-column.vue`, - `packages/frontend/src/widgets/WidgetTimeline.vue`) -* check the changes against our `develop` (`git diff develop`) and - against Misskey (`git diff misskey/develop`) -* re-generate `misskey-js` (`pnpm build-misskey-js-with-types`) and commit -* build the frontend: `rm -rf built/; NODE_ENV=development pnpm - --filter=frontend --filter=frontend-embed build` (the `development` - tells it to keep some of the original filenames in the built files) -* make sure there aren't any new `ti-*` classes (Tabler Icons), and - replace them with appropriate `ph-*` ones (Phosphor Icons): - `grep -rP '["'\'']ti[ -](?!fw)' -- built/` should show you what to change. - NOTE: `ti-fw` is a special class that's defined by Misskey, leave it - alone - - after every change, re-build the frontend and check again, until - there are no more `ti-*` classes in the built files - - commit! -* double-check the new migration, that they won't conflict with our db - changes: `git diff develop -- packages/backend/migration/` -* `pnpm clean; pnpm build` -* run tests `pnpm --filter='!megalodon' test` (requires a test - database, [see above](#testing)) and fix as much as you can - * right now `megalodon` doesn't pass its tests, so we skip them -* run lint `pnpm --filter=backend lint` + `pnpm --filter=frontend - eslint` and fix as much as you can - -Then push and open a Merge Request. diff --git a/COPYING b/COPYING index 6a5f3ca1d5..c218443d42 100644 --- a/COPYING +++ b/COPYING @@ -1,5 +1,5 @@ Unless otherwise stated this repository is -Copyright © 2014-2024 syuilo and contributors +Copyright © 2014-2023 syuilo and contributers And is distributed under The GNU Affero General Public License Version 3, you should have received a copy of the license file as LICENSE. diff --git a/Dockerfile b/Dockerfile index abee7fb098..99286b39b0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,86 +1,62 @@ # syntax = docker/dockerfile:1.4 -ARG NODE_VERSION=20.16.0-alpine3.20 +ARG NODE_VERSION=20.10.0-alpine3.18 FROM node:${NODE_VERSION} as build -RUN apk add git linux-headers build-base - -ENV PYTHONUNBUFFERED=1 -RUN apk add --update python3 && ln -sf python3 /usr/bin/python -RUN apk add py3-pip py3-setuptools - RUN corepack enable WORKDIR /sharkey -COPY --link . ./ +RUN apk add git linux-headers build-base + +ENV PYTHONUNBUFFERED=1 +RUN apk add --update python3 && ln -sf python3 /usr/bin/python +RUN python3 -m ensurepip +RUN pip3 install --no-cache --upgrade pip setuptools + +COPY . ./ RUN git submodule update --init --recursive RUN pnpm config set fetch-retries 5 RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \ - pnpm i --frozen-lockfile --aggregate-output + pnpm i RUN pnpm build RUN node scripts/trim-deps.mjs RUN mv packages/frontend/assets sharkey-assets -RUN mv packages/frontend-embed/assets sharkey-embed-assets +RUN rm -r node_modules packages/frontend packages/sw RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \ - pnpm prune -RUN rm -r node_modules packages/frontend packages/frontend-shared packages/frontend-embed packages/sw -RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \ - pnpm i --prod --frozen-lockfile --aggregate-output + pnpm i --prod RUN rm -rf .git FROM node:${NODE_VERSION} -ARG UID="991" -ARG GID="991" - -RUN apk add ffmpeg tini jemalloc \ - && corepack enable \ - && addgroup -g "${GID}" sharkey \ - && adduser -D -u "${UID}" -G sharkey -h /sharkey sharkey \ - && mkdir /sharkey/files \ - && chown sharkey:sharkey /sharkey/files \ - && find / -type d -path /sys -prune -o -type d -path /proc -prune -o -type f -perm /u+s -exec chmod u-s {} \; \ - && find / -type d -path /sys -prune -o -type d -path /proc -prune -o -type f -perm /g+s -exec chmod g-s {} \; - -USER sharkey WORKDIR /sharkey -# add package.json to add pnpm -COPY --chown=sharkey:sharkey ./package.json ./package.json -RUN corepack install +RUN apk add ffmpeg tini -COPY --chown=sharkey:sharkey --from=build /sharkey/node_modules ./node_modules -COPY --chown=sharkey:sharkey --from=build /sharkey/packages/backend/node_modules ./packages/backend/node_modules -COPY --chown=sharkey:sharkey --from=build /sharkey/packages/misskey-js/node_modules ./packages/misskey-js/node_modules -COPY --chown=sharkey:sharkey --from=build /sharkey/packages/misskey-reversi/node_modules ./packages/misskey-reversi/node_modules -COPY --chown=sharkey:sharkey --from=build /sharkey/packages/misskey-bubble-game/node_modules ./packages/misskey-bubble-game/node_modules -COPY --chown=sharkey:sharkey --from=build /sharkey/packages/megalodon/node_modules ./packages/megalodon/node_modules -COPY --chown=sharkey:sharkey --from=build /sharkey/built ./built -COPY --chown=sharkey:sharkey --from=build /sharkey/packages/misskey-js/built ./packages/misskey-js/built -COPY --chown=sharkey:sharkey --from=build /sharkey/packages/misskey-reversi/built ./packages/misskey-reversi/built -COPY --chown=sharkey:sharkey --from=build /sharkey/packages/misskey-bubble-game/built ./packages/misskey-bubble-game/built -COPY --chown=sharkey:sharkey --from=build /sharkey/packages/backend/built ./packages/backend/built -COPY --chown=sharkey:sharkey --from=build /sharkey/packages/megalodon/lib ./packages/megalodon/lib -COPY --chown=sharkey:sharkey --from=build /sharkey/fluent-emojis ./fluent-emojis -COPY --chown=sharkey:sharkey --from=build /sharkey/tossface-emojis/dist ./tossface-emojis/dist -COPY --chown=sharkey:sharkey --from=build /sharkey/sharkey-assets ./packages/frontend/assets -COPY --chown=sharkey:sharkey --from=build /sharkey/sharkey-embed-assets ./packages/frontend-embed/assets +COPY --from=build /sharkey/built ./built +COPY --from=build /sharkey/node_modules ./node_modules +COPY --from=build /sharkey/packages/backend/built ./packages/backend/built +COPY --from=build /sharkey/packages/backend/node_modules ./packages/backend/node_modules +COPY --from=build /sharkey/packages/megalodon/lib ./packages/megalodon/lib +COPY --from=build /sharkey/packages/megalodon/node_modules ./packages/megalodon/node_modules +COPY --from=build /sharkey/packages/misskey-js/built ./packages/misskey-js/built +COPY --from=build /sharkey/packages/misskey-js/node_modules ./packages/misskey-js/node_modules +COPY --from=build /sharkey/fluent-emojis ./fluent-emojis +COPY --from=build /sharkey/sharkey-assets ./packages/frontend/assets -COPY --chown=sharkey:sharkey pnpm-workspace.yaml ./pnpm-workspace.yaml -COPY --chown=sharkey:sharkey packages/backend/package.json ./packages/backend/package.json -COPY --chown=sharkey:sharkey packages/backend/scripts/check_connect.js ./packages/backend/scripts/check_connect.js -COPY --chown=sharkey:sharkey packages/backend/ormconfig.js ./packages/backend/ormconfig.js -COPY --chown=sharkey:sharkey packages/backend/migration ./packages/backend/migration -COPY --chown=sharkey:sharkey packages/backend/assets ./packages/backend/assets -COPY --chown=sharkey:sharkey packages/megalodon/package.json ./packages/megalodon/package.json -COPY --chown=sharkey:sharkey packages/misskey-js/package.json ./packages/misskey-js/package.json -COPY --chown=sharkey:sharkey packages/misskey-reversi/package.json ./packages/misskey-reversi/package.json -COPY --chown=sharkey:sharkey packages/misskey-bubble-game/package.json ./packages/misskey-bubble-game/package.json +COPY package.json ./package.json +COPY pnpm-workspace.yaml ./pnpm-workspace.yaml +COPY packages/backend/package.json ./packages/backend/package.json +COPY packages/backend/check_connect.js ./packages/backend/check_connect.js +COPY packages/backend/ormconfig.js ./packages/backend/ormconfig.js +COPY packages/backend/migration ./packages/backend/migration +COPY packages/backend/assets ./packages/backend/assets +COPY packages/megalodon/package.json ./packages/megalodon/package.json +COPY packages/misskey-js/package.json ./packages/misskey-js/package.json -ENV LD_PRELOAD=/usr/lib/libjemalloc.so.2 ENV NODE_ENV=production +RUN corepack enable ENTRYPOINT ["/sbin/tini", "--"] CMD ["pnpm", "run", "migrateandstart"] diff --git a/IMPORTANT_NOTES.md b/IMPORTANT_NOTES.md deleted file mode 100644 index 54d0440bea..0000000000 --- a/IMPORTANT_NOTES.md +++ /dev/null @@ -1,16 +0,0 @@ -# Basic Precautions - -When using a service with Sharkey, there are several important points to keep in mind. - -1. Because it is decentralized, there is no guarantee that data you upload will be deleted from all other servers even if you delete it once. (However, this applies to the internet in general.) - -2. Even for posts made in private, there is no guarantee that the recipient's server will treat them as private in the same way. Please exercise caution when posting personal or confidential information. (Again, this applies to the internet in general.) - -3. The "Drive" feature is NOT secure cloud storage. This feature exists for easier managing of your uploaded files. -Any data uploaded, whether shared via post or not, will be publicly accessible. Please use 3rd party cloud storage providers if you need to upload data with sensitive information of any kind. - -4. Account deletion can be a resource-intensive process and may take a long time. In cases with a lot of uploaded data, it may even be impossible to delete an account. - -5. Please disable ad blockers. Some servers may rely on advertising revenue to cover operating costs. Additionally, ad blockers can mistakenly block content and features unrelated to ads, potentially causing issues with the client's functionality and preventing normal use of Sharkey. Therefore, we recommend turning off ad blockers and similar features when using Sharkey. - -Please understand these points and enjoy using the service. diff --git a/README.md b/README.md index f9198c06c0..d3ba23c4e1 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,15 @@
- Sharkey logo + Sharkey logo **🌎 **[Sharkey](https://joinsharkey.org/)** is an open source, decentralized social media platform that's free forever! 🚀** --- + + find an instance + create an instance @@ -16,8 +19,10 @@ join the community - - donate + + donate + + Translate Sharkey --- @@ -25,13 +30,13 @@
- + ## ✨ Features - **ActivityPub support**\ Not on Sharkey? No problem! Not only can Sharkey instances talk to each other, but you can make friends with people on other networks like Mastodon and Pixelfed! - **Federated Backgrounds and Music status**\ -You can add a background to your profile as well as a music status via ListenBrainz, show everyone what music you are currently listening to +You can add a background to your profile as well as a music status via ListenBrainz, show everyone what music you are currently listening too - **Mastodon API**\ Sharkey implements the Mastodon API unlike normal Misskey - **UI/UX Improvements**\ @@ -39,9 +44,9 @@ Sharkey makes some UI/UX improvements to make it easier to navigate - **Sign-Up Approval**\ With Sharkey, you can enable sign-ups, subject to manual moderator approval and mandatory user-provided reasons for joining. - **Rich Web UI**\ - Sharkey has a rich and easy to use Web UI! - It is highly customizable, from changing the layout and adding widgets to making custom themes. - Furthermore, plugins can be created using AiScript, an original programming language. + Sharkey has a rich and easy to use Web UI! + It is highly customizable, from changing the layout and adding widgets to making custom themes. + Furthermore, plugins can be created using AiScript, an original programming language. - And much more...
diff --git a/ROADMAP.md b/ROADMAP.md index 509ecb9fe7..3077c41e73 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -6,7 +6,6 @@ Also, the later tasks are more indefinite and are subject to change as developme This is the phase we are at now. We need to make a high-maintenance environment that can withstand future development. - ~~Make the number of type errors zero (backend)~~ → Done ✔️ -- Make the number of type errors zero (frontend) - Improve CI - ~~Fix tests~~ → Done ✔️ - Fix random test failures - https://github.com/misskey-dev/misskey/issues/7985 and https://github.com/misskey-dev/misskey/issues/7986 diff --git a/SECURITY.md b/SECURITY.md index cfc0614dd6..fa00b700e9 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,6 +4,6 @@ If you discover a security issue in Sharkey, please report it by sending an email to [admin@transfem.org](mailto:admin@transfem.org). This will allow us to assess the risk, and make a fix available before we add a -bug report to the GitLab repository. +bug report to the GitHub repository. Thanks for helping make Sharkey safe for everyone. diff --git a/UPGRADE_NOTES.md b/UPGRADE_NOTES.md deleted file mode 100644 index c941de6643..0000000000 --- a/UPGRADE_NOTES.md +++ /dev/null @@ -1,74 +0,0 @@ -# Upgrade Notes - -## 2024.10.0 - -### Hellspawns - -Sharkey versions before 2024.10 suffered from a bug in the "Mark instance as NSFW" feature. -When a user from such an instance boosted a note, the boost would be converted to a hellspawn (pure renote with Content Warning). -Hellspawns are buggy and do not properly federate, so it may be desirable to correct any that already exist in the database. -The following script will correct any local or remote hellspawns in the database. - -```postgresql -/* Remove "instance is marked as NSFW" hellspawns */ -UPDATE "note" -SET "cw" = null -WHERE - "renoteId" IS NOT NULL - AND "text" IS NULL - AND "cw" = 'Instance is marked as NSFW' - AND "replyId" IS NULL - AND "hasPoll" = false - AND "fileIds" = '{}'; - -/* Fix legacy / user-created hellspawns */ -UPDATE "note" -SET "text" = '.' -WHERE - "renoteId" IS NOT NULL - AND "text" IS NULL - AND "cw" IS NOT NULL - AND "replyId" IS NULL - AND "hasPoll" = false - AND "fileIds" = '{}'; -``` - -## 2024.9.0 - -### Following Feed - -When upgrading an existing instance to version 2024.9.0, the Following Feed will initially be empty. -The feed will gradually fill as new posts federate, but it may be desirable to back-fill the feed with existing data. -This database script will populate the feed with the latest post of each type for all users, ensuring that data is fully populated after the update. -Run this after migrations but before starting the instance. -Warning: the script may take a long time to execute! - -```postgresql -INSERT INTO latest_note (user_id, note_id, is_public, is_reply, is_quote) -SELECT - "userId" as user_id, - id as note_id, - visibility = 'public' AS is_public, - "replyId" IS NOT NULL AS is_reply, - ( - "renoteId" IS NOT NULL - AND ( - text IS NOT NULL - OR cw IS NOT NULL - OR "replyId" IS NOT NULL - OR "hasPoll" - OR "fileIds" != '{}' - ) - ) AS is_quote -FROM note -WHERE ( -- Exclude pure renotes (boosts) - "renoteId" IS NULL - OR text IS NOT NULL - OR cw IS NOT NULL - OR "replyId" IS NOT NULL - OR "hasPoll" - OR "fileIds" != '{}' - ) -ORDER BY id DESC -- This part is very important: it ensures that we only load the *latest* notes of each type. Do not remove it! -ON CONFLICT DO NOTHING; -- Any conflicts are guaranteed to be older notes that we can ignore. -``` diff --git a/chart/files/default.yml b/chart/files/default.yml index 97201aad66..9c81964736 100644 --- a/chart/files/default.yml +++ b/chart/files/default.yml @@ -124,14 +124,6 @@ redis: # #prefix: example-prefix # #db: 1 -#redisForReactions: -# host: redis -# port: 6379 -# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 -# #pass: example-pass -# #prefix: example-prefix -# #db: 1 - # ┌───────────────────────────┐ #───┘ MeiliSearch configuration └───────────────────────────── @@ -160,22 +152,6 @@ redis: # ID SETTINGS AFTER THAT! id: "aidx" - -# ┌────────────────┐ -#───┘ Error tracking └────────────────────────────────────────── - -# Sentry is available for error tracking. -# See the Sentry documentation for more details on options. - -#sentryForBackend: -# enableNodeProfiling: true -# options: -# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' - -#sentryForFrontend: -# options: -# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0' - # ┌─────────────────────┐ #───┘ Other configuration └───────────────────────────────────── @@ -216,13 +192,8 @@ id: "aidx" # Media Proxy #mediaProxy: https://example.com/proxy -# Sign outgoing ActivityPub GET request (default: true) +# Sign to ActivityPub GET request (default: true) signToActivityPubGet: true -# Sign outgoing ActivityPub Activities (default: true) -# Linked Data signatures are cryptographic signatures attached to each activity to provide proof of authenticity. -# When using authorized fetch, this is often undesired as any signed activity can be forwarded to a blocked instance by relays and other instances. -# This setting allows admins to disable LD signatures for increased privacy, at the expense of fewer relayed activities and additional inbound fetch (GET) requests. -attachLdSignatureForRelays: true # check that inbound ActivityPub GET requests are signed ("authorized fetch") checkActivityPubGetSignature: false diff --git a/crowdin.yml b/crowdin.yml index 0525ac7b0b..774ddc7a63 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,4 +1,4 @@ files: - - source: /sharkey-locales/en-US.yml - translation: /sharkey-locales/%locale%.yml + - source: /locales/ja-JP.yml + translation: /locales/%locale%.yml update_option: update_as_unapproved diff --git a/cypress/e2e/basic.cy.ts b/cypress/e2e/basic.cy.js similarity index 93% rename from cypress/e2e/basic.cy.ts rename to cypress/e2e/basic.cy.js index d2525e0a7d..5ab07c7480 100644 --- a/cypress/e2e/basic.cy.ts +++ b/cypress/e2e/basic.cy.js @@ -1,8 +1,3 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - describe('Before setup instance', () => { beforeEach(() => { cy.resetState(); @@ -166,13 +161,11 @@ describe('After user signed in', () => { }); it('successfully loads', () => { - // 表示に時間がかかるのでデフォルト秒数だとタイムアウトする - cy.get('[data-cy-user-setup-continue]', { timeout: 30000 }).should('be.visible'); + cy.get('[data-cy-user-setup-continue]').should('be.visible'); }); it('account setup wizard', () => { - // 表示に時間がかかるのでデフォルト秒数だとタイムアウトする - cy.get('[data-cy-user-setup-continue]', { timeout: 30000 }).click(); + cy.get('[data-cy-user-setup-continue]').click(); cy.get('[data-cy-user-setup-user-name] input').type('ありす'); cy.get('[data-cy-user-setup-user-description] textarea').type('ほげ'); @@ -209,8 +202,7 @@ describe('After user setup', () => { cy.login('alice', 'alice1234'); // アカウント初期設定ウィザード - // 表示に時間がかかるのでデフォルト秒数だとタイムアウトする - cy.get('[data-cy-user-setup] [data-cy-modal-window-close]', { timeout: 30000 }).click(); + cy.get('[data-cy-user-setup] [data-cy-modal-window-close]').click(); cy.get('[data-cy-modal-dialog-ok]').click(); }); diff --git a/cypress/e2e/router.cy.ts b/cypress/e2e/router.cy.ts deleted file mode 100644 index 8d8fb3af31..0000000000 --- a/cypress/e2e/router.cy.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -describe('Router transition', () => { - describe('Redirect', () => { - // サーバの初期化。ルートのテストに関しては各describeごとに1度だけ実行で十分だと思う(使いまわした方が早い) - before(() => { - cy.resetState(); - - // インスタンス初期セットアップ - cy.registerUser('admin', 'pass', true); - - // ユーザー作成 - cy.registerUser('alice', 'alice1234'); - - cy.login('alice', 'alice1234'); - - // アカウント初期設定ウィザード - // 表示に時間がかかるのでデフォルト秒数だとタイムアウトする - cy.get('[data-cy-user-setup] [data-cy-modal-window-close]', { timeout: 30000 }).click(); - cy.wait(500); - cy.get('[data-cy-modal-dialog-ok]').click(); - }); - - it('redirect to user profile', () => { - // テストのためだけに用意されたリダイレクト用ルートに飛ぶ - cy.visit('/redirect-test'); - - // プロフィールページのURLであることを確認する - cy.url().should('include', '/@alice') - }); - }); -}); diff --git a/cypress/e2e/widgets.cy.ts b/cypress/e2e/widgets.cy.js similarity index 95% rename from cypress/e2e/widgets.cy.ts rename to cypress/e2e/widgets.cy.js index 847801a69f..df6ec8357d 100644 --- a/cypress/e2e/widgets.cy.ts +++ b/cypress/e2e/widgets.cy.js @@ -1,8 +1,3 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - /* flaky describe('After user signed in', () => { beforeEach(() => { diff --git a/cypress/support/commands.ts b/cypress/support/commands.js similarity index 87% rename from cypress/support/commands.ts rename to cypress/support/commands.js index 281f2e6ccd..91a4d7abe6 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.js @@ -30,13 +30,9 @@ Cypress.Commands.add('visitHome', () => { }) Cypress.Commands.add('resetState', () => { - // iframe.contentWindow.indexedDB.deleteDatabase() がchromeのバグで使用できないため、indexedDBを無効化している。 - // see https://github.com/misskey-dev/misskey/issues/13605#issuecomment-2053652123 - /* - cy.window().then(win => { + cy.window(win => { win.indexedDB.deleteDatabase('keyval-store'); }); - */ cy.request('POST', '/api/reset-db', {}).as('reset'); cy.get('@reset').its('status').should('equal', 204); cy.reload(true); diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.js similarity index 100% rename from cypress/support/e2e.ts rename to cypress/support/e2e.js diff --git a/cypress/support/index.ts b/cypress/support/index.ts deleted file mode 100644 index c1bed21979..0000000000 --- a/cypress/support/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -declare global { - namespace Cypress { - interface Chainable { - login(username: string, password: string): Chainable; - - registerUser( - username: string, - password: string, - isAdmin?: boolean - ): Chainable; - - resetState(): Chainable; - - visitHome(): Chainable; - } - } -} - -export {} diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json deleted file mode 100644 index 6fe7f32cc4..0000000000 --- a/cypress/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "lib": ["dom", "es5"], - "target": "es5", - "types": ["cypress", "node"] - }, - "include": ["./**/*.ts"] -} diff --git a/compose.local-db.yml b/docker-compose.local-db.yml similarity index 98% rename from compose.local-db.yml rename to docker-compose.local-db.yml index 3835cb23db..16ba4b49e1 100644 --- a/compose.local-db.yml +++ b/docker-compose.local-db.yml @@ -1,3 +1,5 @@ +version: "3" + # このconfigは、 dockerでMisskey本体を起動せず、 redisとpostgresql などだけを起動します services: diff --git a/compose_example.yml b/docker-compose_example.yml similarity index 58% rename from compose_example.yml rename to docker-compose_example.yml index 0db8b04dc6..b61daa5eb3 100644 --- a/compose_example.yml +++ b/docker-compose_example.yml @@ -1,12 +1,13 @@ +version: "3" + services: web: -# image: registry.activitypub.software/transfem-org/sharkey:latest +# image: git.joinsharkey.org/sharkey/sharkey:latest build: . restart: always links: - db - redis -# - mcaptcha # - meilisearch depends_on: db: @@ -17,10 +18,9 @@ services: - "3000:3000" networks: - shonk - # env_file: - # - .config/docker.env volumes: - ./files:/sharkey/files + - ./cache:/sharkey/cache - ./.config:/sharkey/.config:ro redis: @@ -49,37 +49,6 @@ services: interval: 5s retries: 20 -# mcaptcha: -# restart: always -# image: mcaptcha/mcaptcha:latest -# networks: -# shonk: -# aliases: -# - localhost -# ports: -# - 7493:7493 -# env_file: -# - .config/docker.env -# environment: -# PORT: 7493 -# MCAPTCHA_redis_URL: "redis://mcaptcha_redis/" -# MCAPTCHA_allow_registration: true -# MCAPTCHA_server_DOMAIN: "example.tld" -# depends_on: -# db: -# condition: service_healthy -# mcaptcha_redis: -# condition: service_healthy -# -# mcaptcha_redis: -# image: mcaptcha/cache:latest -# networks: -# - shonk -# healthcheck: -# test: "redis-cli ping" -# interval: 5s -# retries: 20 - # meilisearch: # restart: always # image: getmeili/meilisearch:v1.3.4 diff --git a/eslint/locale.js b/eslint/locale.js deleted file mode 100644 index dbb807b714..0000000000 --- a/eslint/locale.js +++ /dev/null @@ -1,251 +0,0 @@ -/* - * SPDX-FileCopyrightText: dakkar and other Sharkey contributors - * SPDX-License-Identifier: AGPL-3.0-only -*/ - -/* This is a ESLint rule to report use of the `i18n.ts` and `i18n.tsx` - * objects that reference translation items that don't actually exist - * in the lexicon (the `locale/` files) - */ - -/* given a MemberExpression node, collects all the member names - * - * e.g. for a bit of code like `foo=one.two.three`, `collectMembers` - * called on the node for `three` would return `['one', 'two', - * 'three']` - */ -function collectMembers(node) { - if (!node) return []; - if (node.type !== 'MemberExpression') return []; - // this is something like `foo[bar]` - if (node.computed) return []; - return [ node.property.name, ...collectMembers(node.parent) ]; -} - -/* given an object and an array of names, recursively descends the - * object via those names - * - * e.g. `walkDown({one:{two:{three:15}}},['one','two','three'])` would - * return 15 - */ -function walkDown(locale, path) { - if (!locale) return null; - if (!path || path.length === 0 || !path[0]) return locale; - return walkDown(locale[path[0]], path.slice(1)); -} - -/* given a MemberExpression node, returns its attached CallExpression - * node if present - * - * e.g. for a bit of code like `foo=one.two.three()`, - * `findCallExpression` called on the node for `three` would return - * the node for function call (which is the parent of the `one` and - * `two` nodes, and holds the nodes for the argument list) - * - * if the code had been `foo=one.two.three`, `findCallExpression` - * would have returned null, because there's no function call attached - * to the MemberExpressions - */ -function findCallExpression(node) { - if (!node.parent) return null; - - // the second half of this guard protects from cases like - // `foo(one.two.three)` where the CallExpression is parent of the - // MemberExpressions, but via `arguments`, not `callee` - if (node.parent.type === 'CallExpression' && node.parent.callee === node) return node.parent; - if (node.parent.type === 'MemberExpression') return findCallExpression(node.parent); - return null; -} - -// same, but for Vue expressions (``) -function findVueExpression(node) { - if (!node.parent) return null; - - if (node.parent.type.match(/^VExpr/) && node.parent.expression === node) return node.parent; - if (node.parent.type === 'MemberExpression') return findVueExpression(node.parent); - return null; -} - -function areArgumentsOneObject(node) { - return node.arguments.length === 1 && - node.arguments[0].type === 'ObjectExpression'; -} - -// only call if `areArgumentsOneObject(node)` is true -function getArgumentObjectProperties(node) { - return new Set(node.arguments[0].properties.map( - p => { - if (p.key && p.key.type === 'Identifier') return p.key.name; - return null; - }, - )); -} - -function getTranslationParameters(translation) { - return new Set(Array.from(translation.matchAll(/\{(\w+)\}/g)).map( m => m[1] )); -} - -function setDifference(a,b) { - const result = []; - for (const element of a.values()) { - if (!b.has(element)) { - result.push(element); - } - } - - return result; -} - -/* the actual rule body - */ -function theRuleBody(context,node) { - // we get the locale/translations via the options; it's the data - // that goes into a specific language's JSON file, see - // `scripts/build-assets.mjs` - const locale = context.options[0]; - - // sometimes we get MemberExpression nodes that have a - // *descendent* with the right identifier: skip them, we'll get - // the right ones as well - if (node.object?.name !== 'i18n') { - return; - } - - // `method` is going to be `'ts'` or `'tsx'`, `path` is going to - // be the various translation steps/names - const [ method, ...path ] = collectMembers(node); - const pathStr = `i18n.${method}.${path.join('.')}`; - - // does that path point to a real translation? - const translation = walkDown(locale, path); - if (!translation) { - context.report({ - node, - message: `translation missing for ${pathStr}`, - }); - return; - } - - // we hit something weird, assume the programmers know what - // they're doing (this is usually some complicated slicing of - // the translation structure) - if (typeof(translation) !== 'string') return; - - const callExpression = findCallExpression(node); - const vueExpression = findVueExpression(node); - - // some more checks on how the translation is called - if (method === 'ts') { - // the ` component gets parametric translations via - // `i18n.ts.*`, but we error out elsewhere - if (translation.match(/\{/) && !vueExpression) { - context.report({ - node, - message: `translation for ${pathStr} is parametric, but called via 'ts'`, - }); - return; - } - - if (callExpression) { - context.report({ - node, - message: `translation for ${pathStr} is not parametric, but is called as a function`, - }); - } - } - - if (method === 'tsx') { - if (!translation.match(/\{/)) { - context.report({ - node, - message: `translation for ${pathStr} is not parametric, but called via 'tsx'`, - }); - return; - } - - if (!callExpression && !vueExpression) { - context.report({ - node, - message: `translation for ${pathStr} is parametric, but not called as a function`, - }); - return; - } - - // we're not currently checking arguments when used via the - // `` component, because it's too complicated (also, it - // would have to be done inside the `if (method === 'ts')`) - if (!callExpression) return; - - if (!areArgumentsOneObject(callExpression)) { - context.report({ - node, - message: `translation for ${pathStr} should be called with a single object as argument`, - }); - return; - } - - const translationParameters = getTranslationParameters(translation); - const parameterCount = translationParameters.size; - const callArguments = getArgumentObjectProperties(callExpression); - const argumentCount = callArguments.size; - - if (parameterCount !== argumentCount) { - context.report({ - node, - message: `translation for ${pathStr} has ${parameterCount} parameters, but is called with ${argumentCount} arguments`, - }); - } - - // node 20 doesn't have `Set.difference`... - const extraArguments = setDifference(callArguments, translationParameters); - const missingArguments = setDifference(translationParameters, callArguments); - - if (extraArguments.length > 0) { - context.report({ - node, - message: `translation for ${pathStr} passes unused arguments ${extraArguments.join(' ')}`, - }); - } - - if (missingArguments.length > 0) { - context.report({ - node, - message: `translation for ${pathStr} does not pass arguments ${missingArguments.join(' ')}`, - }); - } - } -} - -function theRule(context) { - // we get the locale/translations via the options; it's the data - // that goes into a specific language's JSON file, see - // `scripts/build-assets.mjs` - const locale = context.options[0]; - - // for all object member access that have an identifier 'i18n'... - return context.getSourceCode().parserServices.defineTemplateBodyVisitor( - { - // this is for @@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only - - diff --git a/packages/frontend/src/components/MkCwButton.stories.impl.ts b/packages/frontend/src/components/MkCwButton.stories.impl.ts deleted file mode 100644 index 5d6ea56da9..0000000000 --- a/packages/frontend/src/components/MkCwButton.stories.impl.ts +++ /dev/null @@ -1,79 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -/* eslint-disable @typescript-eslint/explicit-function-return-type */ -/* eslint-disable import/no-default-export */ -import { StoryObj } from '@storybook/vue3'; -import { action } from '@storybook/addon-actions'; -import { expect, userEvent, within } from '@storybook/test'; -import { file } from '../../.storybook/fakes.js'; -import MkCwButton from './MkCwButton.vue'; -import { i18n } from '@/i18n.js'; - -export const Default = { - render(args) { - return { - components: { - MkCwButton, - }, - data() { - return { - showContent: false, - }; - }, - setup() { - return { - args, - }; - }, - computed: { - props() { - return { - ...this.args, - }; - }, - events() { - return { - 'update:modelValue': action('update:modelValue'), - }; - }, - }, - template: '', - }; - }, - args: { - text: 'Some CW content', - }, - async play({ canvasElement }) { - const canvas = within(canvasElement); - const buttonElement = canvas.getByRole('button'); - await expect(buttonElement).toHaveTextContent(i18n.ts._cw.show); - await expect(buttonElement).toHaveTextContent(i18n.tsx._cw.chars({ count: 15 })); - await userEvent.click(buttonElement); - await expect(buttonElement).toHaveTextContent(i18n.ts._cw.hide); - await userEvent.click(buttonElement); - }, - parameters: { - chromatic: { - // NOTE: テストが終わるまで待つ - delay: 5000, - }, - layout: 'centered', - }, -} satisfies StoryObj; -export const IncludesTextAndDriveFile = { - ...Default, - args: { - text: 'Some CW content', - files: [file()], - }, - async play({ canvasElement }) { - const canvas = within(canvasElement); - const buttonElement = canvas.getByRole('button'); - await expect(buttonElement).toHaveTextContent(i18n.tsx._cw.chars({ count: 15 })); - await expect(buttonElement).toHaveTextContent(' / '); - await expect(buttonElement).toHaveTextContent(i18n.tsx._cw.files({ count: 1 })); - }, -} satisfies StoryObj; diff --git a/packages/frontend/src/components/MkCwButton.vue b/packages/frontend/src/components/MkCwButton.vue index b5f6e78b6c..4a6d2dfba2 100644 --- a/packages/frontend/src/components/MkCwButton.vue +++ b/packages/frontend/src/components/MkCwButton.vue @@ -1,5 +1,5 @@ @@ -10,7 +10,6 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/components/MkDialog.stories.impl.ts b/packages/frontend/src/components/MkDialog.stories.impl.ts deleted file mode 100644 index 2d8d3661f2..0000000000 --- a/packages/frontend/src/components/MkDialog.stories.impl.ts +++ /dev/null @@ -1,159 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { action } from '@storybook/addon-actions'; -import { expect, userEvent, waitFor, within } from '@storybook/test'; -import { StoryObj } from '@storybook/vue3'; -import { i18n } from '@/i18n.js'; -import MkDialog from './MkDialog.vue'; -const Base = { - render(args) { - return { - components: { - MkDialog, - }, - setup() { - return { - args, - }; - }, - computed: { - props() { - return { - ...this.args, - }; - }, - events() { - return { - done: action('done'), - closed: action('closed'), - }; - }, - }, - template: '', - }; - }, - args: { - text: 'Hello, world!', - }, - parameters: { - layout: 'centered', - }, -} satisfies StoryObj; -export const Success = { - ...Base, - args: { - ...Base.args, - type: 'success', - }, -} satisfies StoryObj; -export const Error = { - ...Base, - args: { - ...Base.args, - type: 'error', - }, -} satisfies StoryObj; -export const Warning = { - ...Base, - args: { - ...Base.args, - type: 'warning', - }, -} satisfies StoryObj; -export const Info = { - ...Base, - args: { - ...Base.args, - type: 'info', - }, -} satisfies StoryObj; -export const Question = { - ...Base, - args: { - ...Base.args, - type: 'question', - }, -} satisfies StoryObj; -export const Waiting = { - ...Base, - args: { - ...Base.args, - type: 'waiting', - }, -} satisfies StoryObj; -export const DialogWithActions = { - ...Question, - args: { - ...Question.args, - text: i18n.ts.areYouSure, - actions: [ - { - text: i18n.ts.yes, - primary: true, - callback() { - action('YES')(); - }, - }, - { - text: i18n.ts.no, - callback() { - action('NO')(); - }, - }, - ], - }, -} satisfies StoryObj; -export const DialogWithDangerActions = { - ...Warning, - args: { - ...Warning.args, - text: i18n.ts.resetAreYouSure, - actions: [ - { - text: i18n.ts.yes, - danger: true, - primary: true, - callback() { - action('YES')(); - }, - }, - { - text: i18n.ts.no, - callback() { - action('NO')(); - }, - }, - ], - }, -} satisfies StoryObj; -export const DialogWithInput = { - ...Question, - args: { - ...Question.args, - title: 'Hello, world!', - text: undefined, - input: { - placeholder: i18n.ts.inputMessageHere, - type: 'text', - default: null, - minLength: 2, - maxLength: 3, - }, - }, - async play({ canvasElement }) { - const canvas = within(canvasElement); - await expect(canvasElement).toHaveTextContent(i18n.tsx._dialog.charactersBelow({ current: 0, min: 2 })); - const okButton = canvas.getByRole('button', { name: i18n.ts.ok }); - await expect(okButton).toBeDisabled(); - const input = canvas.getByRole('combobox'); - await waitFor(() => userEvent.hover(input)); - await waitFor(() => userEvent.click(input)); - await waitFor(() => userEvent.type(input, 'M')); - await expect(canvasElement).toHaveTextContent(i18n.tsx._dialog.charactersBelow({ current: 1, min: 2 })); - await waitFor(() => userEvent.type(input, 'i')); - await expect(okButton).toBeEnabled(); - }, -} satisfies StoryObj; diff --git a/packages/frontend/src/components/MkDialog.vue b/packages/frontend/src/components/MkDialog.vue index 7dc381b662..2c0f6a4d78 100644 --- a/packages/frontend/src/components/MkDialog.vue +++ b/packages/frontend/src/components/MkDialog.vue @@ -1,10 +1,10 @@ diff --git a/packages/frontend/src/components/MkDonation.stories.impl.ts b/packages/frontend/src/components/MkDonation.stories.impl.ts deleted file mode 100644 index 27d6b7df6c..0000000000 --- a/packages/frontend/src/components/MkDonation.stories.impl.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { action } from '@storybook/addon-actions'; -import { StoryObj } from '@storybook/vue3'; -import { onBeforeUnmount } from 'vue'; -import MkDonation from './MkDonation.vue'; -import { instance } from '@/instance.js'; -export const Default = { - render(args) { - return { - components: { - MkDonation, - }, - setup() { - return { - args, - }; - }, - computed: { - props() { - return { - ...this.args, - }; - }, - events() { - return { - closed: action('closed'), - }; - }, - }, - template: '', - }; - }, - args: { - // @ts-expect-error name is used for mocking instance - name: 'Misskey Hub', - }, - decorators: [ - (_, { args }) => ({ - setup() { - // @ts-expect-error name is used for mocking instance - instance.name = args.name; - onBeforeUnmount(() => instance.name = null); - }, - template: '', - }), - ], - parameters: { - layout: 'centered', - }, -} satisfies StoryObj; diff --git a/packages/frontend/src/components/MkDonation.vue b/packages/frontend/src/components/MkDonation.vue index 1dfdebf0d4..a77ff42f94 100644 --- a/packages/frontend/src/components/MkDonation.vue +++ b/packages/frontend/src/components/MkDonation.vue @@ -1,5 +1,5 @@ @@ -23,17 +23,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- {{ i18n.ts.learnMore }} -
-
-
- - - -
- {{ i18n.ts.learnMore }} + {{ i18n.ts.learnMore }}
@@ -41,14 +31,14 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts.neverShow }}
- + diff --git a/packages/frontend/src/components/MkDriveWindow.stories.impl.ts b/packages/frontend/src/components/MkDriveWindow.stories.impl.ts deleted file mode 100644 index faa1f7fd5f..0000000000 --- a/packages/frontend/src/components/MkDriveWindow.stories.impl.ts +++ /dev/null @@ -1,7 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import MkDriveWindow from './MkDriveWindow.vue'; -void MkDriveWindow; diff --git a/packages/frontend/src/components/MkDriveWindow.vue b/packages/frontend/src/components/MkDriveWindow.vue index c0142ec76e..72aa79b153 100644 --- a/packages/frontend/src/components/MkDriveWindow.vue +++ b/packages/frontend/src/components/MkDriveWindow.vue @@ -1,5 +1,5 @@ diff --git a/packages/frontend/src/components/MkEmbedCodeGenDialog.vue b/packages/frontend/src/components/MkEmbedCodeGenDialog.vue deleted file mode 100644 index c060c3a659..0000000000 --- a/packages/frontend/src/components/MkEmbedCodeGenDialog.vue +++ /dev/null @@ -1,414 +0,0 @@ - - - - - - - diff --git a/packages/frontend/src/components/MkEmojiPicker.section.stories.impl.ts b/packages/frontend/src/components/MkEmojiPicker.section.stories.impl.ts deleted file mode 100644 index 69aef577de..0000000000 --- a/packages/frontend/src/components/MkEmojiPicker.section.stories.impl.ts +++ /dev/null @@ -1,7 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import MkEmojiPicker_section from './MkEmojiPicker.section.vue'; -void MkEmojiPicker_section; diff --git a/packages/frontend/src/components/MkEmojiPicker.section.vue b/packages/frontend/src/components/MkEmojiPicker.section.vue index 151843b18c..dabc12237a 100644 --- a/packages/frontend/src/components/MkEmojiPicker.section.vue +++ b/packages/frontend/src/components/MkEmojiPicker.section.vue @@ -1,5 +1,5 @@ @@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- (:{{ emojis.length }}) + (:{{ emojis.length }})
@@ -28,7 +27,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- (:{{ customEmojiTree?.length }} :{{ emojis.length }}) + (:{{ customEmojiTree.length }} :{{ emojis.length }})
@@ -62,14 +60,13 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/components/MkEmojiPicker.stories.impl.ts b/packages/frontend/src/components/MkEmojiPicker.stories.impl.ts deleted file mode 100644 index d38d8de808..0000000000 --- a/packages/frontend/src/components/MkEmojiPicker.stories.impl.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { action } from '@storybook/addon-actions'; -import { expect, userEvent, waitFor, within } from '@storybook/test'; -import { StoryObj } from '@storybook/vue3'; -import { i18n } from '@/i18n.js'; -import MkEmojiPicker from './MkEmojiPicker.vue'; -export const Default = { - render(args) { - return { - components: { - MkEmojiPicker, - }, - setup() { - return { - args, - }; - }, - computed: { - props() { - return { - ...this.args, - }; - }, - events() { - return { - chosen: action('chosen'), - }; - }, - }, - template: '', - }; - }, - async play({ canvasElement }) { - const canvas = within(canvasElement); - const faceSection = canvas.getByText(/face/i); - await waitFor(() => userEvent.click(faceSection)); - const grinning = canvasElement.querySelector('[data-emoji="😀"]'); - await expect(grinning).toBeInTheDocument(); - if (grinning == null) throw new Error(); // NOTE: not called - await waitFor(() => userEvent.click(grinning)); - const recentUsedSection = canvas.getByText(new RegExp(i18n.ts.recentUsed)).parentElement; - await expect(recentUsedSection).toBeInTheDocument(); - if (recentUsedSection == null) throw new Error(); // NOTE: not called - await expect(within(recentUsedSection).getByAltText('😀')).toBeInTheDocument(); - await expect(within(recentUsedSection).queryByAltText('😬')).toEqual(null); - }, - parameters: { - layout: 'centered', - }, -} satisfies StoryObj; diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index 949ed4db91..b7e329d7c2 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -1,23 +1,11 @@ @@ -117,6 +101,7 @@ SPDX-License-Identifier: AGPL-3.0-only + + diff --git a/packages/frontend/src/components/MkFeaturedPhotos.vue b/packages/frontend/src/components/MkFeaturedPhotos.vue index c42c692db0..6d1bad7433 100644 --- a/packages/frontend/src/components/MkFeaturedPhotos.vue +++ b/packages/frontend/src/components/MkFeaturedPhotos.vue @@ -1,14 +1,22 @@ diff --git a/packages/frontend/src/components/MkFollowButton.vue b/packages/frontend/src/components/MkFollowButton.vue index 52497a2994..d1b1956a03 100644 --- a/packages/frontend/src/components/MkFollowButton.vue +++ b/packages/frontend/src/components/MkFollowButton.vue @@ -1,5 +1,5 @@ @@ -12,20 +12,20 @@ SPDX-License-Identifier: AGPL-3.0-only > -
- @@ -79,24 +68,19 @@ import MkSelect from './MkSelect.vue'; import MkRange from './MkRange.vue'; import MkButton from './MkButton.vue'; import MkRadios from './MkRadios.vue'; -import XFile from './MkFormDialog.file.vue'; -import type { Form } from '@/scripts/form.js'; import MkModalWindow from '@/components/MkModalWindow.vue'; import { i18n } from '@/i18n.js'; -import { infoImageUrl } from '@/instance.js'; const props = defineProps<{ title: string; - form: Form; + form: any; }>(); const emit = defineEmits<{ (ev: 'done', v: { - canceled: true; - } | { - result: Record; + canceled?: boolean; + result?: any; }): void; - (ev: 'closed'): void; }>(); const dialog = shallowRef>(); @@ -110,13 +94,13 @@ function ok() { emit('done', { result: values, }); - dialog.value?.close(); + dialog.value.close(); } function cancel() { emit('done', { canceled: true, }); - dialog.value?.close(); + dialog.value.close(); } diff --git a/packages/frontend/src/components/MkFormFooter.vue b/packages/frontend/src/components/MkFormFooter.vue deleted file mode 100644 index 1e88d59d8e..0000000000 --- a/packages/frontend/src/components/MkFormFooter.vue +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - diff --git a/packages/frontend/src/components/MkFormula.vue b/packages/frontend/src/components/MkFormula.vue new file mode 100644 index 0000000000..039cef8da8 --- /dev/null +++ b/packages/frontend/src/components/MkFormula.vue @@ -0,0 +1,33 @@ + + + + + + + diff --git a/packages/frontend/src/components/MkGalleryPostPreview.stories.impl.ts b/packages/frontend/src/components/MkGalleryPostPreview.stories.impl.ts index a433ad680b..035b727a35 100644 --- a/packages/frontend/src/components/MkGalleryPostPreview.stories.impl.ts +++ b/packages/frontend/src/components/MkGalleryPostPreview.stories.impl.ts @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-FileCopyrightText: syuilo and other misskey contributors * SPDX-License-Identifier: AGPL-3.0-only */ /* eslint-disable @typescript-eslint/explicit-function-return-type */ -import { expect, userEvent, waitFor, within } from '@storybook/test'; +import { expect } from '@storybook/jest'; +import { userEvent, waitFor, within } from '@storybook/testing-library'; import { StoryObj } from '@storybook/vue3'; import { galleryPost } from '../../.storybook/fakes.js'; import MkGalleryPostPreview from './MkGalleryPostPreview.vue'; diff --git a/packages/frontend/src/components/MkGalleryPostPreview.vue b/packages/frontend/src/components/MkGalleryPostPreview.vue index 2bb5b8762a..316632b1a6 100644 --- a/packages/frontend/src/components/MkGalleryPostPreview.vue +++ b/packages/frontend/src/components/MkGalleryPostPreview.vue @@ -1,5 +1,5 @@ @@ -14,8 +14,8 @@ SPDX-License-Identifier: AGPL-3.0-only leaveActiveClass: $style.transition_toggle_leaveActive, leaveToClass: $style.transition_toggle_leaveTo, }" - :src="post.files?.[0]?.thumbnailUrl" - :hash="post.files?.[0]?.blurhash" + :src="post.files[0].thumbnailUrl" + :hash="post.files[0].blurhash" :forceBlurhash="!show" /> @@ -83,7 +83,7 @@ function leaveHover(): void { > article { > footer { - &::before { + &:before { opacity: 1; } } @@ -139,7 +139,7 @@ function leaveHover(): void { text-shadow: 0 0 8px #000; background: linear-gradient(transparent, rgba(0, 0, 0, 0.7)); - &::before { + &:before { content: ""; display: block; position: absolute; diff --git a/packages/frontend/src/components/MkGoogle.vue b/packages/frontend/src/components/MkGoogle.vue index 54c7585f18..c0b20507fc 100644 --- a/packages/frontend/src/components/MkGoogle.vue +++ b/packages/frontend/src/components/MkGoogle.vue @@ -1,19 +1,18 @@ diff --git a/packages/frontend/src/components/MkHeatmap.vue b/packages/frontend/src/components/MkHeatmap.vue index 0cc0df9911..a57e6c9292 100644 --- a/packages/frontend/src/components/MkHeatmap.vue +++ b/packages/frontend/src/components/MkHeatmap.vue @@ -1,5 +1,5 @@ @@ -15,8 +15,7 @@ SPDX-License-Identifier: AGPL-3.0-only - - diff --git a/packages/frontend/src/components/MkImgWithBlurhash.vue b/packages/frontend/src/components/MkImgWithBlurhash.vue index c04d0864fb..942861e1f4 100644 --- a/packages/frontend/src/components/MkImgWithBlurhash.vue +++ b/packages/frontend/src/components/MkImgWithBlurhash.vue @@ -1,5 +1,5 @@ @@ -14,8 +14,8 @@ SPDX-License-Identifier: AGPL-3.0-only :enterToClass="defaultStore.state.animation && props.transition?.enterToClass || undefined" :leaveFromClass="defaultStore.state.animation && props.transition?.leaveFromClass || undefined" > - - + +
@@ -23,8 +23,8 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/components/MkInstanceTicker.vue b/packages/frontend/src/components/MkInstanceTicker.vue index 46d42248d3..e358a1c549 100644 --- a/packages/frontend/src/components/MkInstanceTicker.vue +++ b/packages/frontend/src/components/MkInstanceTicker.vue @@ -1,5 +1,5 @@ @@ -12,15 +12,15 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -119,7 +119,6 @@ function close() { margin-top: 12px; font-size: 0.8em; line-height: 1.5em; - text-align: center; } > .indicatorWithValue { @@ -139,7 +138,7 @@ function close() { left: 32px; color: var(--indicator); font-size: 8px; - animation: global-blink 1s infinite; + animation: blink 1s infinite; @media (max-width: 500px) { top: 16px; diff --git a/packages/frontend/src/components/MkLink.vue b/packages/frontend/src/components/MkLink.vue index 263cd95eb1..bda683002d 100644 --- a/packages/frontend/src/components/MkLink.vue +++ b/packages/frontend/src/components/MkLink.vue @@ -1,34 +1,27 @@ diff --git a/packages/frontend/src/components/MkMediaBanner.vue b/packages/frontend/src/components/MkMediaBanner.vue index 77a86ff2fb..7b0387cefe 100644 --- a/packages/frontend/src/components/MkMediaBanner.vue +++ b/packages/frontend/src/components/MkMediaBanner.vue @@ -1,53 +1,54 @@ diff --git a/packages/frontend/src/components/MkMediaVideo.vue b/packages/frontend/src/components/MkMediaVideo.vue index 0502bdd401..a1950b110a 100644 --- a/packages/frontend/src/components/MkMediaVideo.vue +++ b/packages/frontend/src/components/MkMediaVideo.vue @@ -1,505 +1,71 @@ diff --git a/packages/frontend/src/components/SkMfmWindow.vue b/packages/frontend/src/components/MkMfmWindow.vue similarity index 74% rename from packages/frontend/src/components/SkMfmWindow.vue rename to packages/frontend/src/components/MkMfmWindow.vue index c599531ec5..ce2a0e7391 100644 --- a/packages/frontend/src/components/SkMfmWindow.vue +++ b/packages/frontend/src/components/MkMfmWindow.vue @@ -1,8 +1,3 @@ - - - +
{{ i18n.ts._mfm.intro }}
-
+
{{ i18n.ts._mfm.mention }}

{{ i18n.ts._mfm.mentionDescription }}

- +
@@ -34,7 +29,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.hashtagDescription }}

- +
@@ -44,7 +39,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.linkDescription }}

- +
@@ -54,7 +49,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.emojiDescription }}

- +
@@ -64,7 +59,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.boldDescription }}

- +
@@ -74,7 +69,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.smallDescription }}

- +
@@ -84,7 +79,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.quoteDescription }}

- +
@@ -94,7 +89,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.centerDescription }}

- +
@@ -104,7 +99,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.inlineCodeDescription }}

- +
@@ -114,7 +109,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.blockCodeDescription }}

- +
@@ -124,7 +119,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.inlineMathDescription }}

- +
@@ -134,7 +129,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.blockMathDescription }}

- +
@@ -144,7 +139,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.searchDescription }}

- +
@@ -154,7 +149,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.flipDescription }}

- +
@@ -164,7 +159,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.fontDescription }}

- +
@@ -174,7 +169,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.x2Description }}

- +
@@ -184,7 +179,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.x3Description }}

- +
@@ -194,7 +189,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.x4Description }}

- +
@@ -204,7 +199,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.blurDescription }}

- +
@@ -214,7 +209,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.jellyDescription }}

- +
@@ -224,7 +219,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.tadaDescription }}

- +
@@ -234,7 +229,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.jumpDescription }}

- +
@@ -244,7 +239,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.bounceDescription }}

- +
@@ -254,7 +249,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.spinDescription }}

- +
@@ -264,7 +259,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.shakeDescription }}

- +
@@ -274,7 +269,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.twitchDescription }}

- +
@@ -284,7 +279,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.rainbowDescription }}

- +
@@ -294,7 +289,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.sparkleDescription }}

- + MFM
@@ -304,69 +299,37 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.rotateDescription }}

- + MFM
-
-
{{ i18n.ts._mfm.crop }}
-
-

{{ i18n.ts._mfm.cropDescription }}

-
- - MFM -
-
-
{{ i18n.ts._mfm.position }}

{{ i18n.ts._mfm.positionDescription }}

- + MFM
-
-
{{ i18n.ts._mfm.followMouse }}
- {{ i18n.ts._mfm.uncommonFeature }} -
-
-

{{ i18n.ts._mfm.followMouseDescription }}

-
- - MFM -
-
-
{{ i18n.ts._mfm.scale }}

{{ i18n.ts._mfm.scaleDescription }}

- + MFM
-
-
{{ i18n.ts._mfm.fade }}
-
-

{{ i18n.ts._mfm.fadeDescription }}

-
- - MFM -
-
-
{{ i18n.ts._mfm.foreground }}

{{ i18n.ts._mfm.foregroundDescription }}

- + MFM
@@ -376,7 +339,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.backgroundDescription }}

- + MFM
@@ -386,7 +349,7 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ i18n.ts._mfm.plainDescription }}

- + MFM
@@ -399,19 +362,18 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/components/MkModal.vue b/packages/frontend/src/components/MkModal.vue index c766a33823..5cd31cdf7c 100644 --- a/packages/frontend/src/components/MkModal.vue +++ b/packages/frontend/src/components/MkModal.vue @@ -1,5 +1,5 @@ @@ -30,9 +30,9 @@ SPDX-License-Identifier: AGPL-3.0-only [$style.transition_modal_leaveTo]: transitionName === 'modal', [$style.transition_send_leaveTo]: transitionName === 'send', })" - :duration="transitionDuration" appear @afterLeave="onClosed" @enter="emit('opening')" @afterEnter="onOpened" + :duration="transitionDuration" appear @afterLeave="emit('closed')" @enter="emit('opening')" @afterEnter="onOpened" > -
+
@@ -47,9 +47,6 @@ import * as os from '@/os.js'; import { isTouchUsing } from '@/scripts/touch.js'; import { defaultStore } from '@/store.js'; import { deviceKind } from '@/scripts/device-kind.js'; -import { type Keymap } from '@/scripts/hotkey.js'; -import { focusTrap } from '@/scripts/focus-trap.js'; -import { focusParent } from '@/scripts/focus.js'; function getFixedContainer(el: Element | null): Element | null { if (el == null || el.tagName === 'BODY') return null; @@ -71,8 +68,6 @@ const props = withDefaults(defineProps<{ zPriority?: 'low' | 'middle' | 'high'; noOverlap?: boolean; transparentBg?: boolean; - hasInteractionWithOtherFocusTrappedEls?: boolean; - returnFocusTo?: HTMLElement | null; }>(), { manualShowing: null, src: null, @@ -81,8 +76,6 @@ const props = withDefaults(defineProps<{ zPriority: 'low', noOverlap: true, transparentBg: false, - hasInteractionWithOtherFocusTrappedEls: false, - returnFocusTo: null, }); const emit = defineEmits<{ @@ -100,13 +93,12 @@ const maxHeight = ref(); const fixed = ref(false); const transformOrigin = ref('center'); const showing = ref(true); -const modalRootEl = shallowRef(); const content = shallowRef(); const zIndex = os.claimZIndex(props.zPriority); const useSendAnime = ref(false); const type = computed(() => { if (props.preferType === 'auto') { - if ((defaultStore.state.menuStyle === 'drawer') || (defaultStore.state.menuStyle === 'auto' && isTouchUsing && deviceKind === 'smartphone')) { + if (!defaultStore.state.disableDrawer && isTouchUsing && deviceKind === 'smartphone') { return 'drawer'; } else { return props.src != null ? 'popup' : 'dialog'; @@ -139,7 +131,6 @@ const transitionDuration = computed((() => : 0 )); -let releaseFocusTrap: (() => void) | null = null; let contentClicking = false; function close(opts: { useSendAnimation?: boolean } = {}) { @@ -163,11 +154,8 @@ if (type.value === 'drawer') { } const keymap = { - 'esc': { - allowRepeat: true, - callback: () => emit('esc'), - }, -} as const satisfies Keymap; + 'esc': () => emit('esc'), +}; const MARGIN = 16; const SCROLLBAR_THICKNESS = 16; @@ -187,8 +175,8 @@ const align = () => { let left; let top; - const x = srcRect.left + (fixed.value ? 0 : window.scrollX); - const y = srcRect.top + (fixed.value ? 0 : window.scrollY); + const x = srcRect.left + (fixed.value ? 0 : window.pageXOffset); + const y = srcRect.top + (fixed.value ? 0 : window.pageYOffset); if (props.anchor.x === 'center') { left = x + (props.src.offsetWidth / 2) - (width / 2); @@ -232,24 +220,24 @@ const align = () => { } } else { // 画面から横にはみ出る場合 - if (left + width - window.scrollX > (window.innerWidth - SCROLLBAR_THICKNESS)) { - left = (window.innerWidth - SCROLLBAR_THICKNESS) - width + window.scrollX - 1; + if (left + width - window.pageXOffset > (window.innerWidth - SCROLLBAR_THICKNESS)) { + left = (window.innerWidth - SCROLLBAR_THICKNESS) - width + window.pageXOffset - 1; } - const underSpace = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - (top - window.scrollY); + const underSpace = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - (top - window.pageYOffset); const upperSpace = (srcRect.top - MARGIN); // 画面から縦にはみ出る場合 - if (top + height - window.scrollY > ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN)) { + if (top + height - window.pageYOffset > ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN)) { if (props.noOverlap && props.anchor.x === 'center') { if (underSpace >= (upperSpace / 3)) { maxHeight.value = underSpace; } else { maxHeight.value = upperSpace; - top = window.scrollY + ((upperSpace + MARGIN) - height); + top = window.pageYOffset + ((upperSpace + MARGIN) - height); } } else { - top = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - height + window.scrollY - 1; + top = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - height + window.pageYOffset - 1; } } else { maxHeight.value = underSpace; @@ -267,15 +255,15 @@ const align = () => { let transformOriginX = 'center'; let transformOriginY = 'center'; - if (top >= srcRect.top + props.src.offsetHeight + (fixed.value ? 0 : window.scrollY)) { + if (top >= srcRect.top + props.src.offsetHeight + (fixed.value ? 0 : window.pageYOffset)) { transformOriginY = 'top'; - } else if ((top + height) <= srcRect.top + (fixed.value ? 0 : window.scrollY)) { + } else if ((top + height) <= srcRect.top + (fixed.value ? 0 : window.pageYOffset)) { transformOriginY = 'bottom'; } - if (left >= srcRect.left + props.src.offsetWidth + (fixed.value ? 0 : window.scrollX)) { + if (left >= srcRect.left + props.src.offsetWidth + (fixed.value ? 0 : window.pageXOffset)) { transformOriginX = 'left'; - } else if ((left + width) <= srcRect.left + (fixed.value ? 0 : window.scrollX)) { + } else if ((left + width) <= srcRect.left + (fixed.value ? 0 : window.pageXOffset)) { transformOriginX = 'right'; } @@ -288,11 +276,8 @@ const align = () => { const onOpened = () => { emit('opened'); - // NOTE: Chromatic テストの際に undefined になる場合がある - if (content.value == null) return; - // モーダルコンテンツにマウスボタンが押され、コンテンツ外でマウスボタンが離されたときにモーダルバックグラウンドクリックと判定させないためにマウスイベントを監視しフラグ管理する - const el = content.value.children[0]; + const el = content.value!.children[0]; el.addEventListener('mousedown', ev => { contentClicking = true; window.addEventListener('mouseup', ev => { @@ -304,10 +289,6 @@ const onOpened = () => { }, { passive: true }); }; -const onClosed = () => { - emit('closed'); -}; - const alignObserver = new ResizeObserver((entries, observer) => { align(); }); @@ -325,20 +306,6 @@ onMounted(() => { align(); }, { immediate: true }); - watch([showing, () => props.manualShowing], ([showing, manualShowing]) => { - if (manualShowing === true || (manualShowing == null && showing === true)) { - if (modalRootEl.value != null) { - const { release } = focusTrap(modalRootEl.value, props.hasInteractionWithOtherFocusTrappedEls); - - releaseFocusTrap = release; - modalRootEl.value.focus(); - } - } else { - releaseFocusTrap?.(); - focusParent(props.returnFocusTo ?? props.src, true, false); - } - }, { immediate: true }); - nextTick(() => { alignObserver.observe(content.value!); }); diff --git a/packages/frontend/src/components/MkModalWindow.vue b/packages/frontend/src/components/MkModalWindow.vue index f26959888b..b91988304d 100644 --- a/packages/frontend/src/components/MkModalWindow.vue +++ b/packages/frontend/src/components/MkModalWindow.vue @@ -1,18 +1,18 @@ +
diff --git a/packages/frontend/src/components/MkUserAnnouncementEditDialog.vue b/packages/frontend/src/components/MkUserAnnouncementEditDialog.vue index 3c5f563aa0..3fbadbe34f 100644 --- a/packages/frontend/src/components/MkUserAnnouncementEditDialog.vue +++ b/packages/frontend/src/components/MkUserAnnouncementEditDialog.vue @@ -1,5 +1,5 @@ @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -24,10 +24,10 @@ SPDX-License-Identifier: AGPL-3.0-only - - - - + + + + @@ -39,11 +39,11 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts._announcement.needConfirmationToRead }} - {{ i18n.ts.delete }} + {{ i18n.ts.delete }}
- {{ props.announcement ? i18n.ts.update : i18n.ts.create }} + {{ props.announcement ? i18n.ts.update : i18n.ts.create }}
@@ -56,7 +56,6 @@ import MkModalWindow from '@/components/MkModalWindow.vue'; import MkButton from '@/components/MkButton.vue'; import MkInput from '@/components/MkInput.vue'; import * as os from '@/os.js'; -import { misskeyApi } from '@/scripts/misskey-api.js'; import { i18n } from '@/i18n.js'; import MkTextarea from '@/components/MkTextarea.vue'; import MkSwitch from '@/components/MkSwitch.vue'; @@ -64,14 +63,14 @@ import MkRadios from '@/components/MkRadios.vue'; const props = defineProps<{ user: Misskey.entities.User, - announcement?: Misskey.entities.Announcement, + announcement?: any, }>(); const dialog = ref | null>(null); -const title = ref(props.announcement ? props.announcement.title : ''); -const text = ref(props.announcement ? props.announcement.text : ''); -const icon = ref(props.announcement ? props.announcement.icon : 'info'); -const display = ref(props.announcement ? props.announcement.display : 'dialog'); +const title = ref(props.announcement ? props.announcement.title : ''); +const text = ref(props.announcement ? props.announcement.text : ''); +const icon = ref(props.announcement ? props.announcement.icon : 'info'); +const display = ref(props.announcement ? props.announcement.display : 'dialog'); const needConfirmationToRead = ref(props.announcement ? props.announcement.needConfirmationToRead : false); const emit = defineEmits<{ @@ -92,18 +91,18 @@ async function done() { if (props.announcement) { await os.apiWithDialog('admin/announcements/update', { - ...params, id: props.announcement.id, + ...params, }); emit('done', { updated: { - ...params, id: props.announcement.id, + ...params, }, }); - dialog.value?.close(); + dialog.value.close(); } else { const created = await os.apiWithDialog('admin/announcements/create', params); @@ -111,27 +110,25 @@ async function done() { created: created, }); - dialog.value?.close(); + dialog.value.close(); } } async function del() { const { canceled } = await os.confirm({ type: 'warning', - text: i18n.tsx.removeAreYouSure({ x: title.value }), + text: i18n.t('removeAreYouSure', { x: title.value }), }); if (canceled) return; - if (props.announcement) { - await misskeyApi('admin/announcements/delete', { - id: props.announcement.id, + os.api('admin/announcements/delete', { + id: props.announcement.id, + }).then(() => { + emit('done', { + deleted: true, }); - } - - emit('done', { - deleted: true, + dialog.value.close(); }); - dialog.value?.close(); } diff --git a/packages/frontend/src/components/MkUserCardMini.vue b/packages/frontend/src/components/MkUserCardMini.vue index 603f9f2435..b9c7377972 100644 --- a/packages/frontend/src/components/MkUserCardMini.vue +++ b/packages/frontend/src/components/MkUserCardMini.vue @@ -1,16 +1,16 @@ @@ -18,7 +18,7 @@ SPDX-License-Identifier: AGPL-3.0-only import * as Misskey from 'misskey-js'; import { onMounted, ref } from 'vue'; import MkMiniChart from '@/components/MkMiniChart.vue'; -import { misskeyApiGet } from '@/scripts/misskey-api.js'; +import * as os from '@/os.js'; import { acct } from '@/filters/user.js'; const props = withDefaults(defineProps<{ @@ -32,7 +32,7 @@ const chartValues = ref(null); onMounted(() => { if (props.withChart) { - misskeyApiGet('charts/user/notes', { userId: props.user.id, limit: 16 + 1, span: 'day' }).then(res => { + os.apiGet('charts/user/notes', { userId: props.user.id, limit: 16 + 1, span: 'day' }).then(res => { // 今日のぶんの値はまだ途中の値であり、それも含めると大抵の場合前日よりも下降しているようなグラフになってしまうため今日は弾く res.inc.splice(0, 1); chartValues.value = res.inc; @@ -42,53 +42,77 @@ onMounted(() => { diff --git a/packages/frontend/src/components/MkUserInfo.vue b/packages/frontend/src/components/MkUserInfo.vue index 73cdd9ce00..0e3f3914b8 100644 --- a/packages/frontend/src/components/MkUserInfo.vue +++ b/packages/frontend/src/components/MkUserInfo.vue @@ -1,28 +1,20 @@ @@ -49,8 +41,6 @@ import { userPage } from '@/filters/user.js'; import { i18n } from '@/i18n.js'; import { $i } from '@/account.js'; import { isFollowingVisibleForMe, isFollowersVisibleForMe } from '@/scripts/isFfVisibleForMe.js'; -import { getStaticImageUrl } from '@/scripts/media-proxy.js'; -import { defaultStore } from '@/store.js'; defineProps<{ user: Misskey.entities.UserDetailed; @@ -152,30 +142,4 @@ defineProps<{ top: 8px; right: 8px; } - -.infoBadges { - position: absolute; - top: 12px; - left: 12px; - - display: flex; - flex-direction: row; - - padding: 0; - margin: 0; - - > * { - padding: 4px 8px; - color: #fff; - background: rgba(0, 0, 0, 0.7); - font-size: 0.7em; - border-radius: var(--radius-sm); - list-style-type: none; - margin-left: 0; - } - - > :not(:first-child) { - margin-left: 8px; - } -} diff --git a/packages/frontend/src/components/MkUserList.vue b/packages/frontend/src/components/MkUserList.vue index ac82ecc3d6..56a61dce23 100644 --- a/packages/frontend/src/components/MkUserList.vue +++ b/packages/frontend/src/components/MkUserList.vue @@ -1,10 +1,10 @@ @@ -51,10 +51,9 @@ import { watch, ref, computed } from 'vue'; import MkFoldableSection from '@/components/MkFoldableSection.vue'; import MkPagination from '@/components/MkPagination.vue'; import MkGalleryPostPreview from '@/components/MkGalleryPostPreview.vue'; -import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; import { definePageMetadata } from '@/scripts/page-metadata.js'; import { i18n } from '@/i18n.js'; -import { useRouter } from '@/router/supplier.js'; +import { useRouter } from '@/router.js'; const router = useRouter(); @@ -98,7 +97,7 @@ watch(() => props.tag, () => { }); const headerActions = computed(() => [{ - icon: 'ti ti-plus', + icon: 'ph-plus ph-bold ph-lg', text: i18n.ts.create, handler: () => { router.push('/gallery/new'); @@ -112,17 +111,17 @@ const headerTabs = computed(() => [{ }, { key: 'liked', title: i18n.ts._gallery.liked, - icon: 'ti ti-heart', + icon: 'ph-heart ph-bold ph-lg', }, { key: 'my', title: i18n.ts._gallery.my, - icon: 'ti ti-edit', + icon: 'ph-pencil-line ph-bold ph-lg', }]); -definePageMetadata(() => ({ +definePageMetadata({ title: i18n.ts.gallery, icon: 'ph-images-square ph-bold ph-lg', -})); +}); diff --git a/packages/frontend/src/pages/install-extensions.vue b/packages/frontend/src/pages/install-extentions.vue similarity index 93% rename from packages/frontend/src/pages/install-extensions.vue rename to packages/frontend/src/pages/install-extentions.vue index 4bee437f65..7e6c75ac99 100644 --- a/packages/frontend/src/pages/install-extensions.vue +++ b/packages/frontend/src/pages/install-extentions.vue @@ -1,5 +1,5 @@ @@ -10,9 +10,9 @@ SPDX-License-Identifier: AGPL-3.0-only
- - - + + +

{{ i18n.ts._externalResourceInstaller[`_${data.type}`].title }}

{{ i18n.ts._externalResourceInstaller.checkVendorBeforeInstall }}
@@ -51,7 +51,7 @@ SPDX-License-Identifier: AGPL-3.0-only - + @@ -69,18 +69,18 @@ SPDX-License-Identifier: AGPL-3.0-only
- {{ i18n.ts.install }} + {{ i18n.ts.install }}
- +

{{ errorKV?.title }}

{{ errorKV?.description }}
@@ -105,7 +105,6 @@ import MkInfo from '@/components/MkInfo.vue'; import MkFolder from '@/components/MkFolder.vue'; import MkKeyValue from '@/components/MkKeyValue.vue'; import * as os from '@/os.js'; -import { misskeyApi } from '@/scripts/misskey-api.js'; import { AiScriptPluginMeta, parsePluginMeta, installPlugin } from '@/scripts/install-plugin.js'; import { parseThemeCode, installTheme } from '@/scripts/install-theme.js'; import { unisonReload } from '@/scripts/unison-reload.js'; @@ -160,7 +159,7 @@ async function fetch() { uiPhase.value = 'error'; return; } - const res = await misskeyApi('fetch-external-resources', { + const res = await os.api('fetch-external-resources', { url: url.value, hash: hash.value, }).catch((err) => { @@ -312,10 +311,10 @@ const headerActions = computed(() => []); const headerTabs = computed(() => []); -definePageMetadata(() => ({ +definePageMetadata({ title: i18n.ts._externalResourceInstaller.title, - icon: 'ti ti-download', -})); + icon: 'ph-download ph-bold ph-lg', +}); diff --git a/packages/frontend/src/pages/invite.vue b/packages/frontend/src/pages/invite.vue index ef485a9446..6ac78a2068 100644 --- a/packages/frontend/src/pages/invite.vue +++ b/packages/frontend/src/pages/invite.vue @@ -1,5 +1,5 @@ @@ -12,16 +12,16 @@ SPDX-License-Identifier: AGPL-3.0-only
- + {{ i18n.ts.nothing }}
-
{{ i18n.tsx.inviteLimitResetCycle({ time: resetCycle, limit: inviteLimit }) }}
- {{ i18n.ts.createInviteCode }} -
{{ i18n.tsx.createLimitRemaining({ limit: currentInviteLimit }) }}
+
{{ i18n.t('inviteLimitResetCycle', { time: resetCycle, limit: inviteLimit }) }}
+ {{ i18n.ts.createInviteCode }} +
{{ i18n.t('createLimitRemaining', { limit: currentInviteLimit }) }}
@@ -82,8 +82,8 @@ const headerActions = computed(() => []); const headerTabs = computed(() => []); -definePageMetadata(() => ({ +definePageMetadata({ title: 'Create new webhook', - icon: 'ti ti-webhook', -})); + icon: 'ph-webhooks-logo ph-bold ph-lg', +}); diff --git a/packages/frontend/src/pages/settings/webhook.vue b/packages/frontend/src/pages/settings/webhook.vue index 0d11b00c97..c391458274 100644 --- a/packages/frontend/src/pages/settings/webhook.vue +++ b/packages/frontend/src/pages/settings/webhook.vue @@ -1,5 +1,5 @@ @@ -15,10 +15,10 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ webhook.name || webhook.url }}