Merge branch 'develop' into sw-notification-action

This commit is contained in:
tamaina 2021-02-28 18:59:21 +09:00
commit 3d67998cbc
86 changed files with 1100 additions and 472 deletions

View file

@ -706,6 +706,7 @@ receiveAnnouncementFromInstance: "E-Mail-Benachrichtigungen von dieser Instanz e
emailNotification: "E-Mail-Benachrichtigungen" emailNotification: "E-Mail-Benachrichtigungen"
inChannelSearch: "In Kanal suchen" inChannelSearch: "In Kanal suchen"
useReactionPickerForContextMenu: "Reaktionsauswahl durch Rechtsklick öffnen" useReactionPickerForContextMenu: "Reaktionsauswahl durch Rechtsklick öffnen"
typingUsers: "{users} ist/sind am schreiben..."
jumpToSpecifiedDate: "Zu bestimmtem Datum springen" jumpToSpecifiedDate: "Zu bestimmtem Datum springen"
showingPastTimeline: "Momentan wird eine alte Chronik angezeigt" showingPastTimeline: "Momentan wird eine alte Chronik angezeigt"
clear: "Zurückkehren" clear: "Zurückkehren"

View file

@ -706,6 +706,7 @@ receiveAnnouncementFromInstance: "Receive Email notifications from this instance
emailNotification: "Email notifications" emailNotification: "Email notifications"
inChannelSearch: "Search in channel" inChannelSearch: "Search in channel"
useReactionPickerForContextMenu: "Open reaction picker on right-click" useReactionPickerForContextMenu: "Open reaction picker on right-click"
typingUsers: "{users} is/are typing..."
jumpToSpecifiedDate: "Jump to specific date" jumpToSpecifiedDate: "Jump to specific date"
showingPastTimeline: "Currently displaying an old timeline" showingPastTimeline: "Currently displaying an old timeline"
clear: "Return" clear: "Return"

View file

@ -268,8 +268,11 @@ other: "Avanzate"
abuseReports: "Segnala" abuseReports: "Segnala"
reportAbuse: "Segnala" reportAbuse: "Segnala"
reportAbuseOf: "Segnala {name}" reportAbuseOf: "Segnala {name}"
send: "Inviare"
openInNewTab: "Apri in una nuova scheda"
random: "Casuale" random: "Casuale"
system: "Sistema" system: "Sistema"
desktop: "Desktop"
optional: "Opzionale" optional: "Opzionale"
public: "Pubblico" public: "Pubblico"
yes: "Sì" yes: "Sì"

View file

@ -705,6 +705,10 @@ apply: "Применить"
receiveAnnouncementFromInstance: "Получать оповещения с инстанса" receiveAnnouncementFromInstance: "Получать оповещения с инстанса"
emailNotification: "Уведомления по электронной почте" emailNotification: "Уведомления по электронной почте"
inChannelSearch: "Поиск по каналу" inChannelSearch: "Поиск по каналу"
useReactionPickerForContextMenu: "Открывать палитру реакций правой кнопкой"
typingUsers: "Стук клавиш. Это {users}…"
jumpToSpecifiedDate: "Перейти к заданной дате"
showingPastTimeline: "Отображается старая лента"
_email: _email:
_follow: _follow:
title: "Новый подписчик" title: "Новый подписчик"

View file

@ -1,7 +1,7 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <syuilotan@yahoo.co.jp>", "author": "syuilo <syuilotan@yahoo.co.jp>",
"version": "12.71.0", "version": "12.72.0",
"codename": "indigo", "codename": "indigo",
"repository": { "repository": {
"type": "git", "type": "git",
@ -186,7 +186,7 @@
"multer": "1.4.2", "multer": "1.4.2",
"nested-property": "4.0.0", "nested-property": "4.0.0",
"node-fetch": "2.6.1", "node-fetch": "2.6.1",
"nodemailer": "6.4.18", "nodemailer": "6.5.0",
"object-assign-deep": "0.4.0", "object-assign-deep": "0.4.0",
"os-utils": "0.0.14", "os-utils": "0.0.14",
"p-cancelable": "2.0.0", "p-cancelable": "2.0.0",
@ -254,14 +254,14 @@
"vue-style-loader": "4.1.2", "vue-style-loader": "4.1.2",
"vuedraggable": "4.0.1", "vuedraggable": "4.0.1",
"web-push": "3.4.4", "web-push": "3.4.4",
"webpack": "5.23.0", "webpack": "5.24.2",
"webpack-cli": "4.5.0", "webpack-cli": "4.5.0",
"websocket": "1.0.33", "websocket": "1.0.33",
"ws": "7.4.3", "ws": "7.4.3",
"xev": "2.0.1" "xev": "2.0.1"
}, },
"devDependencies": { "devDependencies": {
"@types/chai": "4.2.14", "@types/chai": "4.2.15",
"@types/fluent-ffmpeg": "2.1.16", "@types/fluent-ffmpeg": "2.1.16",
"chai": "4.3.0", "chai": "4.3.0",
"cross-env": "7.0.3" "cross-env": "7.0.3"

View file

@ -66,7 +66,9 @@ if (!program.quiet) {
// Display detail of uncaught exception // Display detail of uncaught exception
process.on('uncaughtException', err => { process.on('uncaughtException', err => {
try {
logger.error(err); logger.error(err);
} catch { }
}); });
// Dying away... // Dying away...

View file

@ -401,7 +401,8 @@ export default defineComponent({
z-index: 65535; z-index: 65535;
max-width: 100%; max-width: 100%;
margin-top: calc(1em + 8px); margin-top: calc(1em + 8px);
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
transition: top 0.1s ease, left 0.1s ease; transition: top 0.1s ease, left 0.1s ease;
> ol { > ol {
@ -418,7 +419,8 @@ export default defineComponent({
align-items: center; align-items: center;
padding: 4px 12px; padding: 4px 12px;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
font-size: 0.9em; font-size: 0.9em;
cursor: default; cursor: default;
@ -427,7 +429,8 @@ export default defineComponent({
} }
* { * {
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
} }

View file

@ -66,7 +66,8 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.eftoefju { .eftoefju {
display: block; display: block;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
width: 100%; width: 100%;
&:hover { &:hover {

View file

@ -342,7 +342,8 @@ export default defineComponent({
text-align: center; text-align: center;
word-break: break-all; word-break: break-all;
color: var(--fg); color: var(--fg);
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
> .ext { > .ext {
opacity: 0.5; opacity: 0.5;

View file

@ -0,0 +1,201 @@
<template>
<MkModal ref="modal" :manual-showing="manualShowing" :src="src" @click="$refs.modal.close()" @opening="opening" @close="$emit('close')" @closed="$emit('closed')" v-slot="{ showing }">
<MkEmojiPicker v-show="showing !== false" :show-pinned="showPinned" :as-reaction-picker="asReactionPicker" @chosen="chosen" ref="picker"/>
</MkModal>
</template>
<script lang="ts">
import { defineComponent, markRaw } from 'vue';
import MkModal from '@/components/ui/modal.vue';
import MkEmojiPicker from '@/components/emoji-picker.vue';
export default defineComponent({
components: {
MkModal,
MkEmojiPicker,
},
props: {
manualShowing: {
type: Boolean,
required: false,
default: null,
},
src: {
required: false
},
showPinned: {
required: false,
default: true
},
asReactionPicker: {
required: false
},
},
emits: ['done', 'closed'],
data() {
return {
};
},
methods: {
chosen(emoji: any) {
this.$emit('done', emoji);
this.$refs.modal.close();
},
opening() {
this.$refs.picker.reset();
this.$refs.picker.focus();
}
}
});
</script>
<style lang="scss" scoped>
.omfetrab {
$pad: 8px;
--eachSize: 40px;
display: flex;
flex-direction: column;
contain: content;
&.big {
--eachSize: 44px;
}
&.w1 {
width: calc((var(--eachSize) * 5) + (#{$pad} * 2));
}
&.w2 {
width: calc((var(--eachSize) * 6) + (#{$pad} * 2));
}
&.w3 {
width: calc((var(--eachSize) * 7) + (#{$pad} * 2));
}
&.h1 {
--height: calc((var(--eachSize) * 4) + (#{$pad} * 2));
}
&.h2 {
--height: calc((var(--eachSize) * 6) + (#{$pad} * 2));
}
&.h3 {
--height: calc((var(--eachSize) * 8) + (#{$pad} * 2));
}
> .search {
width: 100%;
padding: 12px;
box-sizing: border-box;
font-size: 1em;
outline: none;
border: none;
background: transparent;
color: var(--fg);
&:not(.filled) {
order: 1;
z-index: 2;
box-shadow: 0px -1px 0 0px var(--divider);
}
}
> .emojis {
height: var(--height);
overflow-y: auto;
overflow-x: hidden;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
> .index {
min-height: var(--height);
position: relative;
border-bottom: solid 1px var(--divider);
> .arrow {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
padding: 16px 0;
text-align: center;
opacity: 0.5;
pointer-events: none;
}
}
section {
> header {
position: sticky;
top: 0;
left: 0;
z-index: 1;
padding: 8px;
font-size: 12px;
}
> div {
padding: $pad;
> button {
position: relative;
padding: 0;
width: var(--eachSize);
height: var(--eachSize);
border-radius: 4px;
&:focus {
outline: solid 2px var(--focus);
z-index: 1;
}
&:hover {
background: rgba(0, 0, 0, 0.05);
}
&:active {
background: var(--accent);
box-shadow: inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15);
}
> * {
font-size: 24px;
height: 1.25em;
vertical-align: -.25em;
pointer-events: none;
}
}
}
&.result {
border-bottom: solid 1px var(--divider);
&:empty {
display: none;
}
}
&.unicode {
min-height: 384px;
}
&.custom {
min-height: 64px;
}
}
}
}
</style>

View file

@ -0,0 +1,197 @@
<template>
<MkWindow ref="window"
:initial-width="null"
:initial-height="null"
:can-resize="false"
:mini="true"
:front="true"
@closed="$emit('closed')"
>
<MkEmojiPicker :show-pinned="showPinned" :as-reaction-picker="asReactionPicker" @chosen="chosen"/>
</MkWindow>
</template>
<script lang="ts">
import { defineComponent, markRaw } from 'vue';
import MkWindow from '@/components/ui/window.vue';
import MkEmojiPicker from '@/components/emoji-picker.vue';
export default defineComponent({
components: {
MkWindow,
MkEmojiPicker,
},
props: {
src: {
required: false
},
showPinned: {
required: false,
default: true
},
asReactionPicker: {
required: false
},
},
emits: ['chosen', 'closed'],
data() {
return {
};
},
methods: {
chosen(emoji: any) {
this.$emit('chosen', emoji);
},
}
});
</script>
<style lang="scss" scoped>
.omfetrab {
$pad: 8px;
--eachSize: 40px;
display: flex;
flex-direction: column;
contain: content;
&.big {
--eachSize: 44px;
}
&.w1 {
width: calc((var(--eachSize) * 5) + (#{$pad} * 2));
}
&.w2 {
width: calc((var(--eachSize) * 6) + (#{$pad} * 2));
}
&.w3 {
width: calc((var(--eachSize) * 7) + (#{$pad} * 2));
}
&.h1 {
--height: calc((var(--eachSize) * 4) + (#{$pad} * 2));
}
&.h2 {
--height: calc((var(--eachSize) * 6) + (#{$pad} * 2));
}
&.h3 {
--height: calc((var(--eachSize) * 8) + (#{$pad} * 2));
}
> .search {
width: 100%;
padding: 12px;
box-sizing: border-box;
font-size: 1em;
outline: none;
border: none;
background: transparent;
color: var(--fg);
&:not(.filled) {
order: 1;
z-index: 2;
box-shadow: 0px -1px 0 0px var(--divider);
}
}
> .emojis {
height: var(--height);
overflow-y: auto;
overflow-x: hidden;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
> .index {
min-height: var(--height);
position: relative;
border-bottom: solid 1px var(--divider);
> .arrow {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
padding: 16px 0;
text-align: center;
opacity: 0.5;
pointer-events: none;
}
}
section {
> header {
position: sticky;
top: 0;
left: 0;
z-index: 1;
padding: 8px;
font-size: 12px;
}
> div {
padding: $pad;
> button {
position: relative;
padding: 0;
width: var(--eachSize);
height: var(--eachSize);
border-radius: 4px;
&:focus {
outline: solid 2px var(--focus);
z-index: 1;
}
&:hover {
background: rgba(0, 0, 0, 0.05);
}
&:active {
background: var(--accent);
box-shadow: inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15);
}
> * {
font-size: 24px;
height: 1.25em;
vertical-align: -.25em;
pointer-events: none;
}
}
}
&.result {
border-bottom: solid 1px var(--divider);
&:empty {
display: none;
}
}
&.unicode {
min-height: 384px;
}
&.custom {
min-height: 64px;
}
}
}
}
</style>

View file

@ -0,0 +1,52 @@
<template>
<section>
<header class="_acrylic" @click="shown = !shown">
<Fa :icon="shown ? faChevronDown : faChevronUp" :key="shown" fixed-width class="toggle"/> <slot></slot> ({{ emojis.length }})
</header>
<div v-if="shown">
<button v-for="emoji in emojis"
class="_button"
@click="chosen(emoji, $event)"
:key="emoji"
>
<MkEmoji :emoji="emoji" :normal="true"/>
</button>
</div>
</section>
</template>
<script lang="ts">
import { defineComponent, markRaw } from 'vue';
import { faChevronUp, faChevronDown } from '@fortawesome/free-solid-svg-icons';
import { getStaticImageUrl } from '@/scripts/get-static-image-url';
export default defineComponent({
props: {
emojis: {
required: true,
},
initialShown: {
required: false
}
},
emits: ['chosen'],
data() {
return {
getStaticImageUrl,
shown: this.initialShown,
faChevronUp, faChevronDown,
};
},
methods: {
chosen(emoji: any, ev) {
this.$parent.chosen(emoji, ev);
},
}
});
</script>
<style lang="scss" scoped>
</style>

View file

@ -1,7 +1,6 @@
<template> <template>
<MkModal ref="modal" :src="src" @click="$refs.modal.close()" @closed="$emit('closed')">
<div class="omfetrab _popup" :class="['w' + width, 'h' + height, { big }]"> <div class="omfetrab _popup" :class="['w' + width, 'h' + height, { big }]">
<input ref="search" class="search" :class="{ filled: q != null && q != '' }" v-model.trim="q" :placeholder="$ts.search" @paste.stop="paste" @keyup.enter="done()"> <input ref="search" class="search" data-prevent-emoji-insert :class="{ filled: q != null && q != '' }" v-model.trim="q" :placeholder="$ts.search" @paste.stop="paste" @keyup.enter="done()">
<div class="emojis" ref="emojis"> <div class="emojis" ref="emojis">
<section class="result"> <section class="result">
<div v-if="searchResultCustom.length > 0"> <div v-if="searchResultCustom.length > 0">
@ -29,7 +28,7 @@
</div> </div>
</section> </section>
<div class="index"> <div class="index" v-if="tab === 'index'">
<section v-if="showPinned"> <section v-if="showPinned">
<div> <div>
<button v-for="emoji in pinned" <button v-for="emoji in pinned"
@ -54,64 +53,48 @@
</button> </button>
</div> </div>
</section> </section>
<div class="arrow"><Fa :icon="faChevronDown"/></div>
</div> </div>
<div>
<section v-for="category in customEmojiCategories" :key="'custom:' + category" class="custom"> <header class="_acrylic">{{ $ts.customEmojis }}</header>
<header class="_acrylic" v-appear="() => visibleCategories[category] = true">{{ category || $ts.other }}</header> <XSection v-for="category in customEmojiCategories" :key="'custom:' + category" :initial-shown="false" :emojis="customEmojis.filter(e => e.category === category).map(e => ':' + e.name + ':')">{{ category || $ts.other }}</XSection>
<div v-if="visibleCategories[category]">
<button v-for="emoji in customEmojis.filter(e => e.category === category)"
class="_button"
:title="emoji.name"
@click="chosen(emoji, $event)"
:key="emoji.name"
>
<img :src="$store.state.disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url"/>
</button>
</div> </div>
</section> <div>
<header class="_acrylic">{{ $ts.emoji }}</header>
<section v-for="category in categories" :key="category.name" class="unicode"> <XSection v-for="category in categories" :emojis="emojilist.filter(e => e.category === category).map(e => e.char)">{{ category }}</XSection>
<header class="_acrylic" v-appear="() => category.isActive = true"><Fa :icon="category.icon" fixed-width/> {{ category.name }}</header>
<div v-if="category.isActive">
<button v-for="emoji in emojilist.filter(e => e.category === category.name)"
class="_button"
:title="emoji.name"
@click="chosen(emoji, $event)"
:key="emoji.name"
>
<MkEmoji :emoji="emoji.char"/>
</button>
</div> </div>
</section> <div>
<header class="_acrylic">{{ $ts.tags }}</header>
<XSection v-for="tag in emojiTags" :emojis="customEmojis.filter(e => e.aliases.includes(tag)).map(e => ':' + e.name + ':')">{{ tag }}</XSection>
</div>
</div>
<div class="tabs">
<button class="_button tab" :class="{ active: tab === 'index' }" @click="tab = 'index'"><Fa :icon="faAsterisk" fixed-width/></button>
<button class="_button tab" :class="{ active: tab === 'custom' }" @click="tab = 'custom'"><Fa :icon="faLaugh" fixed-width/></button>
<button class="_button tab" :class="{ active: tab === 'unicode' }" @click="tab = 'unicode'"><Fa :icon="faLeaf" fixed-width/></button>
<button class="_button tab" :class="{ active: tab === 'tags' }" @click="tab = 'tags'"><Fa :icon="faHashtag" fixed-width/></button>
</div> </div>
</div> </div>
</MkModal>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, markRaw } from 'vue'; import { defineComponent, markRaw } from 'vue';
import { emojilist } from '../../misc/emojilist'; import { emojilist } from '../../misc/emojilist';
import { getStaticImageUrl } from '@/scripts/get-static-image-url'; import { getStaticImageUrl } from '@/scripts/get-static-image-url';
import { faAsterisk, faLeaf, faUtensils, faFutbol, faCity, faDice, faGlobe, faClock, faUser, faChevronDown } from '@fortawesome/free-solid-svg-icons'; import { faAsterisk, faLeaf, faUtensils, faFutbol, faCity, faDice, faGlobe, faClock, faUser, faChevronDown, faShapes, faBicycle, faHashtag } from '@fortawesome/free-solid-svg-icons';
import { faHeart, faFlag, faLaugh } from '@fortawesome/free-regular-svg-icons'; import { faHeart, faFlag, faLaugh } from '@fortawesome/free-regular-svg-icons';
import MkModal from '@/components/ui/modal.vue';
import Particle from '@/components/particle.vue'; import Particle from '@/components/particle.vue';
import * as os from '@/os'; import * as os from '@/os';
import { isDeviceTouch } from '@/scripts/is-device-touch'; import { isDeviceTouch } from '@/scripts/is-device-touch';
import { isMobile } from '@/scripts/is-mobile'; import { isMobile } from '@/scripts/is-mobile';
import { emojiCategories } from '@/instance'; import { emojiCategories, emojiTags } from '@/instance';
import XSection from './emoji-picker.section.vue';
export default defineComponent({ export default defineComponent({
components: { components: {
MkModal, XSection
}, },
props: { props: {
src: {
required: false
},
showPinned: { showPinned: {
required: false, required: false,
default: true default: true
@ -121,7 +104,7 @@ export default defineComponent({
}, },
}, },
emits: ['done', 'closed'], emits: ['chosen'],
data() { data() {
return { return {
@ -132,50 +115,14 @@ export default defineComponent({
height: this.asReactionPicker ? this.$store.state.reactionPickerHeight : 2, height: this.asReactionPicker ? this.$store.state.reactionPickerHeight : 2,
big: this.asReactionPicker ? isDeviceTouch : false, big: this.asReactionPicker ? isDeviceTouch : false,
customEmojiCategories: emojiCategories, customEmojiCategories: emojiCategories,
emojiTags,
customEmojis: this.$instance.emojis, customEmojis: this.$instance.emojis,
visibleCategories: {},
q: null, q: null,
searchResultCustom: [], searchResultCustom: [],
searchResultUnicode: [], searchResultUnicode: [],
faGlobe, faClock, faChevronDown, tab: 'index',
categories: [{ categories: ['face', 'people', 'animals_and_nature', 'food_and_drink', 'activity', 'travel_and_places', 'objects', 'symbols', 'flags'],
name: 'face', faGlobe, faClock, faChevronDown, faAsterisk, faLaugh, faUtensils, faLeaf, faShapes, faBicycle, faHashtag,
icon: faLaugh,
isActive: false
}, {
name: 'people',
icon: faUser,
isActive: false
}, {
name: 'animals_and_nature',
icon: faLeaf,
isActive: false
}, {
name: 'food_and_drink',
icon: faUtensils,
isActive: false
}, {
name: 'activity',
icon: faFutbol,
isActive: false
}, {
name: 'travel_and_places',
icon: faCity,
isActive: false
}, {
name: 'objects',
icon: faDice,
isActive: false
}, {
name: 'symbols',
icon: faHeart,
isActive: false
}, {
name: 'flags',
icon: faFlag,
isActive: false
}],
faAsterisk
}; };
}, },
@ -323,6 +270,11 @@ export default defineComponent({
}, },
mounted() { mounted() {
this.focus();
},
methods: {
focus() {
if (!isMobile && !isDeviceTouch) { if (!isMobile && !isDeviceTouch) {
this.$refs.search.focus({ this.$refs.search.focus({
preventScroll: true preventScroll: true
@ -330,7 +282,10 @@ export default defineComponent({
} }
}, },
methods: { reset() {
this.$refs.emojis.scrollTop = 0;
},
getKey(emoji: any) { getKey(emoji: any) {
return typeof emoji === 'string' ? emoji : (emoji.char || `:${emoji.name}:`); return typeof emoji === 'string' ? emoji : (emoji.char || `:${emoji.name}:`);
}, },
@ -345,15 +300,14 @@ export default defineComponent({
} }
const key = this.getKey(emoji); const key = this.getKey(emoji);
this.$emit('done', key); this.$emit('chosen', key);
this.$refs.modal.close();
// 使 // 使
if (!this.pinned.includes(key)) { if (!this.pinned.includes(key)) {
let recents = this.$store.state.recentlyUsedEmojis; let recents = this.$store.state.recentlyUsedEmojis;
recents = recents.filter((e: any) => e !== key); recents = recents.filter((e: any) => e !== key);
recents.unshift(key); recents.unshift(key);
this.$store.set('recentlyUsedEmojis', recents.splice(0, 16)); this.$store.set('recentlyUsedEmojis', recents.splice(0, 32));
} }
}, },
@ -445,6 +399,22 @@ export default defineComponent({
} }
} }
> .tabs {
display: flex;
display: none;
> .tab {
flex: 1;
height: 38px;
border-top: solid 1px var(--divider);
&.active {
border-top: solid 1px var(--accent);
color: var(--accent);
}
}
}
> .emojis { > .emojis {
height: var(--height); height: var(--height);
overflow-y: auto; overflow-y: auto;
@ -456,34 +426,43 @@ export default defineComponent({
display: none; display: none;
} }
> .index { > div {
min-height: var(--height); &:not(.index) {
position: relative; padding: 4px 0 8px 0;
border-bottom: solid 1px var(--divider); border-top: solid 1px var(--divider);
}
> .arrow { > header {
position: absolute; /*position: sticky;
bottom: 0; top: 0;
left: 0; left: 0;*/
width: 100%; height: 32px;
padding: 16px 0; line-height: 32px;
text-align: center; z-index: 2;
opacity: 0.5; padding: 0 8px;
pointer-events: none; font-size: 12px;
} }
} }
section { ::v-deep(section) {
> header { > header {
position: sticky; position: sticky;
top: 0; top: 0;
left: 0; left: 0;
height: 32px;
line-height: 32px;
z-index: 1; z-index: 1;
padding: 8px; padding: 0 8px;
font-size: 12px; font-size: 12px;
cursor: pointer;
&:hover {
color: var(--accent);
}
} }
> div { > div {
position: relative;
padding: $pad; padding: $pad;
> button { > button {
@ -523,14 +502,6 @@ export default defineComponent({
display: none; display: none;
} }
} }
&.unicode {
min-height: 384px;
}
&.custom {
min-height: 64px;
}
} }
} }
} }

View file

@ -261,7 +261,8 @@ export default defineComponent({
display: inline-block; display: inline-block;
min-width: 16px; min-width: 16px;
max-width: 150px; max-width: 150px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
} }

View file

@ -83,7 +83,8 @@ export default defineComponent({
> .text { > .text {
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
padding-right: 12px; padding-right: 12px;
} }

View file

@ -101,7 +101,8 @@ export default defineComponent({
top: 0; top: 0;
border-radius: 100%; border-radius: 100%;
z-index: 1; z-index: 1;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
object-fit: cover; object-fit: cover;
width: 100%; width: 100%;
height: 100%; height: 100%;

View file

@ -126,7 +126,8 @@ export default defineComponent({
&.nowrap { &.nowrap {
white-space: pre; white-space: pre;
word-wrap: normal; // https://codeday.me/jp/qa/20190424/690106.html word-wrap: normal; // https://codeday.me/jp/qa/20190424/690106.html
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
} }

View file

@ -692,7 +692,8 @@ export default defineComponent({
> dd { > dd {
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
white-space: nowrap; white-space: nowrap;
} }

View file

@ -44,7 +44,8 @@ export default defineComponent({
height: $height; height: $height;
border-radius: 4px 0 0 4px; border-radius: 4px 0 0 4px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
color: #fff; color: #fff;
> .icon { > .icon {

View file

@ -62,7 +62,8 @@ export default defineComponent({
width: 100%; width: 100%;
border-radius: 4px; border-radius: 4px;
margin-top: 4px; margin-top: 4px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
> .download, > .download,
> .sensitive { > .sensitive {
@ -77,7 +78,8 @@ export default defineComponent({
} }
> b { > b {
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
} }

View file

@ -143,7 +143,8 @@ export default defineComponent({
> a { > a {
display: block; display: block;
cursor: zoom-in; cursor: zoom-in;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
width: 100%; width: 100%;
height: 100%; height: 100%;
background-position: center; background-position: center;

View file

@ -105,7 +105,8 @@ export default defineComponent({
grid-gap: 4px; grid-gap: 4px;
> * { > * {
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
border-radius: 6px; border-radius: 6px;
} }

View file

@ -78,7 +78,8 @@ export default defineComponent({
align-items: center; align-items: center;
font-size: 3.5em; font-size: 3.5em;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
background-position: center; background-position: center;
background-size: cover; background-size: cover;
width: 100%; width: 100%;

View file

@ -523,20 +523,14 @@ export default defineComponent({
react(viaKeyboard = false) { react(viaKeyboard = false) {
pleaseLogin(); pleaseLogin();
this.blur(); this.blur();
os.popup(import('@/components/emoji-picker.vue'), { os.pickReaction(this.$refs.reactButton, reaction => {
src: this.$refs.reactButton,
asReactionPicker: true
}, {
done: reaction => {
if (reaction) {
os.api('notes/reactions/create', { os.api('notes/reactions/create', {
noteId: this.appearNote.id, noteId: this.appearNote.id,
reaction: reaction reaction: reaction
}); });
} }, () => {
this.focus(); this.focus();
}, });
}, 'closed');
}, },
reactDirectly(reaction) { reactDirectly(reaction) {
@ -892,7 +886,8 @@ export default defineComponent({
.note { .note {
position: relative; position: relative;
transition: box-shadow 0.1s ease; transition: box-shadow 0.1s ease;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
contain: content; contain: content;
&:focus-visible { &:focus-visible {
@ -952,7 +947,8 @@ export default defineComponent({
} }
> span { > span {
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
flex-shrink: 1; flex-shrink: 1;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;

View file

@ -61,7 +61,8 @@ export default defineComponent({
display: block; display: block;
margin: 0 .5em 0 0; margin: 0 .5em 0 0;
padding: 0; padding: 0;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
font-size: 1em; font-size: 1em;
font-weight: bold; font-weight: bold;
text-decoration: none; text-decoration: none;
@ -90,7 +91,8 @@ export default defineComponent({
> .username { > .username {
margin: 0 .5em 0 0; margin: 0 .5em 0 0;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
} }

View file

@ -50,7 +50,8 @@ export default defineComponent({
display: flex; display: flex;
margin: 0; margin: 0;
padding: 0; padding: 0;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
font-size: 0.95em; font-size: 0.95em;
> .avatar { > .avatar {

View file

@ -498,20 +498,14 @@ export default defineComponent({
react(viaKeyboard = false) { react(viaKeyboard = false) {
pleaseLogin(); pleaseLogin();
this.blur(); this.blur();
os.popup(import('@/components/emoji-picker.vue'), { os.pickReaction(this.$refs.reactButton, reaction => {
src: this.$refs.reactButton,
asReactionPicker: true
}, {
done: reaction => {
if (reaction) {
os.api('notes/reactions/create', { os.api('notes/reactions/create', {
noteId: this.appearNote.id, noteId: this.appearNote.id,
reaction: reaction reaction: reaction
}); });
} }, () => {
this.focus(); this.focus();
}, });
}, 'closed');
}, },
reactDirectly(reaction) { reactDirectly(reaction) {
@ -867,7 +861,8 @@ export default defineComponent({
.tkcbzcuz { .tkcbzcuz {
position: relative; position: relative;
transition: box-shadow 0.1s ease; transition: box-shadow 0.1s ease;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
contain: content; contain: content;
// //
@ -954,7 +949,8 @@ export default defineComponent({
} }
> span { > span {
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
flex-shrink: 1; flex-shrink: 1;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
@ -1026,7 +1022,8 @@ export default defineComponent({
&.collapsed { &.collapsed {
position: relative; position: relative;
max-height: 9em; max-height: 9em;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
> .fade { > .fade {
display: block; display: block;

View file

@ -268,7 +268,8 @@ export default defineComponent({
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
min-width: 0; min-width: 0;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
} }
> .time { > .time {
@ -279,7 +280,8 @@ export default defineComponent({
> .text { > .text {
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
> [data-icon] { > [data-icon] {

View file

@ -112,7 +112,8 @@ export default defineComponent({
padding: 4px 8px; padding: 4px 8px;
border: solid 1px var(--divider); border: solid 1px var(--divider);
border-radius: 4px; border-radius: 4px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
cursor: pointer; cursor: pointer;
&:hover { &:hover {

View file

@ -127,7 +127,8 @@ export default defineComponent({
height: 64px; height: 64px;
margin-right: 4px; margin-right: 4px;
border-radius: 4px; border-radius: 4px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
cursor: move; cursor: move;
&:hover > .remove { &:hover > .remove {

View file

@ -632,9 +632,7 @@ export default defineComponent({
}, },
async insertEmoji(ev) { async insertEmoji(ev) {
os.pickEmoji(ev.currentTarget || ev.target).then(emoji => { os.openEmojiPicker(ev.currentTarget || ev.target, {}, this.$refs.text);
insertTextAtCursor(this.$refs.text, emoji);
});
}, },
showActions(ev) { showActions(ev) {

View file

@ -390,7 +390,8 @@ export default defineComponent({
font-size: $ui-font-size; font-size: $ui-font-size;
line-height: 3rem; line-height: 3rem;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
white-space: nowrap; white-space: nowrap;
width: 100%; width: 100%;
text-align: left; text-align: left;

View file

@ -67,7 +67,8 @@ export default defineComponent({
height: 100%; height: 100%;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
border-radius: 8px; border-radius: 8px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
} }
} }
</style> </style>

View file

@ -124,7 +124,8 @@ export default defineComponent({
text-decoration: none; text-decoration: none;
background: var(--buttonBg); background: var(--buttonBg);
border-radius: 999px; border-radius: 999px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
&:not(:disabled):hover { &:not(:disabled):hover {
background: var(--buttonHoverBg); background: var(--buttonHoverBg);
@ -212,7 +213,8 @@ export default defineComponent({
width: 100%; width: 100%;
height: 100%; height: 100%;
border-radius: 6px; border-radius: 6px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
::v-deep(div) { ::v-deep(div) {
position: absolute; position: absolute;

View file

@ -116,7 +116,8 @@ export default defineComponent({
.ukygtjoj { .ukygtjoj {
position: relative; position: relative;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
&.naked { &.naked {
background: transparent !important; background: transparent !important;

View file

@ -298,7 +298,8 @@ export default defineComponent({
transform: scale(.75); transform: scale(.75);
white-space: nowrap; white-space: nowrap;
width: 133%; width: 133%;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
> .warning { > .warning {
@ -354,7 +355,8 @@ export default defineComponent({
display: inline-block; display: inline-block;
min-width: 16px; min-width: 16px;
max-width: 150px; max-width: 150px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
} }

View file

@ -155,7 +155,8 @@ export default defineComponent({
font-size: 0.9em; font-size: 0.9em;
line-height: 20px; line-height: 20px;
text-align: center; text-align: center;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
&.danger { &.danger {

View file

@ -89,7 +89,8 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.ebkgoccj { .ebkgoccj {
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
contain: content; contain: content;
@ -123,7 +124,8 @@ export default defineComponent({
padding-left: 32px; padding-left: 32px;
font-weight: bold; font-weight: bold;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
pointer-events: none; pointer-events: none;

View file

@ -1,11 +1,11 @@
<template> <template>
<div class="mk-modal" v-hotkey.global="keymap" :style="{ pointerEvents: showing ? 'auto' : 'none', '--transformOrigin': transformOrigin }"> <div class="mk-modal" v-hotkey.global="keymap" :style="{ pointerEvents: (manualShowing != null ? manualShowing : showing) ? 'auto' : 'none', '--transformOrigin': transformOrigin }">
<transition :name="$store.state.animation ? 'modal-bg' : ''" appear> <transition :name="$store.state.animation ? 'modal-bg' : ''" appear>
<div class="bg _modalBg" v-if="showing" @click="onBgClick"></div> <div class="bg _modalBg" v-if="manualShowing != null ? manualShowing : showing" @click="onBgClick"></div>
</transition> </transition>
<div class="content" :class="{ popup, fixed, top: position === 'top' }" @click.self="onBgClick" ref="content"> <div class="content" :class="{ popup, fixed, top: position === 'top' }" @click.self="onBgClick" ref="content">
<transition :name="$store.state.animation ? popup ? 'modal-popup-content' : 'modal-content' : ''" appear @after-leave="$emit('closed')" @after-enter="childRendered"> <transition :name="$store.state.animation ? popup ? 'modal-popup-content' : 'modal-content' : ''" appear @after-leave="$emit('closed')" @enter="$emit('opening')" @after-enter="childRendered">
<slot v-if="showing"></slot> <slot v-if="manualShowing != null ? true : showing" v-bind:showing="manualShowing"></slot>
</transition> </transition>
</div> </div>
</div> </div>
@ -29,6 +29,11 @@ export default defineComponent({
modal: true modal: true
}, },
props: { props: {
manualShowing: {
type: Boolean,
required: false,
default: null,
},
srcCenter: { srcCenter: {
type: Boolean, type: Boolean,
required: false required: false
@ -40,7 +45,7 @@ export default defineComponent({
required: false required: false
} }
}, },
emits: ['click', 'esc', 'closed'], emits: ['opening', 'click', 'esc', 'close', 'closed'],
data() { data() {
return { return {
showing: true, showing: true,
@ -60,15 +65,26 @@ export default defineComponent({
} }
}, },
mounted() { mounted() {
this.$watch('src', () => {
this.fixed = getFixedContainer(this.src) != null; this.fixed = getFixedContainer(this.src) != null;
this.$nextTick(() => {
this.align();
});
}, { immediate: true });
this.$nextTick(() => { this.$nextTick(() => {
const popover = this.$refs.content as any;
new ResizeObserver((entries, observer) => {
this.align();
}).observe(popover);
});
},
methods: {
align() {
if (!this.popup) return; if (!this.popup) return;
const popover = this.$refs.content as any; const popover = this.$refs.content as any;
// TODO: ResizeObserver
new ResizeObserver((entries, observer) => {
const rect = this.src.getBoundingClientRect(); const rect = this.src.getBoundingClientRect();
const width = popover.offsetWidth; const width = popover.offsetWidth;
@ -117,14 +133,14 @@ export default defineComponent({
if (top > rect.top + (this.fixed ? 0 : window.pageYOffset)) { if (top > rect.top + (this.fixed ? 0 : window.pageYOffset)) {
this.transformOrigin = 'center top'; this.transformOrigin = 'center top';
} else {
this.transformOrigin = 'center';
} }
popover.style.left = left + 'px'; popover.style.left = left + 'px';
popover.style.top = top + 'px'; popover.style.top = top + 'px';
}).observe(popover);
});
}, },
methods: {
childRendered() { childRendered() {
// //
const content = this.$refs.content.children[0]; const content = this.$refs.content.children[0];
@ -141,6 +157,7 @@ export default defineComponent({
close() { close() {
this.showing = false; this.showing = false;
this.$emit('close');
}, },
onBgClick() { onBgClick() {

View file

@ -89,7 +89,8 @@ export default defineComponent({
pointer-events: none; pointer-events: none;
font-size: 16px; font-size: 16px;
color: var(--inputLabel); color: var(--inputLabel);
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
} }
> input { > input {

View file

@ -1,8 +1,8 @@
<template> <template>
<transition :name="$store.state.animation ? 'window' : ''" appear @after-leave="$emit('closed')"> <transition :name="$store.state.animation ? 'window' : ''" appear @after-leave="$emit('closed')">
<div class="ebkgocck" v-if="showing"> <div class="ebkgocck" :class="{ front }" v-if="showing">
<div class="body _popup _shadow _narrow_" @mousedown="onBodyMousedown" @keydown="onKeydown"> <div class="body _popup _shadow _narrow_" @mousedown="onBodyMousedown" @keydown="onKeydown">
<div class="header" @contextmenu.prevent.stop="onContextmenu"> <div class="header" :class="{ mini }" @contextmenu.prevent.stop="onContextmenu">
<slot v-if="closeRight" name="buttons"><button class="_button" style="pointer-events: none;"></button></slot> <slot v-if="closeRight" name="buttons"><button class="_button" style="pointer-events: none;"></button></slot>
<button v-else class="_button" @click="close()"><Fa :icon="faTimes"/></button> <button v-else class="_button" @click="close()"><Fa :icon="faTimes"/></button>
@ -92,6 +92,16 @@ export default defineComponent({
required: false, required: false,
default: false, default: false,
}, },
mini: {
type: Boolean,
required: false,
default: false,
},
front: {
type: Boolean,
required: false,
default: false,
},
contextmenu: { contextmenu: {
type: Array, type: Array,
required: false, required: false,
@ -387,8 +397,13 @@ export default defineComponent({
left: 0; left: 0;
z-index: 5000; z-index: 5000;
&.front {
z-index: 11000; // frontmk-modal
}
> .body { > .body {
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
contain: content; contain: content;
@ -396,17 +411,22 @@ export default defineComponent({
height: 100%; height: 100%;
> .header { > .header {
$height: 50px; --height: 50px;
&.mini {
--height: 38px;
}
display: flex; display: flex;
position: relative; position: relative;
z-index: 1; z-index: 1;
flex-shrink: 0; flex-shrink: 0;
user-select: none; user-select: none;
height: $height; height: var(--height);
> ::v-deep(button) { > ::v-deep(button) {
height: $height; height: var(--height);
width: $height; width: var(--height);
&:hover { &:hover {
color: var(--fgHighlighted); color: var(--fgHighlighted);
@ -416,9 +436,10 @@ export default defineComponent({
> .title { > .title {
flex: 1; flex: 1;
position: relative; position: relative;
line-height: $height; line-height: var(--height);
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
text-align: center; text-align: center;
cursor: move; cursor: move;

View file

@ -244,7 +244,8 @@ export default defineComponent({
font-size: 14px; font-size: 14px;
box-shadow: 0 0 0 1px var(--divider); box-shadow: 0 0 0 1px var(--divider);
border-radius: 8px; border-radius: 8px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
&:hover { &:hover {
text-decoration: none; text-decoration: none;
@ -326,7 +327,8 @@ export default defineComponent({
&.compact { &.compact {
> article { > article {
> header h1, p, footer { > header h1, p, footer {
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
} }

View file

@ -110,7 +110,8 @@ export default defineComponent({
display: -webkit-box; display: -webkit-box;
-webkit-line-clamp: 3; -webkit-line-clamp: 3;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
} }
} }

View file

@ -111,7 +111,8 @@ export default defineComponent({
position: absolute; position: absolute;
z-index: 11000; z-index: 11000;
width: 300px; width: 300px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
transform-origin: center top; transform-origin: center top;
> .info { > .info {

View file

@ -66,7 +66,8 @@ export default defineComponent({
height: 350px; height: 350px;
background: var(--panel); background: var(--panel);
border-radius: var(--radius); border-radius: var(--radius);
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -127,7 +128,8 @@ export default defineComponent({
> .body { > .body {
padding: 0 8px; padding: 0 8px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
> .name { > .name {
display: block; display: block;

View file

@ -141,7 +141,8 @@ export default defineComponent({
> *:nth-child(2) { > *:nth-child(2) {
flex: 1 1 auto; flex: 1 1 auto;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
> span:first-child { > span:first-child {

View file

@ -17,6 +17,7 @@ if (localStorage.getItem('vuex') != null) {
set('accounts', JSON.parse(JSON.stringify(vuex.device.accounts))); set('accounts', JSON.parse(JSON.stringify(vuex.device.accounts)));
localStorage.setItem('miux:themes', JSON.stringify(vuex.device.themes)); localStorage.setItem('miux:themes', JSON.stringify(vuex.device.themes));
if (vuex.device.userData) {
for (const [k, v] of Object.entries(vuex.device.userData)) { for (const [k, v] of Object.entries(vuex.device.userData)) {
localStorage.setItem('pizzax::base::' + k, JSON.stringify({ localStorage.setItem('pizzax::base::' + k, JSON.stringify({
widgets: v.widgets widgets: v.widgets
@ -29,6 +30,7 @@ if (localStorage.getItem('vuex') != null) {
})); }));
} }
} }
}
localStorage.setItem('vuex-old', JSON.stringify(vuex)); localStorage.setItem('vuex-old', JSON.stringify(vuex));
localStorage.removeItem('vuex'); localStorage.removeItem('vuex');

View file

@ -37,6 +37,16 @@ export const emojiCategories = computed(() => {
return Array.from(categories); return Array.from(categories);
}); });
export const emojiTags = computed(() => {
const tags = new Set();
for (const emoji of instance.emojis) {
for (const tag of emoji.aliases) {
tags.add(tag);
}
}
return Array.from(tags);
});
// このファイルに書きたくないけどここに書かないと何故かVeturが認識しない // このファイルに書きたくないけどここに書かないと何故かVeturが認識しない
declare module '@vue/runtime-core' { declare module '@vue/runtime-core' {
interface ComponentCustomProperties { interface ComponentCustomProperties {

View file

@ -1,5 +1,8 @@
// TODO: なんでもかんでもos.tsに突っ込むのやめたいのでよしなに分割する
import { Component, defineAsyncComponent, markRaw, reactive, Ref, ref } from 'vue'; import { Component, defineAsyncComponent, markRaw, reactive, Ref, ref } from 'vue';
import { EventEmitter } from 'eventemitter3'; import { EventEmitter } from 'eventemitter3';
import insertTextAtCursor from 'insert-text-at-cursor';
import * as Sentry from '@sentry/browser'; import * as Sentry from '@sentry/browser';
import Stream from '@/scripts/stream'; import Stream from '@/scripts/stream';
import { apiUrl, debug } from '@/config'; import { apiUrl, debug } from '@/config';
@ -289,7 +292,7 @@ export async function selectDriveFolder(multiple: boolean) {
export async function pickEmoji(src?: HTMLElement, opts) { export async function pickEmoji(src?: HTMLElement, opts) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
popup(import('@/components/emoji-picker.vue'), { popup(import('@/components/emoji-picker-dialog.vue'), {
src, src,
...opts ...opts
}, { }, {
@ -300,6 +303,92 @@ export async function pickEmoji(src?: HTMLElement, opts) {
}); });
} }
type AwaitType<T> =
T extends Promise<infer U> ? U :
T extends (...args: Array<any>) => Promise<infer V> ? V :
T;
let openingEmojiPicker: AwaitType<ReturnType<typeof popup>> | null = null;
let activeTextarea: HTMLTextAreaElement | HTMLInputElement | null = null;
export async function openEmojiPicker(src?: HTMLElement, opts, initialTextarea: typeof activeTextarea) {
if (openingEmojiPicker) return;
activeTextarea = initialTextarea;
const textareas = document.querySelectorAll('textarea, input');
for (const textarea of Array.from(textareas)) {
textarea.addEventListener('focus', () => {
activeTextarea = textarea;
});
}
const observer = new MutationObserver(records => {
for (const record of records) {
for (const node of Array.from(record.addedNodes).filter(node => node instanceof HTMLElement) as HTMLElement[]) {
const textareas = node.querySelectorAll('textarea, input') as NodeListOf<NonNullable<typeof activeTextarea>>;
for (const textarea of Array.from(textareas).filter(textarea => textarea.dataset.preventEmojiInsert == null)) {
if (document.activeElement === textarea) activeTextarea = textarea;
textarea.addEventListener('focus', () => {
activeTextarea = textarea;
});
}
}
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: false,
characterData: false,
});
openingEmojiPicker = await popup(import('@/components/emoji-picker-window.vue'), {
src,
...opts
}, {
chosen: emoji => {
insertTextAtCursor(activeTextarea, emoji);
},
closed: () => {
openingEmojiPicker!.dispose();
openingEmojiPicker = null;
observer.disconnect();
}
});
}
let reactionPicker = null;
export async function pickReaction(src: HTMLElement, chosen, closed) {
if (reactionPicker) {
reactionPicker.src.value = src;
reactionPicker.manualShowing.value = true;
reactionPicker.chosen = chosen;
reactionPicker.closed = closed;
} else {
reactionPicker = {
src: ref(src),
manualShowing: ref(true),
chosen, closed
};
popup(import('@/components/emoji-picker-dialog.vue'), {
src: reactionPicker.src,
asReactionPicker: true,
manualShowing: reactionPicker.manualShowing
}, {
done: reaction => {
reactionPicker.chosen(reaction);
},
close: () => {
reactionPicker.manualShowing.value = false;
},
closed: () => {
reactionPicker.src.value = null;
reactionPicker.closed();
}
});
}
}
export function modalMenu(items: any[], src?: HTMLElement, options?: { align?: string; viaKeyboard?: boolean }) { export function modalMenu(items: any[], src?: HTMLElement, options?: { align?: string; viaKeyboard?: boolean }) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let dispose; let dispose;

View file

@ -1,5 +1,5 @@
<template> <template>
<div style="overflow: hidden;"> <div style="overflow: hidden; overflow: clip;">
<FormBase class="znqjceqz"> <FormBase class="znqjceqz">
<div id="debug"></div> <div id="debug"></div>
<section class="_formItem about"> <section class="_formItem about">

View file

@ -104,7 +104,8 @@ export default defineComponent({
display: block; display: block;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
margin: 0; margin: 0;
} }
@ -124,7 +125,8 @@ export default defineComponent({
width: 55%; width: 55%;
line-height: 42px; line-height: 42px;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
opacity: 0.7; opacity: 0.7;
font-size: 14px; font-size: 14px;

View file

@ -178,17 +178,20 @@ export default defineComponent({
> .body { > .body {
padding: 0 0 0 8px; padding: 0 0 0 8px;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
> .name { > .name {
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
} }
> .info { > .info {
opacity: 0.5; opacity: 0.5;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
} }
} }
} }
@ -219,17 +222,20 @@ export default defineComponent({
> .body { > .body {
padding: 0 0 0 8px; padding: 0 0 0 8px;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
> .name { > .name {
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
} }
> .info { > .info {
opacity: 0.5; opacity: 0.5;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
} }
} }
} }

View file

@ -226,12 +226,14 @@ export default defineComponent({
align-items: center; align-items: center;
margin-bottom: 2px; margin-bottom: 2px;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
> .name { > .name {
margin: 0; margin: 0;
padding: 0; padding: 0;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
font-size: 1em; font-size: 1em;
font-weight: bold; font-weight: bold;
@ -262,7 +264,8 @@ export default defineComponent({
display: block; display: block;
margin: 0 0 0 0; margin: 0 0 0 0;
padding: 0; padding: 0;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
overflow-wrap: break-word; overflow-wrap: break-word;
font-size: 1.1em; font-size: 1.1em;
color: var(--faceText); color: var(--faceText);

View file

@ -223,9 +223,7 @@ export default defineComponent({
}, },
async insertEmoji(ev) { async insertEmoji(ev) {
os.pickEmoji(ev.currentTarget || ev.target).then(emoji => { os.openEmojiPicker(ev.currentTarget || ev.target, {}, this.$refs.text);
insertTextAtCursor(this.$refs.text, emoji);
});
} }
} }
}); });

View file

@ -154,7 +154,8 @@ export default defineComponent({
display: block; display: block;
margin: 0; margin: 0;
padding: 0; padding: 0;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
overflow-wrap: break-word; overflow-wrap: break-word;
font-size: 1em; font-size: 1em;
color: rgba(#000, 0.5); color: rgba(#000, 0.5);
@ -164,7 +165,8 @@ export default defineComponent({
display: block; display: block;
margin: 0; margin: 0;
padding: 12px 18px; padding: 12px 18px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
overflow-wrap: break-word; overflow-wrap: break-word;
word-break: break-word; word-break: break-word;
font-size: 1em; font-size: 1em;
@ -182,7 +184,8 @@ export default defineComponent({
display: block; display: block;
max-width: 100%; max-width: 100%;
border-radius: 16px; border-radius: 16px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-decoration: none; text-decoration: none;
&:hover { &:hover {

View file

@ -74,7 +74,8 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.cpjygsrt { .cpjygsrt {
position: relative; position: relative;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
background: var(--panel); background: var(--panel);
border: solid 2px var(--X12); border: solid 2px var(--X12);
border-radius: 6px; border-radius: 6px;

View file

@ -434,7 +434,8 @@ export default defineComponent({
> div { > div {
background: transparent; background: transparent;
border-radius: 6px; border-radius: 6px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
* { * {
pointer-events: none; pointer-events: none;

View file

@ -333,7 +333,8 @@ export default defineComponent({
background: transparent; background: transparent;
border: solid 2px var(--divider); border: solid 2px var(--divider);
border-radius: 6px; border-radius: 6px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
cursor: pointer; cursor: pointer;
* { * {

View file

@ -230,7 +230,8 @@ export default defineComponent({
$size: 12px; $size: 12px;
background: rgba(0, 0, 0, 0.1); background: rgba(0, 0, 0, 0.1);
border-radius: ($size / 2); border-radius: ($size / 2);
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
> div { > div {
height: $size; height: $size;

View file

@ -105,7 +105,7 @@ export default defineComponent({
}, },
preview(ev) { preview(ev) {
os.popup(import('@/components/emoji-picker.vue'), { os.popup(import('@/components/emoji-picker-dialog.vue'), {
asReactionPicker: true, asReactionPicker: true,
src: ev.currentTarget || ev.target, src: ev.currentTarget || ev.target,
}, {}, 'closed'); }, {}, 'closed');

View file

@ -144,7 +144,8 @@ export default defineComponent({
flex: 1; flex: 1;
min-width: 0; min-width: 0;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
margin-right: 12px; margin-right: 12px;
} }

View file

@ -184,7 +184,8 @@ export default defineComponent({
position: absolute; position: absolute;
top: 50%; top: 50%;
left: 50%; left: 50%;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
padding: 0 100px; padding: 0 100px;
transform: translate3d(-50%, -50%, 0); transform: translate3d(-50%, -50%, 0);

View file

@ -369,7 +369,8 @@ export default defineComponent({
position: relative; position: relative;
height: 450px; height: 450px;
border-radius: 16px; border-radius: 16px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
background-size: cover; background-size: cover;
background-position: center; background-position: center;
@ -472,7 +473,8 @@ export default defineComponent({
> .name { > .name {
width: 30%; width: 30%;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
font-weight: bold; font-weight: bold;
@ -480,7 +482,8 @@ export default defineComponent({
> .value { > .value {
width: 70%; width: 70%;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
margin: 0; margin: 0;
@ -542,7 +545,8 @@ export default defineComponent({
.ftskorzw.narrow { .ftskorzw.narrow {
max-width: 100vw; max-width: 100vw;
box-sizing: border-box; box-sizing: border-box;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
> .punished { > .punished {
font-size: 0.8em; font-size: 0.8em;
@ -553,12 +557,14 @@ export default defineComponent({
> .main { > .main {
position: relative; position: relative;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
> .banner-container { > .banner-container {
position: relative; position: relative;
height: 250px; height: 250px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
background-size: cover; background-size: cover;
background-position: center; background-position: center;
@ -703,7 +709,8 @@ export default defineComponent({
> .name { > .name {
width: 30%; width: 30%;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
font-weight: bold; font-weight: bold;
@ -712,7 +719,8 @@ export default defineComponent({
> .value { > .value {
width: 70%; width: 70%;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
margin: 0; margin: 0;

View file

@ -167,7 +167,8 @@ export default defineComponent({
margin: auto; margin: auto;
width: 500px; width: 500px;
height: calc(100% - 128px); height: calc(100% - 128px);
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
-webkit-mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%); -webkit-mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%);
mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%); mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%);

View file

@ -151,7 +151,8 @@ export default defineComponent({
margin: auto; margin: auto;
width: 500px; width: 500px;
height: calc(100% - 128px); height: calc(100% - 128px);
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
-webkit-mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%); -webkit-mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%);
mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%); mask-image: linear-gradient(0deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 128px, rgba(0,0,0,1) calc(100% - 128px), rgba(0,0,0,0) 100%);
} }

View file

@ -71,7 +71,8 @@ export default defineComponent({
.mk-setup { .mk-setup {
border-radius: var(--radius); border-radius: var(--radius);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
> h1 { > h1 {
margin: 0; margin: 0;

View file

@ -241,7 +241,8 @@ hr {
border-radius: var(--radius); border-radius: var(--radius);
//border: var(--panelBorder); //border: var(--panelBorder);
box-shadow: var(--panelShadow); box-shadow: var(--panelShadow);
overflow: hidden; overflow: hidden; // overflow: clip; をSafariが対応したら消す
overflow: clip;
} }
._card { ._card {
@ -390,8 +391,8 @@ hr {
._acrylic { ._acrylic {
background: var(--acrylicPanel); background: var(--acrylicPanel);
-webkit-backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(15px);
backdrop-filter: blur(10px); backdrop-filter: blur(15px);
} }
._vMargin { ._vMargin {
@ -457,6 +458,14 @@ hr {
opacity: 0.7; opacity: 0.7;
} }
// TODO: refactor: 全てのvueファイル中の text-overflow: ellipsis; している箇所をこのクラスを使って置き換える
._oneline {
white-space: nowrap;
overflow: hidden; // overflow: clip; をSafariが対応したら消す
overflow: clip;
text-overflow: ellipsis;
}
._monospace { ._monospace {
font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace; font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace;
} }

View file

@ -132,7 +132,8 @@ export default defineComponent({
display: inline-block; display: inline-block;
vertical-align: bottom; vertical-align: bottom;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
padding: 0 16px; padding: 0 16px;
position: relative; position: relative;

View file

@ -89,7 +89,8 @@ export default defineComponent({
font-size: 0.8em; font-size: 0.8em;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
flex-shrink: 1; flex-shrink: 1;
} }
.mk-uploader > ol > li > .top > .name > [data-icon] { .mk-uploader > ol > li > .top > .name > [data-icon] {
@ -119,7 +120,8 @@ export default defineComponent({
background: transparent; background: transparent;
border: none; border: none;
border-radius: 4px; border-radius: 4px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
grid-column: 2/3; grid-column: 2/3;
grid-row: 2/3; grid-row: 2/3;
z-index: 2; z-index: 2;

View file

@ -427,7 +427,8 @@ export default defineComponent({
> .text { > .text {
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
font-size: 0.9em; font-size: 0.9em;
} }
@ -482,7 +483,8 @@ export default defineComponent({
padding: 6px 8px; padding: 6px 8px;
border-radius: 4px; border-radius: 4px;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
&:hover { &:hover {
@ -545,7 +547,8 @@ export default defineComponent({
} }
> .title { > .title {
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
min-width: 0; min-width: 0;
@ -556,7 +559,8 @@ export default defineComponent({
font-size: 0.8em; font-size: 0.8em;
font-weight: normal; font-weight: normal;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
} }

View file

@ -62,7 +62,8 @@ export default defineComponent({
display: block; display: block;
margin: 0 .5em 0 0; margin: 0 .5em 0 0;
padding: 0; padding: 0;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
font-size: 1em; font-size: 1em;
font-weight: bold; font-weight: bold;
text-decoration: none; text-decoration: none;
@ -91,7 +92,8 @@ export default defineComponent({
> .username { > .username {
margin: 0 .5em 0 0; margin: 0 .5em 0 0;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
} }

View file

@ -50,7 +50,8 @@ export default defineComponent({
display: flex; display: flex;
margin: 0; margin: 0;
padding: 0; padding: 0;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
font-size: 0.95em; font-size: 0.95em;
> .avatar { > .avatar {

View file

@ -504,23 +504,14 @@ export default defineComponent({
pleaseLogin(); pleaseLogin();
this.operating = true; this.operating = true;
this.blur(); this.blur();
const { dispose } = await os.popup(import('@/components/emoji-picker.vue'), { os.pickReaction(this.$refs.reactButton, reaction => {
src: this.$refs.reactButton,
asReactionPicker: true
}, {
done: reaction => {
if (reaction) {
os.api('notes/reactions/create', { os.api('notes/reactions/create', {
noteId: this.appearNote.id, noteId: this.appearNote.id,
reaction: reaction reaction: reaction
}); });
} }, () => {
},
closed: () => {
this.operating = false; this.operating = false;
this.focus(); this.focus();
dispose();
}
}); });
}, },
@ -964,7 +955,8 @@ export default defineComponent({
} }
> span { > span {
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
flex-shrink: 1; flex-shrink: 1;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
@ -1037,7 +1029,8 @@ export default defineComponent({
&.collapsed { &.collapsed {
position: relative; position: relative;
max-height: 9em; max-height: 9em;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
> .fade { > .fade {
display: block; display: block;

View file

@ -593,9 +593,7 @@ export default defineComponent({
}, },
async insertEmoji(ev) { async insertEmoji(ev) {
os.pickEmoji(ev.currentTarget || ev.target).then(emoji => { os.openEmojiPicker(ev.currentTarget || ev.target, {}, this.$refs.text);
insertTextAtCursor(this.$refs.text, emoji);
});
}, },
showActions(ev) { showActions(ev) {

View file

@ -268,7 +268,8 @@ export default defineComponent({
--section-padding: 10px; --section-padding: 10px;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
contain: content; contain: content;
&.draghover { &.draghover {
@ -358,7 +359,8 @@ export default defineComponent({
> .header { > .header {
display: inline-block; display: inline-block;
align-items: center; align-items: center;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }

View file

@ -125,7 +125,8 @@ export default defineComponent({
display: inline-block; display: inline-block;
vertical-align: bottom; vertical-align: bottom;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
position: relative; position: relative;
@ -206,7 +207,8 @@ export default defineComponent({
> .title { > .title {
flex: 1; flex: 1;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
position: relative; position: relative;
text-align: center; text-align: center;

View file

@ -171,7 +171,8 @@ export default defineComponent({
> .meter { > .meter {
width: 100%; width: 100%;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
background: var(--X11); background: var(--X11);
border-radius: 8px; border-radius: 8px;

View file

@ -89,7 +89,8 @@ export default defineComponent({
$bodyInfoHieght: 16px; $bodyInfoHieght: 16px;
height: (62px + 1px) + (62px + 1px) + (62px + 1px) + (62px + 1px) + 62px; height: (62px + 1px) + (62px + 1px) + (62px + 1px) + (62px + 1px) + 62px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
> .instances { > .instances {
.chart-move { .chart-move {
@ -113,7 +114,8 @@ export default defineComponent({
> .body { > .body {
flex: 1; flex: 1;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
font-size: 0.9em; font-size: 0.9em;
color: var(--fg); color: var(--fg);
@ -121,7 +123,8 @@ export default defineComponent({
display: block; display: block;
width: 100%; width: 100%;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
line-height: $bodyTitleHieght; line-height: $bodyTitleHieght;
} }

View file

@ -80,7 +80,8 @@ export default defineComponent({
color: var(--fg); color: var(--fg);
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
&:nth-child(even) { &:nth-child(even) {
background: rgba(#000, 0.05); background: rgba(#000, 0.05);

View file

@ -120,7 +120,7 @@ export default defineComponent({
if (this.stats.length > 50) this.stats.shift(); if (this.stats.length > 50) this.stats.shift();
const cpuPolylinePoints = this.stats.map((s, i) => [this.viewBoxX - ((this.stats.length - 1) - i), (1 - s.cpu) * this.viewBoxY]); const cpuPolylinePoints = this.stats.map((s, i) => [this.viewBoxX - ((this.stats.length - 1) - i), (1 - s.cpu) * this.viewBoxY]);
const memPolylinePoints = this.stats.map((s, i) => [this.viewBoxX - ((this.stats.length - 1) - i), (1 - (s.mem.used / this.meta.mem.total)) * this.viewBoxY]); const memPolylinePoints = this.stats.map((s, i) => [this.viewBoxX - ((this.stats.length - 1) - i), (1 - (s.mem.active / this.meta.mem.total)) * this.viewBoxY]);
this.cpuPolylinePoints = cpuPolylinePoints.map(xy => `${xy[0]},${xy[1]}`).join(' '); this.cpuPolylinePoints = cpuPolylinePoints.map(xy => `${xy[0]},${xy[1]}`).join(' ');
this.memPolylinePoints = memPolylinePoints.map(xy => `${xy[0]},${xy[1]}`).join(' '); this.memPolylinePoints = memPolylinePoints.map(xy => `${xy[0]},${xy[1]}`).join(' ');
@ -133,7 +133,7 @@ export default defineComponent({
this.memHeadY = memPolylinePoints[memPolylinePoints.length - 1][1]; this.memHeadY = memPolylinePoints[memPolylinePoints.length - 1][1];
this.cpuP = (stats.cpu * 100).toFixed(0); this.cpuP = (stats.cpu * 100).toFixed(0);
this.memP = (stats.mem.used / this.meta.mem.total * 100).toFixed(0); this.memP = (stats.mem.active / this.meta.mem.total * 100).toFixed(0);
}, },
onStatsLog(statsLog) { onStatsLog(statsLog) {
for (const stats of [...statsLog].reverse()) { for (const stats of [...statsLog].reverse()) {

View file

@ -45,10 +45,10 @@ export default defineComponent({
}, },
methods: { methods: {
onStats(stats) { onStats(stats) {
this.usage = stats.mem.used / this.meta.mem.total; this.usage = stats.mem.active / this.meta.mem.total;
this.total = this.meta.mem.total; this.total = this.meta.mem.total;
this.used = stats.mem.used; this.used = stats.mem.active;
this.free = this.meta.mem.total - stats.mem.used; this.free = this.meta.mem.total - stats.mem.active;
}, },
bytes bytes
} }

View file

@ -68,7 +68,8 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.wbrkwala { .wbrkwala {
height: (62px + 1px) + (62px + 1px) + (62px + 1px) + (62px + 1px) + 62px; height: (62px + 1px) + (62px + 1px) + (62px + 1px) + (62px + 1px) + 62px;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
> .tags { > .tags {
.chart-move { .chart-move {
@ -83,7 +84,8 @@ export default defineComponent({
> .tag { > .tag {
flex: 1; flex: 1;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
font-size: 0.9em; font-size: 0.9em;
color: var(--fg); color: var(--fg);
@ -91,7 +93,8 @@ export default defineComponent({
display: block; display: block;
width: 100%; width: 100%;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden; // overflow: clip; Safari
overflow: clip;
text-overflow: ellipsis; text-overflow: ellipsis;
line-height: 18px; line-height: 18px;
} }

View file

@ -28,7 +28,7 @@ export default function() {
const stats = { const stats = {
cpu: roundCpu(cpu), cpu: roundCpu(cpu),
mem: { mem: {
used: round(memStats.used), used: round(memStats.used - memStats.buffers - memStats.cached),
active: round(memStats.active), active: round(memStats.active),
}, },
net: { net: {

View file

@ -20,9 +20,10 @@ window.onerror = (e) => {
const v = localStorage.getItem('v') || VERSION; const v = localStorage.getItem('v') || VERSION;
//#region Detect language & fetch translations //#region Detect language & fetch translations
if (localStorage.hasOwnProperty('locale')) { const localeVersion = localStorage.getItem('localeVersion');
// TODO: 非同期でlocaleの更新処理をする const localeOutdated = (localeVersion == null || localeVersion !== v);
} else {
if (!localStorage.hasOwnProperty('locale') || localeOutdated) {
const supportedLangs = LANGS; const supportedLangs = LANGS;
let lang = localStorage.getItem('lang'); let lang = localStorage.getItem('lang');
if (lang == null || !supportedLangs.includes(lang)) { if (lang == null || !supportedLangs.includes(lang)) {
@ -39,6 +40,7 @@ window.onerror = (e) => {
const res = await fetch(`/assets/locales/${lang}.${v}.json`); const res = await fetch(`/assets/locales/${lang}.${v}.json`);
localStorage.setItem('lang', lang); localStorage.setItem('lang', lang);
localStorage.setItem('locale', await res.text()); localStorage.setItem('locale', await res.text());
localStorage.setItem('localeVersion', v);
} }
//#endregion //#endregion

View file

@ -94,7 +94,7 @@ export default class Logger {
level === 'info' ? this.syslogClient.info : level === 'info' ? this.syslogClient.info :
null as never; null as never;
send.bind(this.syslogClient)(message); send.bind(this.syslogClient)(message).catch(() => {});
} else { } else {
const Logs = getRepository(Log); const Logs = getRepository(Log);
Logs.insert({ Logs.insert({
@ -106,7 +106,7 @@ export default class Logger {
level: level, level: level,
message: message.substr(0, 1000), // 1024を超えるとログが挿入できずエラーになり無限ループする message: message.substr(0, 1000), // 1024を超えるとログが挿入できずエラーになり無限ループする
data: data, data: data,
} as Log); } as Log).catch(() => {});
} }
} }
} }
@ -116,8 +116,10 @@ export default class Logger {
data = data || {}; data = data || {};
data.e = x; data.e = x;
this.log('error', x.toString(), data, important); this.log('error', x.toString(), data, important);
} else if (typeof x === 'object') {
this.log('error', `${(x as any).message || (x as any).name || x}`, data, important);
} else { } else {
this.log('error', x, data, important); this.log('error', `${x}`, data, important);
} }
} }

View file

@ -492,10 +492,10 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/chai@4.2.14": "@types/chai@4.2.15":
version "4.2.14" version "4.2.15"
resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.14.tgz#44d2dd0b5de6185089375d976b4ec5caf6861193" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.15.tgz#b7a6d263c2cecf44b6de9a051cf496249b154553"
integrity sha512-G+ITQPXkwTrslfG5L/BksmbLUA0M1iybEsmCWPqzSxsRRhJZimBKJkoMi8fr/CPygPTj4zO5pJH7I2/cm9M7SQ== integrity sha512-rYff6FI+ZTKAPkJUoyz7Udq3GaoDZnxYDEvdEdFZASiA7PoErltHezDishqQiSDWrGxvxmplH304jyzQmjp0AQ==
"@types/cheerio@^0.22.10": "@types/cheerio@^0.22.10":
version "0.22.18" version "0.22.18"
@ -2140,17 +2140,7 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6:
caniuse-db "^1.0.30000639" caniuse-db "^1.0.30000639"
electron-to-chromium "^1.2.7" electron-to-chromium "^1.2.7"
browserslist@^4.0.0, browserslist@^4.14.5: browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.3:
version "4.14.5"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.5.tgz#1c751461a102ddc60e40993639b709be7f2c4015"
integrity sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA==
dependencies:
caniuse-lite "^1.0.30001135"
electron-to-chromium "^1.3.571"
escalade "^3.1.0"
node-releases "^1.1.61"
browserslist@^4.16.3:
version "4.16.3" version "4.16.3"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.3.tgz#340aa46940d7db878748567c5dea24a48ddf3717" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.3.tgz#340aa46940d7db878748567c5dea24a48ddf3717"
integrity sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw== integrity sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==
@ -2385,11 +2375,6 @@ caniuse-lite@^1.0.0:
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001048.tgz#4bb4f1bc2eb304e5e1154da80b93dee3f1cf447e" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001048.tgz#4bb4f1bc2eb304e5e1154da80b93dee3f1cf447e"
integrity sha512-g1iSHKVxornw0K8LG9LLdf+Fxnv7T1Z+mMsf0/YYLclQX4Cd522Ap0Lrw6NFqHgezit78dtyWxzlV2Xfc7vgRg== integrity sha512-g1iSHKVxornw0K8LG9LLdf+Fxnv7T1Z+mMsf0/YYLclQX4Cd522Ap0Lrw6NFqHgezit78dtyWxzlV2Xfc7vgRg==
caniuse-lite@^1.0.30001135:
version "1.0.30001142"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001142.tgz#a8518fdb5fee03ad95ac9f32a9a1e5999469c250"
integrity sha512-pDPpn9ankEpBFZXyCv2I4lh1v/ju+bqb78QfKf+w9XgDAFWBwSYPswXqprRdrgQWK0wQnpIbfwRjNHO1HWqvoQ==
caniuse-lite@^1.0.30001181: caniuse-lite@^1.0.30001181:
version "1.0.30001191" version "1.0.30001191"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001191.tgz#bacb432b6701f690c8c5f7c680166b9a9f0843d9" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001191.tgz#bacb432b6701f690c8c5f7c680166b9a9f0843d9"
@ -3757,11 +3742,6 @@ electron-to-chromium@^1.2.7:
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.633.tgz#16dd5aec9de03894e8d14a1db4cda8a369b9b7fe" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.633.tgz#16dd5aec9de03894e8d14a1db4cda8a369b9b7fe"
integrity sha512-bsVCsONiVX1abkWdH7KtpuDAhsQ3N3bjPYhROSAXE78roJKet0Y5wznA14JE9pzbwSZmSMAW6KiKYf1RvbTJkA== integrity sha512-bsVCsONiVX1abkWdH7KtpuDAhsQ3N3bjPYhROSAXE78roJKet0Y5wznA14JE9pzbwSZmSMAW6KiKYf1RvbTJkA==
electron-to-chromium@^1.3.571:
version "1.3.576"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.576.tgz#2e70234484e03d7c7e90310d7d79fd3775379c34"
integrity sha512-uSEI0XZ//5ic+0NdOqlxp0liCD44ck20OAGyLMSymIWTEAtHKVJi6JM18acOnRgUgX7Q65QqnI+sNncNvIy8ew==
electron-to-chromium@^1.3.649: electron-to-chromium@^1.3.649:
version "1.3.672" version "1.3.672"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.672.tgz#3a6e335016dab4bc584d5292adc4f98f54541f6a" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.672.tgz#3a6e335016dab4bc584d5292adc4f98f54541f6a"
@ -3879,10 +3859,10 @@ es-abstract@^1.17.0-next.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-
string.prototype.trimleft "^2.1.1" string.prototype.trimleft "^2.1.1"
string.prototype.trimright "^2.1.1" string.prototype.trimright "^2.1.1"
es-module-lexer@^0.3.26: es-module-lexer@^0.4.0:
version "0.3.26" version "0.4.0"
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.3.26.tgz#7b507044e97d5b03b01d4392c74ffeb9c177a83b" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.4.0.tgz#21f4181cc8b7eee06855f1c59e6087c7bc4f77b0"
integrity sha512-Va0Q/xqtrss45hWzP8CZJwzGSZJjDM5/MJRE3IXXnUCcVLElR9BRaE9F62BopysASyc4nM3uwhSW7FFB9nlWAA== integrity sha512-iuEGihqqhKWFgh72Q/Jtch7V2t/ft8w8IPP2aEN8ArYKO+IWyo6hsi96hCdgyeEDQIV3InhYQ9BlwUFPGXrbEQ==
es-to-primitive@^1.2.1: es-to-primitive@^1.2.1:
version "1.2.1" version "1.2.1"
@ -3934,11 +3914,6 @@ es6-weak-map@^2.0.1:
es6-iterator "^2.0.3" es6-iterator "^2.0.3"
es6-symbol "^3.1.1" es6-symbol "^3.1.1"
escalade@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.0.tgz#e8e2d7c7a8b76f6ee64c2181d6b8151441602d4e"
integrity sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig==
escalade@^3.1.1: escalade@^3.1.1:
version "3.1.1" version "3.1.1"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
@ -7015,20 +6990,15 @@ node-object-hash@^1.2.0:
resolved "https://registry.yarnpkg.com/node-object-hash/-/node-object-hash-1.4.2.tgz#385833d85b229902b75826224f6077be969a9e94" resolved "https://registry.yarnpkg.com/node-object-hash/-/node-object-hash-1.4.2.tgz#385833d85b229902b75826224f6077be969a9e94"
integrity sha512-UdS4swXs85fCGWWf6t6DMGgpN/vnlKeSGEQ7hJcrs7PBFoxoKLmibc3QRb7fwiYsjdL7PX8iI/TMSlZ90dgHhQ== integrity sha512-UdS4swXs85fCGWWf6t6DMGgpN/vnlKeSGEQ7hJcrs7PBFoxoKLmibc3QRb7fwiYsjdL7PX8iI/TMSlZ90dgHhQ==
node-releases@^1.1.61:
version "1.1.61"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.61.tgz#707b0fca9ce4e11783612ba4a2fcba09047af16e"
integrity sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==
node-releases@^1.1.70: node-releases@^1.1.70:
version "1.1.71" version "1.1.71"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb"
integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg== integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==
nodemailer@6.4.18: nodemailer@6.5.0:
version "6.4.18" version "6.5.0"
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.4.18.tgz#2788c85792844fc17befda019031609017f4b9a1" resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.5.0.tgz#d12c28d8d48778918e25f1999d97910231b175d9"
integrity sha512-ht9cXxQ+lTC+t00vkSIpKHIyM4aXIsQ1tcbQCn5IOnxYHi81W2XOaU66EQBFFpbtzLEBTC94gmkbD4mGZQzVpA== integrity sha512-Tm4RPrrIZbnqDKAvX+/4M+zovEReiKlEXWDzG4iwtpL9X34MJY+D5LnQPH/+eghe8DLlAVshHAJZAZWBGhkguw==
nofilter@^2.0.0: nofilter@^2.0.0:
version "2.0.0" version "2.0.0"
@ -11129,10 +11099,10 @@ webpack-sources@^2.1.1:
source-list-map "^2.0.1" source-list-map "^2.0.1"
source-map "^0.6.1" source-map "^0.6.1"
webpack@5.23.0: webpack@5.24.2:
version "5.23.0" version "5.24.2"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.23.0.tgz#9ed57e9a54b267b3549899271ad780cddc6ee316" resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.24.2.tgz#33790dad631e8b639f4246d762e257720875fe54"
integrity sha512-RC6dwDuRxiU75F8XC4H08NtzUrMfufw5LDnO8dTtaKU2+fszEdySCgZhNwSBBn516iNaJbQI7T7OPHIgCwcJmg== integrity sha512-uxxKYEY4kMNjP+D2Y+8aw5Vd7ar4pMuKCNemxV26ysr1nk0YDiQTylg9U3VZIdkmI0YHa0uC8ABxL+uGxGWWJg==
dependencies: dependencies:
"@types/eslint-scope" "^3.7.0" "@types/eslint-scope" "^3.7.0"
"@types/estree" "^0.0.46" "@types/estree" "^0.0.46"
@ -11143,7 +11113,7 @@ webpack@5.23.0:
browserslist "^4.14.5" browserslist "^4.14.5"
chrome-trace-event "^1.0.2" chrome-trace-event "^1.0.2"
enhanced-resolve "^5.7.0" enhanced-resolve "^5.7.0"
es-module-lexer "^0.3.26" es-module-lexer "^0.4.0"
eslint-scope "^5.1.1" eslint-scope "^5.1.1"
events "^3.2.0" events "^3.2.0"
glob-to-regexp "^0.4.1" glob-to-regexp "^0.4.1"
@ -11381,14 +11351,14 @@ xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1:
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
y18n@^3.2.1: y18n@^3.2.1:
version "3.2.1" version "3.2.2"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696"
integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==
y18n@^4.0.0: y18n@^4.0.0:
version "4.0.0" version "4.0.1"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4"
integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==
y18n@^5.0.5: y18n@^5.0.5:
version "5.0.5" version "5.0.5"