Merge branch 'develop' of https://codeberg.org/calckey/calckey into notifications
This commit is contained in:
commit
3a92e77c6c
35
README.md
35
README.md
|
@ -82,8 +82,8 @@ If you have access to a server that supports one of the sources below, I recomme
|
||||||
- 🍱 At least [Redis](https://redis.io/) v6 (v7 recommend)
|
- 🍱 At least [Redis](https://redis.io/) v6 (v7 recommend)
|
||||||
- Web Proxy (one of the following)
|
- Web Proxy (one of the following)
|
||||||
- 🍀 Nginx (recommended)
|
- 🍀 Nginx (recommended)
|
||||||
- 🪶 Apache
|
|
||||||
- 🦦 Caddy
|
- 🦦 Caddy
|
||||||
|
- 🪶 Apache
|
||||||
|
|
||||||
### 😗 Optional dependencies
|
### 😗 Optional dependencies
|
||||||
|
|
||||||
|
@ -107,7 +107,8 @@ git clone --depth 1 https://codeberg.org/calckey/calckey.git
|
||||||
cd calckey/
|
cd calckey/
|
||||||
```
|
```
|
||||||
|
|
||||||
By default, you're on the development branch. Run `git checkout beta` or `git checkout main` to switch to the Beta/Main branches.
|
> **Note**
|
||||||
|
> By default, you're on the main branch. Run `git checkout beta` or `git checkout develop` to switch to the Beta/Develop branches.
|
||||||
|
|
||||||
## 📩 Install dependencies
|
## 📩 Install dependencies
|
||||||
|
|
||||||
|
@ -128,11 +129,18 @@ npm i -g pm2
|
||||||
pm2 install pm2-logrotate
|
pm2 install pm2-logrotate
|
||||||
```
|
```
|
||||||
|
|
||||||
[`pm2-logrotate`](https://github.com/keymetrics/pm2-logrotate/blob/master/README.md) ensures that log files don't infinitely gather size, as Calckey produces a lot of logs.
|
> **Note**
|
||||||
|
> [`pm2-logrotate`](https://github.com/keymetrics/pm2-logrotate/blob/master/README.md) ensures that log files don't infinitely gather size, as Calckey produces a lot of logs.
|
||||||
|
|
||||||
## 🐘 Create database
|
## 🐘 Create database
|
||||||
|
|
||||||
Assuming you set up PostgreSQL correctly, all you have to run is:
|
In PostgreSQL (`psql`), run the following command:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE DATABASE calckey WITH encoding = 'UTF8';
|
||||||
|
```
|
||||||
|
|
||||||
|
or run the following from the command line:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
psql postgres -c "create database calckey with encoding = 'UTF8';"
|
psql postgres -c "create database calckey with encoding = 'UTF8';"
|
||||||
|
@ -144,7 +152,8 @@ In Calckey's directory, fill out the `db` section of `.config/default.yml` with
|
||||||
|
|
||||||
Follow sonic's [installation guide](https://github.com/valeriansaliou/sonic#installation)
|
Follow sonic's [installation guide](https://github.com/valeriansaliou/sonic#installation)
|
||||||
|
|
||||||
If you use IPv4: in Sonic's directory, edit the `config.cfg` file to change `inet` to `"0.0.0.0:1491"`.
|
> **Note**
|
||||||
|
> If you use IPv4: in Sonic's directory, edit the `config.cfg` file to change `inet` to `"0.0.0.0:1491"`.
|
||||||
|
|
||||||
In Calckey's directory, fill out the `sonic` section of `.config/default.yml` with the correct information.
|
In Calckey's directory, fill out the `sonic` section of `.config/default.yml` with the correct information.
|
||||||
|
|
||||||
|
@ -177,13 +186,6 @@ For migrating from Misskey v13, Misskey v12, and Foundkey, read [this document](
|
||||||
- Run `sudo ln -s ./calckey.nginx.conf ../sites-enabled/calckey.nginx.conf`
|
- Run `sudo ln -s ./calckey.nginx.conf ../sites-enabled/calckey.nginx.conf`
|
||||||
- Run `sudo nginx -t` to validate that the config is valid, then restart the NGINX service.
|
- Run `sudo nginx -t` to validate that the config is valid, then restart the NGINX service.
|
||||||
|
|
||||||
### 🪶 Apache
|
|
||||||
|
|
||||||
- Run `sudo cp ./calckey.apache.conf /etc/apache2/sites-available/ && cd /etc/apache2/sites-available/`
|
|
||||||
- Edit `calckey.apache.conf` to reflect your instance properly
|
|
||||||
- Run `sudo a2ensite calckey.apache` to enable the site
|
|
||||||
- Run `sudo service apache2 restart` to reload apache2 configuration
|
|
||||||
|
|
||||||
### 🦦 Caddy
|
### 🦦 Caddy
|
||||||
|
|
||||||
- Add the following block to your `Caddyfile`, replacing `example.tld` with your own domain:
|
- Add the following block to your `Caddyfile`, replacing `example.tld` with your own domain:
|
||||||
|
@ -194,6 +196,15 @@ example.tld {
|
||||||
```
|
```
|
||||||
- Reload your caddy configuration
|
- Reload your caddy configuration
|
||||||
|
|
||||||
|
### 🪶 Apache
|
||||||
|
|
||||||
|
> **Warning**
|
||||||
|
> Apache has some known problems with Calckey. Only use it if you have to.
|
||||||
|
|
||||||
|
- Run `sudo cp ./calckey.apache.conf /etc/apache2/sites-available/ && cd /etc/apache2/sites-available/`
|
||||||
|
- Edit `calckey.apache.conf` to reflect your instance properly
|
||||||
|
- Run `sudo a2ensite calckey.apache` to enable the site
|
||||||
|
- Run `sudo service apache2 restart` to reload apache2 configuration
|
||||||
## 🚀 Build and launch!
|
## 🚀 Build and launch!
|
||||||
|
|
||||||
### 🐢 NodeJS + pm2
|
### 🐢 NodeJS + pm2
|
||||||
|
|
|
@ -1290,7 +1290,7 @@ loadRawImages: Carregar les imatges originals en comptes de mostrar les miniatur
|
||||||
noteFavoritesCount: Nombre de notes afegides a favorits
|
noteFavoritesCount: Nombre de notes afegides a favorits
|
||||||
useSystemFont: Fes servir la font per defecte del sistema
|
useSystemFont: Fes servir la font per defecte del sistema
|
||||||
contact: Contacte
|
contact: Contacte
|
||||||
clips: Clips
|
clips: Retalls
|
||||||
experimentalFeatures: Característiques experimentals
|
experimentalFeatures: Característiques experimentals
|
||||||
developer: Desenvolupador
|
developer: Desenvolupador
|
||||||
makeExplorableDescription: Si desactives aquesta funció el teu compte no sortirà a
|
makeExplorableDescription: Si desactives aquesta funció el teu compte no sortirà a
|
||||||
|
@ -1496,7 +1496,7 @@ gallery: Galeria
|
||||||
popularPosts: Pàgines populars
|
popularPosts: Pàgines populars
|
||||||
shareWithNote: Comparteix amb una publicació
|
shareWithNote: Comparteix amb una publicació
|
||||||
expiration: Data límit
|
expiration: Data límit
|
||||||
memo: Memo
|
memo: Recordatori
|
||||||
priority: Prioritat
|
priority: Prioritat
|
||||||
high: Alta
|
high: Alta
|
||||||
middle: Mitjana
|
middle: Mitjana
|
||||||
|
@ -1537,7 +1537,7 @@ incorrectPassword: Contrasenya incorrecta.
|
||||||
clickToFinishEmailVerification: Feu clic a [{ok}] per completar la verificació del
|
clickToFinishEmailVerification: Feu clic a [{ok}] per completar la verificació del
|
||||||
correu electrònic.
|
correu electrònic.
|
||||||
overridedDeviceKind: Tipus de dispositiu
|
overridedDeviceKind: Tipus de dispositiu
|
||||||
smartphone: Smartphone
|
smartphone: Telèfon intel·ligent
|
||||||
tablet: Tauleta
|
tablet: Tauleta
|
||||||
auto: Automàtic
|
auto: Automàtic
|
||||||
recentNHours: Últimes {n} hores
|
recentNHours: Últimes {n} hores
|
||||||
|
@ -1625,7 +1625,7 @@ customKaTeXMacroDescription: "Configura macros per escriure expressions matemàt
|
||||||
objectStorageRegion: Regió
|
objectStorageRegion: Regió
|
||||||
objectStoragePrefix: Prefix
|
objectStoragePrefix: Prefix
|
||||||
objectStoragePrefixDesc: Els fitxers es guardaran dins de carpetes amb aquest prefix.
|
objectStoragePrefixDesc: Els fitxers es guardaran dins de carpetes amb aquest prefix.
|
||||||
objectStorageEndpoint: Endpoint
|
objectStorageEndpoint: Extrem
|
||||||
newNoteRecived: Hi han notes noves
|
newNoteRecived: Hi han notes noves
|
||||||
sounds: Sons
|
sounds: Sons
|
||||||
listen: Escoltar
|
listen: Escoltar
|
||||||
|
@ -1704,7 +1704,9 @@ oneWeek: Una setmana
|
||||||
reflectMayTakeTime: Pot trigar una mica a reflectir-se.
|
reflectMayTakeTime: Pot trigar una mica a reflectir-se.
|
||||||
thereIsUnresolvedAbuseReportWarning: Hi ha informes sense resoldre.
|
thereIsUnresolvedAbuseReportWarning: Hi ha informes sense resoldre.
|
||||||
driveCapOverrideLabel: Canvieu la capacitat del disc per a aquest usuari
|
driveCapOverrideLabel: Canvieu la capacitat del disc per a aquest usuari
|
||||||
isSystemAccount: Un compte creat i operat automàticament pel sistema.
|
isSystemAccount: Aquest compte és creat i operat automàticament pel sistema. Si us
|
||||||
|
plau, no modereu, editeu, suprimiu o modifiqueu aquest compte de cap forma, o podria
|
||||||
|
trencar el vostre servidor.
|
||||||
typeToConfirm: Introduïu {x} per confirmar
|
typeToConfirm: Introduïu {x} per confirmar
|
||||||
deleteAccount: Suprimeix el compte
|
deleteAccount: Suprimeix el compte
|
||||||
document: Documentació
|
document: Documentació
|
||||||
|
@ -1746,7 +1748,7 @@ reverse: Revés
|
||||||
objectStorageBucket: Cubell
|
objectStorageBucket: Cubell
|
||||||
objectStorageBucketDesc: Si us plau específica el nom del cubell que faràs servir
|
objectStorageBucketDesc: Si us plau específica el nom del cubell que faràs servir
|
||||||
al teu proveïdor.
|
al teu proveïdor.
|
||||||
clip: Clip
|
clip: Retall
|
||||||
createNew: Crear una nova
|
createNew: Crear una nova
|
||||||
optional: Opcional
|
optional: Opcional
|
||||||
jumpToSpecifiedDate: Vés a una data concreta
|
jumpToSpecifiedDate: Vés a una data concreta
|
||||||
|
@ -2056,3 +2058,5 @@ newer: Més nou
|
||||||
older: Més antic
|
older: Més antic
|
||||||
silencedWarning: S'està mostrant aquesta pàgina per què aquest usuari és d'un servidor
|
silencedWarning: S'està mostrant aquesta pàgina per què aquest usuari és d'un servidor
|
||||||
que l'administrador a silenciat, així que pot ser spam.
|
que l'administrador a silenciat, així que pot ser spam.
|
||||||
|
jumpToPrevious: Vés a l'anterior
|
||||||
|
cw: Avís de contingut
|
||||||
|
|
|
@ -1171,6 +1171,8 @@ _mfm:
|
||||||
sparkleDescription: "Verleiht Inhalt einen glitzernden Partikeleffekt."
|
sparkleDescription: "Verleiht Inhalt einen glitzernden Partikeleffekt."
|
||||||
rotate: "Drehen"
|
rotate: "Drehen"
|
||||||
rotateDescription: "Dreht den Inhalt um einen angegebenen Winkel."
|
rotateDescription: "Dreht den Inhalt um einen angegebenen Winkel."
|
||||||
|
fade: "Ein-/Ausblenden"
|
||||||
|
fadeDescription: "Blended Inhalt ein and aus."
|
||||||
plain: "Schlicht"
|
plain: "Schlicht"
|
||||||
plainDescription: "Deaktiviert jegliche MFM-Syntax, die sich innerhalb dieses MFM-Effekts\
|
plainDescription: "Deaktiviert jegliche MFM-Syntax, die sich innerhalb dieses MFM-Effekts\
|
||||||
\ befindet."
|
\ befindet."
|
||||||
|
|
|
@ -57,7 +57,7 @@ sendMessage: "Send a message"
|
||||||
copyUsername: "Copy username"
|
copyUsername: "Copy username"
|
||||||
searchUser: "Search for a user"
|
searchUser: "Search for a user"
|
||||||
reply: "Reply"
|
reply: "Reply"
|
||||||
jumpToReply: "Jump to Reply"
|
jumpToPrevious: "Jump to previous"
|
||||||
loadMore: "Load more"
|
loadMore: "Load more"
|
||||||
showMore: "Show more"
|
showMore: "Show more"
|
||||||
newer: "newer"
|
newer: "newer"
|
||||||
|
@ -69,6 +69,7 @@ followRequestAccepted: "Follow request accepted"
|
||||||
mention: "Mention"
|
mention: "Mention"
|
||||||
mentions: "Mentions"
|
mentions: "Mentions"
|
||||||
directNotes: "Direct messages"
|
directNotes: "Direct messages"
|
||||||
|
cw: "Content warning"
|
||||||
importAndExport: "Import/Export Data"
|
importAndExport: "Import/Export Data"
|
||||||
import: "Import"
|
import: "Import"
|
||||||
export: "Export"
|
export: "Export"
|
||||||
|
@ -971,7 +972,7 @@ driveCapOverrideLabel: "Change the drive capacity for this user"
|
||||||
driveCapOverrideCaption: "Reset the capacity to default by inputting a value of 0\
|
driveCapOverrideCaption: "Reset the capacity to default by inputting a value of 0\
|
||||||
\ or lower."
|
\ or lower."
|
||||||
requireAdminForView: "You must log in with an administrator account to view this."
|
requireAdminForView: "You must log in with an administrator account to view this."
|
||||||
isSystemAccount: "An account created and automatically operated by the system."
|
isSystemAccount: "This account is created and automatically operated by the system. Please do not moderate, edit, delete, or otherwise tamper with this account, or it may break your server."
|
||||||
typeToConfirm: "Please enter {x} to confirm"
|
typeToConfirm: "Please enter {x} to confirm"
|
||||||
deleteAccount: "Delete account"
|
deleteAccount: "Delete account"
|
||||||
document: "Documentation"
|
document: "Documentation"
|
||||||
|
@ -1266,6 +1267,8 @@ _mfm:
|
||||||
sparkleDescription: "Gives content a sparkling particle effect."
|
sparkleDescription: "Gives content a sparkling particle effect."
|
||||||
rotate: "Rotate"
|
rotate: "Rotate"
|
||||||
rotateDescription: "Turns content by a specified angle."
|
rotateDescription: "Turns content by a specified angle."
|
||||||
|
fade: "Fade"
|
||||||
|
fadeDescription: "Fades content in and out."
|
||||||
position: "Position"
|
position: "Position"
|
||||||
positionDescription: "Move content by a specified amount."
|
positionDescription: "Move content by a specified amount."
|
||||||
scale: "Scale"
|
scale: "Scale"
|
||||||
|
|
|
@ -1077,6 +1077,8 @@ _mfm:
|
||||||
sparkle: "Paillettes"
|
sparkle: "Paillettes"
|
||||||
sparkleDescription: "Ajoute un effet scintillant au contenu."
|
sparkleDescription: "Ajoute un effet scintillant au contenu."
|
||||||
rotate: "Pivoter"
|
rotate: "Pivoter"
|
||||||
|
fade: "Apparaître/Disparaître"
|
||||||
|
fadeDescription: "Fait apparaître et disparaître le contenu."
|
||||||
plainDescription: Désactiver les effets de tous les MFM contenus dans cet effet
|
plainDescription: Désactiver les effets de tous les MFM contenus dans cet effet
|
||||||
MFM.
|
MFM.
|
||||||
rotateDescription: Pivoter le contenu d'un angle spécifique.
|
rotateDescription: Pivoter le contenu d'un angle spécifique.
|
||||||
|
|
|
@ -910,6 +910,8 @@ _mfm:
|
||||||
fontDescription: "Puoi scegliere il tipo di carattere per il contenuto."
|
fontDescription: "Puoi scegliere il tipo di carattere per il contenuto."
|
||||||
rainbow: "Arcobaleno"
|
rainbow: "Arcobaleno"
|
||||||
rotate: "Ruota"
|
rotate: "Ruota"
|
||||||
|
fade: "Dissolvenza"
|
||||||
|
fadeDescription: "Dissolvenza in entrata e in uscita del contenuto."
|
||||||
_instanceTicker:
|
_instanceTicker:
|
||||||
none: "Nascondi"
|
none: "Nascondi"
|
||||||
remote: "Mostra solo per gli/le utenti remotə"
|
remote: "Mostra solo per gli/le utenti remotə"
|
||||||
|
|
|
@ -13,7 +13,7 @@ password: "Wachtwoord"
|
||||||
forgotPassword: "Wachtwoord vergeten"
|
forgotPassword: "Wachtwoord vergeten"
|
||||||
fetchingAsApObject: "Ophalen vanuit de Fediverse"
|
fetchingAsApObject: "Ophalen vanuit de Fediverse"
|
||||||
ok: "Ok"
|
ok: "Ok"
|
||||||
gotIt: "Begrepen"
|
gotIt: "Begrepen!"
|
||||||
cancel: "Annuleren"
|
cancel: "Annuleren"
|
||||||
enterUsername: "Voer een gebruikersnaam in"
|
enterUsername: "Voer een gebruikersnaam in"
|
||||||
renotedBy: "Hergedeeld door {user}"
|
renotedBy: "Hergedeeld door {user}"
|
||||||
|
@ -47,12 +47,12 @@ copyContent: "Kopiëren inhoud"
|
||||||
copyLink: "Kopiëren link"
|
copyLink: "Kopiëren link"
|
||||||
delete: "Verwijderen"
|
delete: "Verwijderen"
|
||||||
deleteAndEdit: "Verwijderen en bewerken"
|
deleteAndEdit: "Verwijderen en bewerken"
|
||||||
deleteAndEditConfirm: "Weet je zeker dat je deze notitie wilt verwijderen en dan bewerken?
|
deleteAndEditConfirm: "Weet je zeker dat je deze post wilt verwijderen en dan bewerken?
|
||||||
Je verliest alle reacties, herdelingen en antwoorden erop."
|
Je verliest alle reacties, boosts en antwoorden erop."
|
||||||
addToList: "Aan lijst toevoegen"
|
addToList: "Aan lijst toevoegen"
|
||||||
sendMessage: "Verstuur bericht"
|
sendMessage: "Verstuur bericht"
|
||||||
copyUsername: "Kopiëren gebruikersnaam "
|
copyUsername: "Gebruikersnaam kopiëren"
|
||||||
searchUser: "Zoeken een gebruiker"
|
searchUser: "Zoek een gebruiker"
|
||||||
reply: "Antwoord"
|
reply: "Antwoord"
|
||||||
loadMore: "Laad meer"
|
loadMore: "Laad meer"
|
||||||
showMore: "Toon meer"
|
showMore: "Toon meer"
|
||||||
|
@ -68,7 +68,7 @@ export: "Export"
|
||||||
files: "Bestanden"
|
files: "Bestanden"
|
||||||
download: "Downloaden"
|
download: "Downloaden"
|
||||||
driveFileDeleteConfirm: "Weet je zeker dat je het bestand \"{name}\" wilt verwijderen?
|
driveFileDeleteConfirm: "Weet je zeker dat je het bestand \"{name}\" wilt verwijderen?
|
||||||
Notities met dit bestand als bijlage worden ook verwijderd."
|
Posts met dit bestand als bijlage worden ook verwijderd."
|
||||||
unfollowConfirm: "Weet je zeker dat je {name} wilt ontvolgen?"
|
unfollowConfirm: "Weet je zeker dat je {name} wilt ontvolgen?"
|
||||||
exportRequested: "Je hebt een export aangevraagd. Dit kan een tijdje duren. Het wordt
|
exportRequested: "Je hebt een export aangevraagd. Dit kan een tijdje duren. Het wordt
|
||||||
toegevoegd aan je Drive zodra het is voltooid."
|
toegevoegd aan je Drive zodra het is voltooid."
|
||||||
|
@ -101,13 +101,13 @@ followRequests: "Volgverzoeken"
|
||||||
unfollow: "Ontvolgen"
|
unfollow: "Ontvolgen"
|
||||||
followRequestPending: "Wachten op goedkeuring volgverzoek"
|
followRequestPending: "Wachten op goedkeuring volgverzoek"
|
||||||
enterEmoji: "Voer een emoji in"
|
enterEmoji: "Voer een emoji in"
|
||||||
renote: "Herdelen"
|
renote: "Boost"
|
||||||
unrenote: "Stop herdelen"
|
unrenote: "Stop herdelen"
|
||||||
renoted: "Herdeeld"
|
renoted: "Boosted."
|
||||||
cantRenote: "Dit bericht kan niet worden herdeeld"
|
cantRenote: "Dit bericht kan niet worden geboost."
|
||||||
cantReRenote: "Een herdeling kan niet worden herdeeld"
|
cantReRenote: "Een boost kan niet worden geboost."
|
||||||
quote: "Quote"
|
quote: "Quote"
|
||||||
pinnedNote: "Vastgemaakte notitie"
|
pinnedNote: "Vastgemaakte post"
|
||||||
pinned: "Vastmaken aan profielpagina"
|
pinned: "Vastmaken aan profielpagina"
|
||||||
you: "Jij"
|
you: "Jij"
|
||||||
clickToShow: "Klik om te bekijken"
|
clickToShow: "Klik om te bekijken"
|
||||||
|
@ -116,7 +116,7 @@ add: "Toevoegen"
|
||||||
reaction: "Reacties"
|
reaction: "Reacties"
|
||||||
reactionSettingDescription2: "Sleep om opnieuw te ordenen, Klik om te verwijderen,
|
reactionSettingDescription2: "Sleep om opnieuw te ordenen, Klik om te verwijderen,
|
||||||
Druk op \"+\" om toe te voegen"
|
Druk op \"+\" om toe te voegen"
|
||||||
rememberNoteVisibility: "Vergeet niet de notitie zichtbaarheidsinstellingen"
|
rememberNoteVisibility: "Onthoud post zichtbaarheidsinstellingen"
|
||||||
attachCancel: "Verwijder bijlage"
|
attachCancel: "Verwijder bijlage"
|
||||||
markAsSensitive: "Markeren als NSFW"
|
markAsSensitive: "Markeren als NSFW"
|
||||||
unmarkAsSensitive: "Geen NSFW"
|
unmarkAsSensitive: "Geen NSFW"
|
||||||
|
@ -139,8 +139,8 @@ flagAsCat: "Markeer dit account als een kat."
|
||||||
flagAsCatDescription: "Zet deze vlag aan als je wilt aangeven dat dit account een
|
flagAsCatDescription: "Zet deze vlag aan als je wilt aangeven dat dit account een
|
||||||
kat is."
|
kat is."
|
||||||
flagShowTimelineReplies: "Toon antwoorden op de tijdlijn"
|
flagShowTimelineReplies: "Toon antwoorden op de tijdlijn"
|
||||||
flagShowTimelineRepliesDescription: "Als je dit vlag aanzet, toont de tijdlijn ook
|
flagShowTimelineRepliesDescription: "Als je deze vlag aanzet, toont de tijdlijn ook
|
||||||
antwoorden op andere en niet alleen jouw eigen notities."
|
antwoorden op andere en niet alleen jouw eigen post."
|
||||||
autoAcceptFollowed: "Accepteer verzoeken om jezelf te volgen vanzelf als je de verzoeker
|
autoAcceptFollowed: "Accepteer verzoeken om jezelf te volgen vanzelf als je de verzoeker
|
||||||
al volgt"
|
al volgt"
|
||||||
addAccount: "Account toevoegen"
|
addAccount: "Account toevoegen"
|
||||||
|
@ -203,8 +203,8 @@ mutedUsers: "Gedempte gebruikers"
|
||||||
blockedUsers: "Geblokkeerde gebruikers"
|
blockedUsers: "Geblokkeerde gebruikers"
|
||||||
noUsers: "Er zijn geen gebruikers."
|
noUsers: "Er zijn geen gebruikers."
|
||||||
editProfile: "Bewerk Profiel"
|
editProfile: "Bewerk Profiel"
|
||||||
noteDeleteConfirm: "Ben je zeker dat je dit bericht wil verwijderen?"
|
noteDeleteConfirm: "Ben je zeker dat je deze post wil verwijderen?"
|
||||||
pinLimitExceeded: "Je kunt geen berichten meer vastprikken"
|
pinLimitExceeded: "Je kunt geen posts meer vastprikken"
|
||||||
intro: "Installatie van Calckey geëindigd! Maak nu een beheerder aan."
|
intro: "Installatie van Calckey geëindigd! Maak nu een beheerder aan."
|
||||||
done: "Klaar"
|
done: "Klaar"
|
||||||
processing: "Bezig met verwerken"
|
processing: "Bezig met verwerken"
|
||||||
|
@ -499,3 +499,23 @@ manageGroups: Beheer groepen
|
||||||
subscribePushNotification: Pushmeldingen inschakelen
|
subscribePushNotification: Pushmeldingen inschakelen
|
||||||
unsubscribePushNotification: Pushmeldingen uitschakelen
|
unsubscribePushNotification: Pushmeldingen uitschakelen
|
||||||
pushNotificationAlreadySubscribed: Pushmeldingen zijn al ingeschakeld
|
pushNotificationAlreadySubscribed: Pushmeldingen zijn al ingeschakeld
|
||||||
|
antennaSource: Antenne bron
|
||||||
|
antennaKeywords: Trefwoorden om naar te luisteren
|
||||||
|
antennaExcludeKeywords: Trefwoorden om te negeren
|
||||||
|
driveCapacityPerRemoteAccount: Schijfruimte per externe gebruiker
|
||||||
|
backgroundImageUrl: Achtergrondafbeelding URL
|
||||||
|
basicInfo: Basis informatie
|
||||||
|
pinnedUsers: Vastgezette gebruikers
|
||||||
|
pinnedPages: Vastgezette Pagina's
|
||||||
|
driveCapacityPerLocalAccount: Schijfruimte per lokale gebruiker
|
||||||
|
iconUrl: Icoon URL
|
||||||
|
bannerUrl: Banner afbeelding URL
|
||||||
|
manageAntennas: Beheer Antennes
|
||||||
|
name: Naam
|
||||||
|
notifyAntenna: Meld nieuwe posts
|
||||||
|
withFileAntenna: Alleen posts met bestanden
|
||||||
|
enableServiceworker: Schakel pushmeldingen voor je browser in
|
||||||
|
renoteUnmute: Ontdemp boosts
|
||||||
|
jumpToPrevious: Spring naar vorige
|
||||||
|
caseSensitive: Hoofdlettergevoelig
|
||||||
|
cw: Inhoudswaarschuwing
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "calckey",
|
"name": "calckey",
|
||||||
"version": "14.0.0-dev14",
|
"version": "14.0.0-dev18",
|
||||||
"codename": "aqua",
|
"codename": "aqua",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://codeberg.org/calckey/calckey.git"
|
"url": "https://codeberg.org/calckey/calckey.git"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@8.5.0",
|
"packageManager": "pnpm@8.5.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"rebuild": "pnpm run clean && pnpm -r run build && pnpm run gulp",
|
"rebuild": "pnpm run clean && pnpm -r run build && pnpm run gulp",
|
||||||
|
|
|
@ -85,7 +85,7 @@
|
||||||
"koa-send": "5.0.1",
|
"koa-send": "5.0.1",
|
||||||
"koa-slow": "2.1.0",
|
"koa-slow": "2.1.0",
|
||||||
"koa-views": "7.0.2",
|
"koa-views": "7.0.2",
|
||||||
"mfm-js": "0.23.2",
|
"mfm-js": "0.23.3",
|
||||||
"mime-types": "2.1.35",
|
"mime-types": "2.1.35",
|
||||||
"multer": "1.4.4-lts.1",
|
"multer": "1.4.4-lts.1",
|
||||||
"native-utils": "link:native-utils",
|
"native-utils": "link:native-utils",
|
||||||
|
|
|
@ -9,6 +9,9 @@ export function nyaize(text: string): string {
|
||||||
.replace(/(?<=n)a/gi, (x) => (x === "A" ? "YA" : "ya"))
|
.replace(/(?<=n)a/gi, (x) => (x === "A" ? "YA" : "ya"))
|
||||||
.replace(/(?<=morn)ing/gi, (x) => (x === "ING" ? "YAN" : "yan"))
|
.replace(/(?<=morn)ing/gi, (x) => (x === "ING" ? "YAN" : "yan"))
|
||||||
.replace(/(?<=every)one/gi, (x) => (x === "ONE" ? "NYAN" : "nyan"))
|
.replace(/(?<=every)one/gi, (x) => (x === "ONE" ? "NYAN" : "nyan"))
|
||||||
|
.replace(/non(?=[bcdfghjklmnpqrstvwxyz])/gi, (x) =>
|
||||||
|
x === "NON" ? "NYAN" : "nyan",
|
||||||
|
)
|
||||||
// ko-KR
|
// ko-KR
|
||||||
.replace(/[나-낳]/g, (match) =>
|
.replace(/[나-낳]/g, (match) =>
|
||||||
String.fromCharCode(
|
String.fromCharCode(
|
||||||
|
|
|
@ -38,6 +38,7 @@ export const paramDef = {
|
||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
noteId: { type: "string", format: "misskey:id" },
|
noteId: { type: "string", format: "misskey:id" },
|
||||||
|
userId: { type: "string", format: "misskey:id" },
|
||||||
limit: { type: "integer", minimum: 1, maximum: 100, default: 10 },
|
limit: { type: "integer", minimum: 1, maximum: 100, default: 10 },
|
||||||
sinceId: { type: "string", format: "misskey:id" },
|
sinceId: { type: "string", format: "misskey:id" },
|
||||||
untilId: { type: "string", format: "misskey:id" },
|
untilId: { type: "string", format: "misskey:id" },
|
||||||
|
@ -52,13 +53,19 @@ export default define(meta, paramDef, async (ps, user) => {
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
|
|
||||||
const query = makePaginationQuery(
|
let query = makePaginationQuery(
|
||||||
Notes.createQueryBuilder("note"),
|
Notes.createQueryBuilder("note"),
|
||||||
ps.sinceId,
|
ps.sinceId,
|
||||||
ps.untilId,
|
ps.untilId,
|
||||||
)
|
)
|
||||||
.andWhere("note.renoteId = :renoteId", { renoteId: note.id })
|
.andWhere("note.renoteId = :renoteId", { renoteId: note.id })
|
||||||
.innerJoinAndSelect("note.user", "user")
|
.innerJoinAndSelect("note.user", "user");
|
||||||
|
|
||||||
|
if (ps.userId) {
|
||||||
|
query.andWhere("user.id = :userId", { userId: ps.userId });
|
||||||
|
}
|
||||||
|
|
||||||
|
query
|
||||||
.leftJoinAndSelect("user.avatar", "avatar")
|
.leftJoinAndSelect("user.avatar", "avatar")
|
||||||
.leftJoinAndSelect("user.banner", "banner")
|
.leftJoinAndSelect("user.banner", "banner")
|
||||||
.leftJoinAndSelect("note.reply", "reply")
|
.leftJoinAndSelect("note.reply", "reply")
|
||||||
|
|
|
@ -7,6 +7,7 @@ import * as fs from "node:fs";
|
||||||
import * as http from "node:http";
|
import * as http from "node:http";
|
||||||
import Koa from "koa";
|
import Koa from "koa";
|
||||||
import Router from "@koa/router";
|
import Router from "@koa/router";
|
||||||
|
import cors from "@koa/cors";
|
||||||
import mount from "koa-mount";
|
import mount from "koa-mount";
|
||||||
import koaLogger from "koa-logger";
|
import koaLogger from "koa-logger";
|
||||||
import * as slow from "koa-slow";
|
import * as slow from "koa-slow";
|
||||||
|
@ -41,6 +42,12 @@ app.proxy = true;
|
||||||
|
|
||||||
app.use(removeTrailingSlash());
|
app.use(removeTrailingSlash());
|
||||||
|
|
||||||
|
app.use(
|
||||||
|
cors({
|
||||||
|
origin: "*",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
if (!["production", "test"].includes(process.env.NODE_ENV || "")) {
|
if (!["production", "test"].includes(process.env.NODE_ENV || "")) {
|
||||||
// Logger
|
// Logger
|
||||||
app.use(
|
app.use(
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
"start-server-and-test": "1.15.2",
|
"start-server-and-test": "1.15.2",
|
||||||
"strict-event-emitter-types": "2.0.0",
|
"strict-event-emitter-types": "2.0.0",
|
||||||
"stringz": "2.1.0",
|
"stringz": "2.1.0",
|
||||||
"swiper": "^8.4.5",
|
"swiper": "9.3.2",
|
||||||
"syuilo-password-strength": "0.0.1",
|
"syuilo-password-strength": "0.0.1",
|
||||||
"textarea-caret": "3.1.0",
|
"textarea-caret": "3.1.0",
|
||||||
"three": "0.146.0",
|
"three": "0.146.0",
|
||||||
|
|
|
@ -111,11 +111,12 @@ function onMousedown(evt: MouseEvent): void {
|
||||||
z-index: 1; // 他コンポーネントのbox-shadowに隠されないようにするため
|
z-index: 1; // 他コンポーネントのbox-shadowに隠されないようにするため
|
||||||
display: block;
|
display: block;
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
|
min-height: 35px;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-size: 1em;
|
font-size: max(12px, 1em);
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
background: var(--buttonBg);
|
background: var(--buttonBg);
|
||||||
|
@ -193,7 +194,7 @@ function onMousedown(evt: MouseEvent): void {
|
||||||
|
|
||||||
&.mini {
|
&.mini {
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
font-size: 0.9em;
|
font-size: max(12px, 0.9em);
|
||||||
border-radius: 100px;
|
border-radius: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
class="kpoogebi _button"
|
v-if="$i != null && $i.id != user.id"
|
||||||
|
class="kpoogebi _button follow-button"
|
||||||
:class="{
|
:class="{
|
||||||
wait,
|
wait,
|
||||||
active: isFollowing || hasPendingFollowRequestFromYou,
|
active: isFollowing || hasPendingFollowRequestFromYou,
|
||||||
|
@ -10,40 +11,43 @@
|
||||||
}"
|
}"
|
||||||
:disabled="wait"
|
:disabled="wait"
|
||||||
@click="onClick"
|
@click="onClick"
|
||||||
|
:aria-label="`${state} ${user.name || user.username}`"
|
||||||
>
|
>
|
||||||
<template v-if="!wait">
|
<template v-if="!wait">
|
||||||
<template v-if="isBlocking">
|
<template v-if="isBlocking">
|
||||||
<span v-if="full">{{ i18n.ts.blocked }}</span
|
<span v-if="full">{{ (state = i18n.ts.blocked) }}</span
|
||||||
><i class="ph-prohibit ph-bold ph-lg"></i>
|
><i class="ph-prohibit ph-bold ph-lg"></i>
|
||||||
</template>
|
</template>
|
||||||
<template
|
<template
|
||||||
v-else-if="hasPendingFollowRequestFromYou && user.isLocked"
|
v-else-if="hasPendingFollowRequestFromYou && user.isLocked"
|
||||||
>
|
>
|
||||||
<span v-if="full">{{ i18n.ts.followRequestPending }}</span
|
<span v-if="full">{{
|
||||||
|
(state = i18n.ts.followRequestPending)
|
||||||
|
}}</span
|
||||||
><i class="ph-hourglass-medium ph-bold ph-lg"></i>
|
><i class="ph-hourglass-medium ph-bold ph-lg"></i>
|
||||||
</template>
|
</template>
|
||||||
<template
|
<template
|
||||||
v-else-if="hasPendingFollowRequestFromYou && !user.isLocked"
|
v-else-if="hasPendingFollowRequestFromYou && !user.isLocked"
|
||||||
>
|
>
|
||||||
<!-- つまりリモートフォローの場合。 -->
|
<!-- つまりリモートフォローの場合。 -->
|
||||||
<span v-if="full">{{ i18n.ts.processing }}</span
|
<span v-if="full">{{ (state = i18n.ts.processing) }}</span
|
||||||
><i class="ph-circle-notch ph-bold ph-lg fa-pulse"></i>
|
><i class="ph-circle-notch ph-bold ph-lg fa-pulse"></i>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="isFollowing">
|
<template v-else-if="isFollowing">
|
||||||
<span v-if="full">{{ i18n.ts.unfollow }}</span
|
<span v-if="full">{{ (state = i18n.ts.unfollow) }}</span
|
||||||
><i class="ph-minus ph-bold ph-lg"></i>
|
><i class="ph-minus ph-bold ph-lg"></i>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="!isFollowing && user.isLocked">
|
<template v-else-if="!isFollowing && user.isLocked">
|
||||||
<span v-if="full">{{ i18n.ts.followRequest }}</span
|
<span v-if="full">{{ (state = i18n.ts.followRequest) }}</span
|
||||||
><i class="ph-plus ph-bold ph-lg"></i>
|
><i class="ph-plus ph-bold ph-lg"></i>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="!isFollowing && !user.isLocked">
|
<template v-else-if="!isFollowing && !user.isLocked">
|
||||||
<span v-if="full">{{ i18n.ts.follow }}</span
|
<span v-if="full">{{ (state = i18n.ts.follow) }}</span
|
||||||
><i class="ph-plus ph-bold ph-lg"></i>
|
><i class="ph-plus ph-bold ph-lg"></i>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<span v-if="full">{{ i18n.ts.processing }}</span
|
<span v-if="full">{{ (state = i18n.ts.processing) }}</span
|
||||||
><i class="ph-circle-notch ph-bold ph-lg fa-pulse ph-fw ph-lg"></i>
|
><i class="ph-circle-notch ph-bold ph-lg fa-pulse ph-fw ph-lg"></i>
|
||||||
</template>
|
</template>
|
||||||
</button>
|
</button>
|
||||||
|
@ -55,6 +59,7 @@ import type * as Misskey from "calckey-js";
|
||||||
import * as os from "@/os";
|
import * as os from "@/os";
|
||||||
import { stream } from "@/stream";
|
import { stream } from "@/stream";
|
||||||
import { i18n } from "@/i18n";
|
import { i18n } from "@/i18n";
|
||||||
|
import { $i } from "@/account";
|
||||||
|
|
||||||
const emit = defineEmits(["refresh"]);
|
const emit = defineEmits(["refresh"]);
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
|
@ -71,6 +76,8 @@ const props = withDefaults(
|
||||||
|
|
||||||
const isBlocking = computed(() => props.user.isBlocking);
|
const isBlocking = computed(() => props.user.isBlocking);
|
||||||
|
|
||||||
|
let state = $ref(i18n.ts.processing);
|
||||||
|
|
||||||
let isFollowing = $ref(props.user.isFollowing);
|
let isFollowing = $ref(props.user.isFollowing);
|
||||||
let hasPendingFollowRequestFromYou = $ref(
|
let hasPendingFollowRequestFromYou = $ref(
|
||||||
props.user.hasPendingFollowRequestFromYou
|
props.user.hasPendingFollowRequestFromYou
|
||||||
|
@ -155,7 +162,7 @@ onBeforeUnmount(() => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.kpoogebi {
|
.follow-button {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -164,13 +171,15 @@ onBeforeUnmount(() => {
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
border: solid 1px var(--accent);
|
border: solid 1px var(--accent);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
height: 31px;
|
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
border-radius: 32px;
|
width: 2em;
|
||||||
|
height: 2em;
|
||||||
|
border-radius: 100px;
|
||||||
background: var(--bg);
|
background: var(--bg);
|
||||||
|
|
||||||
&.full {
|
&.full {
|
||||||
padding: 0 8px 0 12px;
|
padding: 0.2em 0.7em;
|
||||||
|
width: auto;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +216,7 @@ onBeforeUnmount(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
color: #fff;
|
color: var(--fgOnAccent);
|
||||||
background: var(--accent);
|
background: var(--accent);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
|
:aria-label="accessibleLabel"
|
||||||
v-if="!muted.muted"
|
v-if="!muted.muted"
|
||||||
v-show="!isDeleted"
|
v-show="!isDeleted"
|
||||||
ref="el"
|
ref="el"
|
||||||
|
@ -85,6 +86,7 @@
|
||||||
:parentId="appearNote.parentId"
|
:parentId="appearNote.parentId"
|
||||||
@push="(e) => router.push(notePage(e))"
|
@push="(e) => router.push(notePage(e))"
|
||||||
@focusfooter="footerEl.focus()"
|
@focusfooter="footerEl.focus()"
|
||||||
|
@expanded="(e) => setPostExpanded(e)"
|
||||||
></MkSubNoteContent>
|
></MkSubNoteContent>
|
||||||
<div v-if="translating || translation" class="translation">
|
<div v-if="translating || translation" class="translation">
|
||||||
<MkLoading v-if="translating" mini />
|
<MkLoading v-if="translating" mini />
|
||||||
|
@ -472,6 +474,39 @@ function readPromo() {
|
||||||
isDeleted.value = true;
|
isDeleted.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let postIsExpanded = ref(false);
|
||||||
|
|
||||||
|
function setPostExpanded(val: boolean) {
|
||||||
|
postIsExpanded.value = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
const accessibleLabel = computed(() => {
|
||||||
|
let label = `${props.note.user.username}; `;
|
||||||
|
if (props.note.renote) {
|
||||||
|
label += `${i18n.t("renoted")} ${props.note.renote.user.username}; `;
|
||||||
|
if (props.note.renote.cw) {
|
||||||
|
label += `${i18n.t("cw")}: ${props.note.renote.cw}; `;
|
||||||
|
if (postIsExpanded.value) {
|
||||||
|
label += `${props.note.renote.text}; `;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
label += `${props.note.renote.text}; `;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (props.note.cw) {
|
||||||
|
label += `${i18n.t("cw")}: ${props.note.cw}; `;
|
||||||
|
if (postIsExpanded.value) {
|
||||||
|
label += `${props.note.text}; `;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
label += `${props.note.text}; `;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const date = new Date(props.note.createdAt);
|
||||||
|
label += `${date.toLocaleTimeString()}`;
|
||||||
|
return label;
|
||||||
|
});
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
focus,
|
focus,
|
||||||
blur,
|
blur,
|
||||||
|
|
|
@ -35,38 +35,30 @@
|
||||||
|
|
||||||
<MkTab v-model="tab" :style="'underline'" @update:modelValue="loadTab">
|
<MkTab v-model="tab" :style="'underline'" @update:modelValue="loadTab">
|
||||||
<option value="replies">
|
<option value="replies">
|
||||||
<i class="ph-arrow-u-up-left ph-bold ph-lg"></i>
|
<!-- <i class="ph-arrow-u-up-left ph-bold ph-lg"></i> -->
|
||||||
<template v-if="appearNote.repliesCount > 0">
|
<span v-if="appearNote.repliesCount > 0" class="count">{{
|
||||||
<span class="count">{{ appearNote.repliesCount }}</span>
|
appearNote.repliesCount
|
||||||
</template>
|
}}</span>
|
||||||
{{ i18n.ts._notification._types.reply }}
|
{{ i18n.ts._notification._types.reply }}
|
||||||
</option>
|
</option>
|
||||||
<option value="renotes">
|
<option value="renotes" v-if="appearNote.renoteCount > 0">
|
||||||
<i class="ph-repeat ph-bold ph-lg"></i>
|
<!-- <i class="ph-repeat ph-bold ph-lg"></i> -->
|
||||||
<template v-if="appearNote.renoteCount > 0">
|
|
||||||
<span class="count">{{ appearNote.renoteCount }}</span>
|
<span class="count">{{ appearNote.renoteCount }}</span>
|
||||||
</template>
|
|
||||||
{{ i18n.ts._notification._types.renote }}
|
{{ i18n.ts._notification._types.renote }}
|
||||||
</option>
|
</option>
|
||||||
<option value="quotes">
|
<option value="reactions" v-if="reactionsCount > 0">
|
||||||
<i class="ph-quotes ph-bold ph-lg"></i>
|
<!-- <i class="ph-smiley ph-bold ph-lg"></i> -->
|
||||||
<template v-if="directQuotes?.length > 0">
|
|
||||||
<span class="count">{{ directQuotes.length }}</span>
|
|
||||||
</template>
|
|
||||||
{{ i18n.ts._notification._types.quote }}
|
|
||||||
</option>
|
|
||||||
<option value="reactions">
|
|
||||||
<i class="ph-smiley ph-bold ph-lg"></i>
|
|
||||||
<template v-if="reactionsCount > 0">
|
|
||||||
<span class="count">{{ reactionsCount }}</span>
|
<span class="count">{{ reactionsCount }}</span>
|
||||||
</template>
|
|
||||||
{{ i18n.ts.reaction }}
|
{{ i18n.ts.reaction }}
|
||||||
</option>
|
</option>
|
||||||
<option value="clips">
|
<option value="quotes" v-if="directQuotes?.length > 0">
|
||||||
<i class="ph-paperclip ph-bold ph-lg"></i>
|
<!-- <i class="ph-quotes ph-bold ph-lg"></i> -->
|
||||||
<template v-if="clips?.length > 0">
|
<span class="count">{{ directQuotes.length }}</span>
|
||||||
|
{{ i18n.ts._notification._types.quote }}
|
||||||
|
</option>
|
||||||
|
<option value="clips" v-if="clips?.length > 0">
|
||||||
|
<!-- <i class="ph-paperclip ph-bold ph-lg"></i> -->
|
||||||
<span class="count">{{ clips.length }}</span>
|
<span class="count">{{ clips.length }}</span>
|
||||||
</template>
|
|
||||||
{{ i18n.ts.clips }}
|
{{ i18n.ts.clips }}
|
||||||
</option>
|
</option>
|
||||||
</MkTab>
|
</MkTab>
|
||||||
|
@ -518,11 +510,15 @@ onUnmounted(() => {
|
||||||
overflow: clip;
|
overflow: clip;
|
||||||
outline: none;
|
outline: none;
|
||||||
scroll-margin-top: calc(var(--stickyTop) + 20vh);
|
scroll-margin-top: calc(var(--stickyTop) + 20vh);
|
||||||
|
&:not(:last-child) {
|
||||||
|
border-bottom: 1px solid var(--divider);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
.article {
|
.article {
|
||||||
cursor: unset;
|
cursor: unset;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
&:first-of-type {
|
&:first-child {
|
||||||
padding-top: 28px;
|
padding-top: 28px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -632,7 +628,7 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
> :deep(.note-container) {
|
> :deep(.note-container) {
|
||||||
padding: 6px 0 0 0;
|
padding: 12px 0 0 0;
|
||||||
> .header > .body {
|
> .header > .body {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
|
@ -642,7 +638,7 @@ onUnmounted(() => {
|
||||||
> :deep(.reacted-users > *) {
|
> :deep(.reacted-users > *) {
|
||||||
padding-inline: 16px !important;
|
padding-inline: 16px !important;
|
||||||
}
|
}
|
||||||
> .chips {
|
> :deep(.underline) {
|
||||||
padding-left: 16px !important;
|
padding-left: 16px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<article
|
||||||
v-if="!muted.muted || muted.what === 'reply'"
|
v-if="!muted.muted || muted.what === 'reply'"
|
||||||
ref="el"
|
ref="el"
|
||||||
v-size="{ max: [450, 500] }"
|
v-size="{ max: [450, 500] }"
|
||||||
|
@ -150,7 +150,7 @@
|
||||||
></MkA>
|
></MkA>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</article>
|
||||||
<div v-else class="muted" @click="muted.muted = false">
|
<div v-else class="muted" @click="muted.muted = false">
|
||||||
<I18n :src="softMuteReasonI18nSrc(muted.what)" tag="small">
|
<I18n :src="softMuteReasonI18nSrc(muted.what)" tag="small">
|
||||||
<template #name>
|
<template #name>
|
||||||
|
|
|
@ -69,11 +69,11 @@ const renote = async (viaKeyboard = false, ev?: MouseEvent) => {
|
||||||
|
|
||||||
const renotes = await os.api("notes/renotes", {
|
const renotes = await os.api("notes/renotes", {
|
||||||
noteId: props.note.id,
|
noteId: props.note.id,
|
||||||
limit: 11,
|
userId: $i.id,
|
||||||
|
limit: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
const users = renotes.map((x) => x.user.id);
|
const hasRenotedBefore = renotes.length > 0;
|
||||||
const hasRenotedBefore = users.includes($i.id);
|
|
||||||
|
|
||||||
let buttonActions: Array<MenuItem> = [];
|
let buttonActions: Array<MenuItem> = [];
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
!note.replyId
|
!note.replyId
|
||||||
"
|
"
|
||||||
:to="`/notes/${note.renoteId}`"
|
:to="`/notes/${note.renoteId}`"
|
||||||
v-tooltip="i18n.ts.jumpToReply"
|
v-tooltip="i18n.ts.jumpToPrevious"
|
||||||
class="reply-icon"
|
class="reply-icon"
|
||||||
@click.stop
|
@click.stop
|
||||||
>
|
>
|
||||||
|
@ -54,11 +54,12 @@
|
||||||
v-model="showContent"
|
v-model="showContent"
|
||||||
:note="note"
|
:note="note"
|
||||||
v-on:keydown="focusFooter"
|
v-on:keydown="focusFooter"
|
||||||
|
v-on:update:model-value="(val) => emit('expanded', val)"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="body"
|
class="body"
|
||||||
v-bind="{
|
v-bind="{
|
||||||
'aria-hidden': !showContent ? 'true' : null,
|
'aria-hidden': note.cw && !showContent ? 'true' : null,
|
||||||
tabindex: !showContent ? '-1' : null,
|
tabindex: !showContent ? '-1' : null,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
|
@ -70,7 +71,7 @@
|
||||||
v-if="!detailed && note.replyId"
|
v-if="!detailed && note.replyId"
|
||||||
:to="`#${note.replyId}`"
|
:to="`#${note.replyId}`"
|
||||||
behavior="browser"
|
behavior="browser"
|
||||||
v-tooltip="i18n.ts.jumpToReply"
|
v-tooltip="i18n.ts.jumpToPrevious"
|
||||||
class="reply-icon"
|
class="reply-icon"
|
||||||
@click.stop
|
@click.stop
|
||||||
>
|
>
|
||||||
|
@ -190,6 +191,7 @@ const props = defineProps<{
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: "push", v): void;
|
(ev: "push", v): void;
|
||||||
(ev: "focusfooter"): void;
|
(ev: "focusfooter"): void;
|
||||||
|
(ev: "expanded", v): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const cwButton = ref<HTMLElement>();
|
const cwButton = ref<HTMLElement>();
|
||||||
|
|
|
@ -16,9 +16,10 @@ export default defineComponent({
|
||||||
return h(
|
return h(
|
||||||
"div",
|
"div",
|
||||||
{
|
{
|
||||||
class: ["pxhvhrfw",
|
class: [
|
||||||
|
"pxhvhrfw",
|
||||||
{ chips: this.style === "chips" },
|
{ chips: this.style === "chips" },
|
||||||
{ underline: this.style === "underline" }
|
{ underline: this.style === "underline" },
|
||||||
],
|
],
|
||||||
role: "tablist",
|
role: "tablist",
|
||||||
},
|
},
|
||||||
|
@ -86,9 +87,14 @@ export default defineComponent({
|
||||||
> .icon {
|
> .icon {
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:empty {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.chips, &.underline {
|
&.chips,
|
||||||
|
&.underline {
|
||||||
padding: 12px 32px;
|
padding: 12px 32px;
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
@ -124,6 +130,7 @@ export default defineComponent({
|
||||||
&.underline {
|
&.underline {
|
||||||
padding-block: 0 !important;
|
padding-block: 0 !important;
|
||||||
margin-bottom: -1px;
|
margin-bottom: -1px;
|
||||||
|
border-radius: 0;
|
||||||
button {
|
button {
|
||||||
background: none !important;
|
background: none !important;
|
||||||
border-radius: 0 !important;
|
border-radius: 0 !important;
|
||||||
|
|
|
@ -299,6 +299,15 @@ const props = withDefaults(
|
||||||
filter: hue-rotate(360deg) contrast(150%) saturate(150%);
|
filter: hue-rotate(360deg) contrast(150%) saturate(150%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes mfm-fade {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
v-if="show"
|
v-if="show"
|
||||||
ref="el"
|
ref="el"
|
||||||
class="fdidabkb"
|
class="fdidabkb"
|
||||||
:class="{ slim: narrow, thin: thin_ }"
|
:class="{ thin: thin_, tabs: tabs?.length > 0 }"
|
||||||
:style="{ background: bg }"
|
:style="{ background: bg }"
|
||||||
@click="onClick"
|
@click="onClick"
|
||||||
>
|
>
|
||||||
|
<div class="left">
|
||||||
|
<div class="buttons">
|
||||||
<button
|
<button
|
||||||
v-if="props.displayBackButton"
|
v-if="props.displayBackButton"
|
||||||
class="_button button icon backButton"
|
class="_button button icon backButton"
|
||||||
|
@ -16,18 +18,17 @@
|
||||||
>
|
>
|
||||||
<i class="ph-caret-left ph-bold ph-lg"></i>
|
<i class="ph-caret-left ph-bold ph-lg"></i>
|
||||||
</button>
|
</button>
|
||||||
<div v-if="narrow" class="buttons left" @click="openAccountMenu">
|
|
||||||
<MkAvatar
|
<MkAvatar
|
||||||
v-if="props.displayMyAvatar && $i"
|
v-if="narrow && props.displayMyAvatar && $i"
|
||||||
class="avatar"
|
class="avatar button"
|
||||||
:user="$i"
|
:user="$i"
|
||||||
:disable-preview="true"
|
:disable-preview="true"
|
||||||
disableLink
|
disableLink
|
||||||
|
@click.stop="openAccountMenu"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="metadata">
|
|
||||||
<div
|
<div
|
||||||
v-if="!hideTitle"
|
v-if="!hideTitle && metadata"
|
||||||
class="titleContainer"
|
class="titleContainer"
|
||||||
@click="showTabsPopup"
|
@click="showTabsPopup"
|
||||||
>
|
>
|
||||||
|
@ -66,7 +67,14 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<nav ref="tabsEl" v-if="hasTabs" class="tabs">
|
</div>
|
||||||
|
<template v-if="metadata">
|
||||||
|
<nav
|
||||||
|
ref="tabsEl"
|
||||||
|
v-if="hasTabs"
|
||||||
|
class="tabs"
|
||||||
|
:class="{ collapse: hasTabs && tabs.length > 3 }"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
v-for="tab in tabs"
|
v-for="tab in tabs"
|
||||||
:ref="(el) => (tabRefs[tab.key] = el)"
|
:ref="(el) => (tabRefs[tab.key] = el)"
|
||||||
|
@ -85,6 +93,20 @@
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
<div class="buttons right">
|
<div class="buttons right">
|
||||||
|
<template v-if="metadata.avatar">
|
||||||
|
<MkFollowButton
|
||||||
|
v-if="narrow"
|
||||||
|
:user="metadata.avatar"
|
||||||
|
:full="false"
|
||||||
|
class="fullButton"
|
||||||
|
></MkFollowButton>
|
||||||
|
<MkFollowButton
|
||||||
|
v-else
|
||||||
|
:user="metadata.avatar"
|
||||||
|
:full="true"
|
||||||
|
class="fullButton"
|
||||||
|
></MkFollowButton>
|
||||||
|
</template>
|
||||||
<template v-for="action in actions">
|
<template v-for="action in actions">
|
||||||
<button
|
<button
|
||||||
v-tooltip.noDelay="action.text"
|
v-tooltip.noDelay="action.text"
|
||||||
|
@ -112,7 +134,7 @@ import {
|
||||||
nextTick,
|
nextTick,
|
||||||
reactive,
|
reactive,
|
||||||
} from "vue";
|
} from "vue";
|
||||||
import tinycolor from "tinycolor2";
|
import MkFollowButton from "@/components/MkFollowButton.vue";
|
||||||
import { popupMenu } from "@/os";
|
import { popupMenu } from "@/os";
|
||||||
import { scrollToTop } from "@/scripts/scroll";
|
import { scrollToTop } from "@/scripts/scroll";
|
||||||
import { globalEvents } from "@/events";
|
import { globalEvents } from "@/events";
|
||||||
|
@ -223,25 +245,9 @@ function goBack(): void {
|
||||||
window.history.back();
|
window.history.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
const calcBg = () => {
|
|
||||||
const rawBg = metadata?.bg || "var(--bg)";
|
|
||||||
const tinyBg = tinycolor(
|
|
||||||
rawBg.startsWith("var(")
|
|
||||||
? getComputedStyle(document.documentElement).getPropertyValue(
|
|
||||||
rawBg.slice(4, -1)
|
|
||||||
)
|
|
||||||
: rawBg
|
|
||||||
);
|
|
||||||
tinyBg.setAlpha(0.85);
|
|
||||||
bg.value = tinyBg.toRgbString();
|
|
||||||
};
|
|
||||||
|
|
||||||
let ro: ResizeObserver | null;
|
let ro: ResizeObserver | null;
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
calcBg();
|
|
||||||
globalEvents.on("themeChanged", calcBg);
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => [props.tab, props.tabs],
|
() => [props.tab, props.tabs],
|
||||||
() => {
|
() => {
|
||||||
|
@ -251,17 +257,15 @@ onMounted(() => {
|
||||||
// offsetWidth や offsetLeft は少数を丸めてしまうため getBoundingClientRect を使う必要がある
|
// offsetWidth や offsetLeft は少数を丸めてしまうため getBoundingClientRect を使う必要がある
|
||||||
// https://developer.mozilla.org/ja/docs/Web/API/HTMLElement/offsetWidth#%E5%80%A4
|
// https://developer.mozilla.org/ja/docs/Web/API/HTMLElement/offsetWidth#%E5%80%A4
|
||||||
const tabSizeX = tabEl.scrollWidth + 20; // + the tab's padding
|
const tabSizeX = tabEl.scrollWidth + 20; // + the tab's padding
|
||||||
|
if (props.tabs.length > 3) {
|
||||||
tabEl.style = `--width: ${tabSizeX}px`;
|
tabEl.style = `--width: ${tabSizeX}px`;
|
||||||
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const parentRect = tabsEl.getBoundingClientRect();
|
|
||||||
const rect = tabEl.getBoundingClientRect();
|
|
||||||
const left =
|
|
||||||
rect.left - parentRect.left + tabsEl?.scrollLeft;
|
|
||||||
tabHighlightEl.style.width = tabSizeX + "px";
|
tabHighlightEl.style.width = tabSizeX + "px";
|
||||||
tabHighlightEl.style.transform = `translateX(${left}px)`;
|
tabHighlightEl.style.transform = `translateX(${tabEl.offsetLeft}px)`;
|
||||||
window.requestAnimationFrame(() => {
|
window.requestAnimationFrame(() => {
|
||||||
tabsEl?.scrollTo({
|
tabsEl?.scrollTo({
|
||||||
left: left - 60,
|
left: tabEl.offsetLeft - 60,
|
||||||
behavior: "smooth",
|
behavior: "smooth",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -286,7 +290,6 @@ onMounted(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
globalEvents.off("themeChanged", calcBg);
|
|
||||||
if (ro) ro.disconnect();
|
if (ro) ro.disconnect();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -295,94 +298,96 @@ onUnmounted(() => {
|
||||||
.fdidabkb {
|
.fdidabkb {
|
||||||
--height: 55px;
|
--height: 55px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: var(--height);
|
||||||
|
padding-inline: 24px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
@media (max-width: 500px) {
|
||||||
|
padding-inline: 12p;
|
||||||
|
}
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
> .left {
|
||||||
|
min-width: unset !important;
|
||||||
|
max-width: 40%;
|
||||||
|
}
|
||||||
|
> .left,
|
||||||
|
> .right {
|
||||||
|
flex: unset !important;
|
||||||
|
}
|
||||||
|
&:not(.tabs) {
|
||||||
|
> .left {
|
||||||
|
width: 0 !important;
|
||||||
|
flex-grow: 1 !important;
|
||||||
|
max-width: unset !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.tabs {
|
||||||
|
> .left {
|
||||||
|
flex-shrink: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons ~ .titleContainer > .title {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
border-bottom: solid 0.5px var(--divider);
|
||||||
-webkit-backdrop-filter: var(--blur, blur(15px));
|
-webkit-backdrop-filter: var(--blur, blur(15px));
|
||||||
backdrop-filter: var(--blur, blur(15px));
|
backdrop-filter: var(--blur, blur(15px));
|
||||||
border-bottom: solid 0.5px var(--divider);
|
z-index: -1;
|
||||||
height: var(--height);
|
}
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: var(--bg);
|
||||||
|
opacity: 0.85;
|
||||||
|
z-index: -2;
|
||||||
|
}
|
||||||
|
|
||||||
&.thin {
|
&.thin {
|
||||||
--height: 45px;
|
--height: 45px;
|
||||||
|
|
||||||
> .buttons {
|
.buttons {
|
||||||
> .button {
|
> .button {
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.slim {
|
> .left {
|
||||||
> .titleContainer {
|
display: flex;
|
||||||
flex: 1;
|
|
||||||
margin: 0 auto;
|
|
||||||
|
|
||||||
> *:first-child {
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
> *:last-child {
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
> .tabs {
|
|
||||||
padding-inline: 12px;
|
|
||||||
mask: linear-gradient(
|
|
||||||
to right,
|
|
||||||
transparent,
|
|
||||||
black 10px 80%,
|
|
||||||
transparent
|
|
||||||
);
|
|
||||||
-webkit-mask: linear-gradient(
|
|
||||||
to right,
|
|
||||||
transparent,
|
|
||||||
black 10px 80%,
|
|
||||||
transparent
|
|
||||||
);
|
|
||||||
margin-left: -10px;
|
|
||||||
padding-left: 22px;
|
|
||||||
scrollbar-width: none;
|
|
||||||
&::before {
|
|
||||||
content: unset;
|
|
||||||
}
|
|
||||||
&::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
&::after {
|
|
||||||
// Force right padding
|
|
||||||
content: "";
|
|
||||||
display: inline-block;
|
|
||||||
min-width: 20%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .buttons {
|
> .buttons {
|
||||||
|
&:not(:empty) {
|
||||||
|
margin-left: calc(0px - var(--margin));
|
||||||
|
}
|
||||||
|
> .avatar {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
margin-left: var(--margin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons {
|
||||||
--margin: 8px;
|
--margin: 8px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: var(--height);
|
height: var(--height);
|
||||||
margin: 0 var(--margin);
|
|
||||||
|
|
||||||
&.left {
|
|
||||||
margin-right: auto;
|
|
||||||
|
|
||||||
> .avatar {
|
|
||||||
$size: 32px;
|
|
||||||
display: inline-block;
|
|
||||||
width: $size;
|
|
||||||
height: $size;
|
|
||||||
vertical-align: bottom;
|
|
||||||
margin: 0 8px;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.right {
|
&.right {
|
||||||
margin-left: auto;
|
justify-content: flex-end;
|
||||||
|
// margin-right: calc(0px - var(--margin));
|
||||||
|
// margin-left: var(--margin);
|
||||||
|
> .button:last-child {
|
||||||
|
margin-right: calc(0px - var(--margin));
|
||||||
}
|
}
|
||||||
|
|
||||||
&:empty {
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> .button/*, @at-root .backButton*/ {
|
> .button/*, @at-root .backButton*/ {
|
||||||
|
@ -412,13 +417,12 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .left {
|
||||||
> .backButton {
|
> .backButton {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-left: 1rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> .titleContainer {
|
> .titleContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -428,7 +432,6 @@ onUnmounted(() => {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
margin-left: 24px;
|
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
|
|
||||||
> .avatar {
|
> .avatar {
|
||||||
|
@ -445,7 +448,6 @@ onUnmounted(() => {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
transform: translate(0em);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> .title {
|
> .title {
|
||||||
|
@ -474,23 +476,58 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> .left,
|
||||||
|
> .right {
|
||||||
|
flex-basis: 100%;
|
||||||
|
flex-shrink: 9999;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
> .left {
|
||||||
|
min-width: 20%;
|
||||||
|
margin-left: -10px;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
> .right {
|
||||||
|
// margin-left: auto;
|
||||||
|
min-width: max-content;
|
||||||
|
margin-right: -10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
> .tabs {
|
> .tabs {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
contain: strict;
|
contain: content;
|
||||||
|
display: flex;
|
||||||
|
padding-inline: 20px;
|
||||||
|
margin-inline: -20px;
|
||||||
|
mask: linear-gradient(
|
||||||
|
to right,
|
||||||
|
transparent,
|
||||||
|
black 20px calc(100% - 20px),
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
-webkit-mask: linear-gradient(
|
||||||
|
to right,
|
||||||
|
transparent,
|
||||||
|
black 20px calc(100% - 20px),
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
scrollbar-width: none;
|
||||||
|
|
||||||
&::before {
|
&.collapse {
|
||||||
content: "";
|
--width: 38px;
|
||||||
display: inline-block;
|
> .tab {
|
||||||
height: 40%;
|
width: 38px;
|
||||||
border-left: 1px solid var(--divider);
|
min-width: 38px !important;
|
||||||
margin-right: 1em;
|
&:not(.active) > .title {
|
||||||
margin-left: 10px;
|
opacity: 0;
|
||||||
vertical-align: -1px;
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .tab {
|
> .tab {
|
||||||
|
@ -499,12 +536,12 @@ onUnmounted(() => {
|
||||||
position: relative;
|
position: relative;
|
||||||
border-inline: 10px solid transparent;
|
border-inline: 10px solid transparent;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
min-width: max-content;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
width: 38px;
|
|
||||||
--width: 38px;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition: color 0.2s, opacity 0.2s, width 0.2s;
|
transition: color 0.2s, opacity 0.2s, width 0.2s, min-width 0.2s;
|
||||||
|
--width: max-content;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
@ -515,9 +552,7 @@ onUnmounted(() => {
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
width: var(--width);
|
width: var(--width);
|
||||||
}
|
min-width: var(--width) !important;
|
||||||
&:not(.active) > .title {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> .icon + .title {
|
> .icon + .title {
|
||||||
|
@ -527,7 +562,6 @@ onUnmounted(() => {
|
||||||
transition: opacity 0.2s;
|
transition: opacity 0.2s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .highlight {
|
> .highlight {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
|
|
@ -156,6 +156,14 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
return h(MkSparkle, {}, genEl(token.children));
|
return h(MkSparkle, {}, genEl(token.children));
|
||||||
}
|
}
|
||||||
|
case "fade": {
|
||||||
|
const direction = token.props.args.out
|
||||||
|
? "alternate-reverse"
|
||||||
|
: "alternate";
|
||||||
|
const speed = validTime(token.props.args.speed) || "1.5s";
|
||||||
|
style = `animation: mfm-fade ${speed} linear infinite; animation-direction: ${direction};`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "flip": {
|
case "flip": {
|
||||||
const transform =
|
const transform =
|
||||||
token.props.args.h && token.props.args.v
|
token.props.args.h && token.props.args.v
|
||||||
|
|
|
@ -353,6 +353,18 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="section _block">
|
||||||
|
<div class="title">{{ i18n.ts._mfm.fade }}</div>
|
||||||
|
<div class="content">
|
||||||
|
<p>{{ i18n.ts._mfm.fadeDescription }}</p>
|
||||||
|
<div class="preview">
|
||||||
|
<Mfm :text="preview_fade" />
|
||||||
|
<MkTextarea v-model="preview_fade"
|
||||||
|
><span>MFM</span></MkTextarea
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="section _block">
|
<div class="section _block">
|
||||||
<div class="title">{{ i18n.ts._mfm.position }}</div>
|
<div class="title">{{ i18n.ts._mfm.position }}</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
@ -479,6 +491,7 @@ let preview_bg = $ref("$[bg.color=ff0000 Background color]");
|
||||||
let preview_plain = $ref(
|
let preview_plain = $ref(
|
||||||
"<plain>**bold** @mention #hashtag `code` $[x2 🍮]</plain>"
|
"<plain>**bold** @mention #hashtag `code` $[x2 🍮]</plain>"
|
||||||
);
|
);
|
||||||
|
let preview_fade = $ref("$[fade 🍮] $[fade.out 🍮] $[fade.speed=5s 🍮]");
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata({
|
||||||
title: i18n.ts._mfm.cheatSheet,
|
title: i18n.ts._mfm.cheatSheet,
|
||||||
|
|
|
@ -27,11 +27,10 @@
|
||||||
v-if="!showNext && hasNext"
|
v-if="!showNext && hasNext"
|
||||||
class="load next"
|
class="load next"
|
||||||
@click="showNext = true"
|
@click="showNext = true"
|
||||||
v-tooltip="
|
>
|
||||||
`${i18n.ts.loadMore} (${i18n.ts.newer})`
|
<i class="ph-caret-up ph-bold ph-lg"></i>
|
||||||
"
|
{{ `${i18n.ts.loadMore} (${i18n.ts.newer})` }}
|
||||||
><i class="ph-caret-up ph-bold ph-lg"></i
|
</MkButton>
|
||||||
></MkButton>
|
|
||||||
<div class="note _gap">
|
<div class="note _gap">
|
||||||
<MkRemoteCaution
|
<MkRemoteCaution
|
||||||
v-if="note.user.host != null"
|
v-if="note.user.host != null"
|
||||||
|
@ -47,11 +46,10 @@
|
||||||
v-if="!showPrev && hasPrev"
|
v-if="!showPrev && hasPrev"
|
||||||
class="load prev"
|
class="load prev"
|
||||||
@click="showPrev = true"
|
@click="showPrev = true"
|
||||||
v-tooltip="
|
>
|
||||||
`${i18n.ts.loadMore} (${i18n.ts.older})`
|
<i class="ph-caret-down ph-bold ph-lg"></i>
|
||||||
"
|
{{ `${i18n.ts.loadMore} (${i18n.ts.older})` }}
|
||||||
><i class="ph-caret-down ph-bold ph-lg"></i
|
</MkButton>
|
||||||
></MkButton>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="showPrev" class="_gap">
|
<div v-if="showPrev" class="_gap">
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
<MkInfo
|
<MkInfo
|
||||||
v-if="user.username.includes('.')"
|
v-if="user.username.includes('.')"
|
||||||
class="_formBlock"
|
class="_formBlock"
|
||||||
|
warn
|
||||||
>{{ i18n.ts.isSystemAccount }}</MkInfo
|
>{{ i18n.ts.isSystemAccount }}</MkInfo
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,6 @@
|
||||||
<div class="follow-container">
|
<div class="follow-container">
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<MkFollowButton
|
<MkFollowButton
|
||||||
v-if="$i != null && $i.id != user.id"
|
|
||||||
:user="user"
|
:user="user"
|
||||||
@refresh="emit('refresh')"
|
@refresh="emit('refresh')"
|
||||||
:inline="true"
|
:inline="true"
|
||||||
|
|
|
@ -199,6 +199,11 @@ export const routes = [
|
||||||
name: "api",
|
name: "api",
|
||||||
component: page(() => import("./pages/settings/api.vue")),
|
component: page(() => import("./pages/settings/api.vue")),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/apps",
|
||||||
|
name: "apps",
|
||||||
|
component: page(() => import("./pages/settings/apps.vue")),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/webhook/edit/:webhookId",
|
path: "/webhook/edit/:webhookId",
|
||||||
name: "webhook",
|
name: "webhook",
|
||||||
|
|
|
@ -9,6 +9,7 @@ const animatedMfm = [
|
||||||
"jump",
|
"jump",
|
||||||
"bounce",
|
"bounce",
|
||||||
"rainbow",
|
"rainbow",
|
||||||
|
"fade",
|
||||||
];
|
];
|
||||||
|
|
||||||
export function extractMfmWithAnimation(nodes: mfm.MfmNode[]): string[] {
|
export function extractMfmWithAnimation(nodes: mfm.MfmNode[]): string[] {
|
||||||
|
|
|
@ -19,4 +19,5 @@ export const MFM_TAGS = [
|
||||||
"rainbow",
|
"rainbow",
|
||||||
"sparkle",
|
"sparkle",
|
||||||
"rotate",
|
"rotate",
|
||||||
|
"fade",
|
||||||
];
|
];
|
||||||
|
|
|
@ -103,7 +103,7 @@ body::-webkit-scrollbar-thumb {
|
||||||
}
|
}
|
||||||
|
|
||||||
html._themeChanging_ {
|
html._themeChanging_ {
|
||||||
&, * {
|
&, *, ::before, ::after {
|
||||||
transition: background 1s ease, border 1s ease !important;
|
transition: background 1s ease, border 1s ease !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -402,7 +402,6 @@ function more(ev: MouseEvent) {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
transform: translateY(0.15em);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> .indicator {
|
> .indicator {
|
||||||
|
@ -524,7 +523,6 @@ function more(ev: MouseEvent) {
|
||||||
> .icon {
|
> .icon {
|
||||||
position: relative;
|
position: relative;
|
||||||
color: var(--fgOnAccent);
|
color: var(--fgOnAccent);
|
||||||
transform: translate(0.15em, 0em);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
> .text {
|
> .text {
|
||||||
|
|
|
@ -111,6 +111,7 @@
|
||||||
|
|
||||||
<div v-if="isMobile" class="buttons">
|
<div v-if="isMobile" class="buttons">
|
||||||
<button
|
<button
|
||||||
|
:aria-label="i18n.t('menu')"
|
||||||
class="button nav _button"
|
class="button nav _button"
|
||||||
@click="drawerMenuShowing = true"
|
@click="drawerMenuShowing = true"
|
||||||
>
|
>
|
||||||
|
@ -119,10 +120,15 @@
|
||||||
><i class="ph-circle ph-fill"></i
|
><i class="ph-circle ph-fill"></i
|
||||||
></span>
|
></span>
|
||||||
</button>
|
</button>
|
||||||
<button class="button home _button" @click="mainRouter.push('/')">
|
<button
|
||||||
|
:aria-label="i18n.t('home')"
|
||||||
|
class="button home _button"
|
||||||
|
@click="mainRouter.push('/')"
|
||||||
|
>
|
||||||
<i class="ph-house ph-bold ph-lg"></i>
|
<i class="ph-house ph-bold ph-lg"></i>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
:aria-label="i18n.t('notifications')"
|
||||||
class="button notifications _button"
|
class="button notifications _button"
|
||||||
@click="mainRouter.push('/my/notifications')"
|
@click="mainRouter.push('/my/notifications')"
|
||||||
>
|
>
|
||||||
|
@ -131,7 +137,11 @@
|
||||||
><i class="ph-circle ph-fill"></i
|
><i class="ph-circle ph-fill"></i
|
||||||
></span>
|
></span>
|
||||||
</button>
|
</button>
|
||||||
<button class="button post _button" @click="os.post()">
|
<button
|
||||||
|
:aria-label="i18n.t('note')"
|
||||||
|
class="button post _button"
|
||||||
|
@click="os.post()"
|
||||||
|
>
|
||||||
<i class="ph-pencil ph-bold ph-lg"></i>
|
<i class="ph-pencil ph-bold ph-lg"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
|
|
||||||
<div v-if="isMobile" class="buttons">
|
<div v-if="isMobile" class="buttons">
|
||||||
<button
|
<button
|
||||||
|
:aria-label="i18n.t('menu')"
|
||||||
class="button nav _button"
|
class="button nav _button"
|
||||||
@click="drawerMenuShowing = true"
|
@click="drawerMenuShowing = true"
|
||||||
>
|
>
|
||||||
|
@ -47,6 +48,7 @@
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
:aria-label="i18n.t('home')"
|
||||||
class="button home _button"
|
class="button home _button"
|
||||||
@click="
|
@click="
|
||||||
mainRouter.currentRoute.value.name === 'index'
|
mainRouter.currentRoute.value.name === 'index'
|
||||||
|
@ -63,6 +65,7 @@
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
:aria-label="i18n.t('notifications')"
|
||||||
class="button notifications _button"
|
class="button notifications _button"
|
||||||
@click="
|
@click="
|
||||||
mainRouter.push('/my/notifications');
|
mainRouter.push('/my/notifications');
|
||||||
|
@ -80,6 +83,7 @@
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
:aria-label="i18n.t('messaging')"
|
||||||
class="button messaging _button"
|
class="button messaging _button"
|
||||||
@click="
|
@click="
|
||||||
mainRouter.push('/my/messaging');
|
mainRouter.push('/my/messaging');
|
||||||
|
@ -99,6 +103,7 @@
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
:aria-label="i18n.t('_deck._columns.widgets')"
|
||||||
class="button widget _button"
|
class="button widget _button"
|
||||||
@click="widgetsShowing = true"
|
@click="widgetsShowing = true"
|
||||||
>
|
>
|
||||||
|
@ -111,6 +116,7 @@
|
||||||
<button
|
<button
|
||||||
v-if="isMobile && mainRouter.currentRoute.value.name === 'index'"
|
v-if="isMobile && mainRouter.currentRoute.value.name === 'index'"
|
||||||
ref="postButton"
|
ref="postButton"
|
||||||
|
:aria-label="i18n.t('note')"
|
||||||
class="postButton button post _button"
|
class="postButton button post _button"
|
||||||
@click="os.post()"
|
@click="os.post()"
|
||||||
>
|
>
|
||||||
|
@ -122,6 +128,7 @@
|
||||||
"
|
"
|
||||||
ref="postButton"
|
ref="postButton"
|
||||||
class="postButton button post _button"
|
class="postButton button post _button"
|
||||||
|
:aria-label="i18n.t('startMessaging')"
|
||||||
@click="messagingStart"
|
@click="messagingStart"
|
||||||
>
|
>
|
||||||
<i class="ph-user-plus ph-bold ph-lg"></i>
|
<i class="ph-user-plus ph-bold ph-lg"></i>
|
||||||
|
|
|
@ -264,8 +264,8 @@ importers:
|
||||||
specifier: 7.0.2
|
specifier: 7.0.2
|
||||||
version: 7.0.2(@types/koa@2.13.5)(ejs@3.1.8)(pug@3.0.2)
|
version: 7.0.2(@types/koa@2.13.5)(ejs@3.1.8)(pug@3.0.2)
|
||||||
mfm-js:
|
mfm-js:
|
||||||
specifier: 0.23.2
|
specifier: 0.23.3
|
||||||
version: 0.23.2
|
version: 0.23.3
|
||||||
mime-types:
|
mime-types:
|
||||||
specifier: 2.1.35
|
specifier: 2.1.35
|
||||||
version: 2.1.35
|
version: 2.1.35
|
||||||
|
@ -840,8 +840,8 @@ importers:
|
||||||
specifier: 2.1.0
|
specifier: 2.1.0
|
||||||
version: 2.1.0
|
version: 2.1.0
|
||||||
swiper:
|
swiper:
|
||||||
specifier: ^8.4.5
|
specifier: 9.3.2
|
||||||
version: 8.4.5
|
version: 9.3.2
|
||||||
syuilo-password-strength:
|
syuilo-password-strength:
|
||||||
specifier: 0.0.1
|
specifier: 0.0.1
|
||||||
version: 0.0.1
|
version: 0.0.1
|
||||||
|
@ -6411,12 +6411,6 @@ packages:
|
||||||
domhandler: 5.0.3
|
domhandler: 5.0.3
|
||||||
entities: 4.4.0
|
entities: 4.4.0
|
||||||
|
|
||||||
/dom7@4.0.4:
|
|
||||||
resolution: {integrity: sha512-DSSgBzQ4rJWQp1u6o+3FVwMNnT5bzQbMb+o31TjYYeRi05uAcpF8koxdfzeoe5ElzPmua7W7N28YJhF7iEKqIw==}
|
|
||||||
dependencies:
|
|
||||||
ssr-window: 4.0.2
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/domelementtype@1.3.1:
|
/domelementtype@1.3.1:
|
||||||
resolution: {integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==}
|
resolution: {integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -10424,17 +10418,10 @@ packages:
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/mfm-js@0.23.2:
|
|
||||||
resolution: {integrity: sha512-lfYvsMr6FIYbt0ZDL+nY+GWWqmcXpe9jrYLBLy5vvQHwGfPALpx43uNHj8hZsakgM82hPMo/zdx0e9tj+4Z4IA==}
|
|
||||||
dependencies:
|
|
||||||
twemoji-parser: 14.0.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/mfm-js@0.23.3:
|
/mfm-js@0.23.3:
|
||||||
resolution: {integrity: sha512-o8scYmbey6rMUmWAlT3k3ntt6khaCLdxlmHhAWV5wTTMj2OK1atQvZfRUq0SIVm1Jig08qlZg/ps71xUqrScNA==}
|
resolution: {integrity: sha512-o8scYmbey6rMUmWAlT3k3ntt6khaCLdxlmHhAWV5wTTMj2OK1atQvZfRUq0SIVm1Jig08qlZg/ps71xUqrScNA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
twemoji-parser: 14.0.0
|
twemoji-parser: 14.0.0
|
||||||
dev: true
|
|
||||||
|
|
||||||
/micromatch@3.1.10:
|
/micromatch@3.1.10:
|
||||||
resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==}
|
resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==}
|
||||||
|
@ -13594,12 +13581,10 @@ packages:
|
||||||
webpack: 5.75.0(@swc/core@1.3.50)(webpack-cli@5.0.1)
|
webpack: 5.75.0(@swc/core@1.3.50)(webpack-cli@5.0.1)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/swiper@8.4.5:
|
/swiper@9.3.2:
|
||||||
resolution: {integrity: sha512-zveyEFBBv4q1sVkbJHnuH4xCtarKieavJ4SxP0QEHvdpPLJRuD7j/Xg38IVVLbp7Db6qrPsLUePvxohYx39Agw==}
|
resolution: {integrity: sha512-Kj9Z4kXRmJR3YT/Wj+XLWj8P6IcRt+WG38uL8M3/Wny7+6sV0TlP9vnE1X+Co9c7VzNooojWGnFa+Wf/9+CUMA==}
|
||||||
engines: {node: '>= 4.7.0'}
|
engines: {node: '>= 4.7.0'}
|
||||||
requiresBuild: true
|
|
||||||
dependencies:
|
dependencies:
|
||||||
dom7: 4.0.4
|
|
||||||
ssr-window: 4.0.2
|
ssr-window: 4.0.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue