Merge branch 'develop'

This commit is contained in:
syuilo 2021-04-16 00:21:56 +09:00
commit 5e1d17dff2
19 changed files with 229 additions and 170 deletions

View file

@ -717,6 +717,8 @@ unlikeConfirm: "いいね解除しますか?"
fullView: "フルビュー" fullView: "フルビュー"
quitFullView: "フルビュー解除" quitFullView: "フルビュー解除"
addDescription: "説明を追加" addDescription: "説明を追加"
userPagePinTip: "個々のノートのメニューから「ピン留め」を選択することで、ここにノートを表示しておくことができます。"
notSpecifiedMentionWarning: "宛先に含まれていないメンションがあります"
_email: _email:
_follow: _follow:

View file

@ -1,7 +1,7 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <syuilotan@yahoo.co.jp>", "author": "syuilo <syuilotan@yahoo.co.jp>",
"version": "12.76.0", "version": "12.76.1",
"codename": "indigo", "codename": "indigo",
"repository": { "repository": {
"type": "git", "type": "git",
@ -181,7 +181,7 @@
"markdown-it": "12.0.4", "markdown-it": "12.0.4",
"markdown-it-anchor": "7.1.0", "markdown-it-anchor": "7.1.0",
"matter-js": "0.16.1", "matter-js": "0.16.1",
"mfm-js": "0.14.0", "mfm-js": "0.15.0",
"mocha": "8.3.2", "mocha": "8.3.2",
"moji": "0.5.1", "moji": "0.5.1",
"ms": "2.1.3", "ms": "2.1.3",

View file

@ -24,11 +24,9 @@ export default defineComponent({
methods: { methods: {
focus() { focus() {
this.$slots.default[0].elm.focus(); this.$slots.default[0].elm.focus();
}
}, },
render() { getDateText(time: string) {
const getDateText = (time: string) => {
const date = new Date(time).getDate(); const date = new Date(time).getDate();
const month = new Date(time).getMonth() + 1; const month = new Date(time).getMonth() + 1;
return this.$t('monthAndDay', { return this.$t('monthAndDay', {
@ -36,9 +34,13 @@ export default defineComponent({
day: date.toString() day: date.toString()
}); });
} }
},
render() {
const noGap = [...document.querySelectorAll('._noGap_')].some(el => el.contains(this.$parent.$el)); const noGap = [...document.querySelectorAll('._noGap_')].some(el => el.contains(this.$parent.$el));
if (this.items.length === 0) return;
return h(this.$store.state.animation ? TransitionGroup : 'div', this.$store.state.animation ? { return h(this.$store.state.animation ? TransitionGroup : 'div', this.$store.state.animation ? {
class: 'sqadhkmv' + (noGap ? ' _block' : ''), class: 'sqadhkmv' + (noGap ? ' _block' : ''),
name: 'list', name: 'list',
@ -72,10 +74,10 @@ export default defineComponent({
class: 'icon', class: 'icon',
icon: faAngleUp, icon: faAngleUp,
}), }),
getDateText(item.createdAt) this.getDateText(item.createdAt)
]), ]),
h('span', [ h('span', [
getDateText(this.items[i + 1].createdAt), this.getDateText(this.items[i + 1].createdAt),
h(FontAwesomeIcon, { h(FontAwesomeIcon, {
class: 'icon', class: 'icon',
icon: faAngleDown, icon: faAngleDown,

View file

@ -58,10 +58,13 @@ export default defineComponent({
const text = token.props.text.replace(/(\r\n|\n|\r)/g, '\n'); const text = token.props.text.replace(/(\r\n|\n|\r)/g, '\n');
if (!this.plain) { if (!this.plain) {
const x = text.split('\n') const res = [];
.map(t => t == '' ? [h('br')] : [t, h('br')]); for (const t of text.split('\n')) {
x[x.length - 1].pop(); res.push(h('br'));
return x; res.push(t);
}
res.shift();
return res;
} else { } else {
return [text.replace(/\n/g, ' ')]; return [text.replace(/\n/g, ' ')];
} }

View file

@ -1,7 +1,6 @@
<template> <template>
<div class="mfcuwfyp _noGap_"> <div class="mfcuwfyp _noGap_ _magnetParent">
<div class="_magnet"></div> <XList class="notifications _magnetChild" :items="items" v-slot="{ item: notification }">
<XList class="notifications" :items="items" v-slot="{ item: notification }">
<XNote v-if="['reply', 'quote', 'mention'].includes(notification.type)" :note="notification.note" @update:note="noteUpdated(notification.note, $event)" :key="notification.id"/> <XNote v-if="['reply', 'quote', 'mention'].includes(notification.type)" :note="notification.note" @update:note="noteUpdated(notification.note, $event)" :key="notification.id"/>
<XNotification v-else :notification="notification" :with-time="true" :full="true" class="_panel notification" :key="notification.id"/> <XNotification v-else :notification="notification" :with-time="true" :full="true" class="_panel notification" :key="notification.id"/>
</XList> </XList>

View file

@ -34,6 +34,7 @@
<button @click="addVisibleUser" class="_buttonPrimary"><Fa :icon="faPlus" fixed-width/></button> <button @click="addVisibleUser" class="_buttonPrimary"><Fa :icon="faPlus" fixed-width/></button>
</div> </div>
</div> </div>
<MkInfo warn v-if="hasNotSpecifiedMentions" class="hasNotSpecifiedMentions">{{ $ts.notSpecifiedMentionWarning }} - <button class="_textButton" @click="addMissingMention()">{{ $ts.add }}</button></MkInfo>
<input v-show="useCw" ref="cw" class="cw" v-model="cw" :placeholder="$ts.annotation" @keydown="onKeydown"> <input v-show="useCw" ref="cw" class="cw" v-model="cw" :placeholder="$ts.annotation" @keydown="onKeydown">
<textarea v-model="text" class="text" :class="{ withCw: useCw }" ref="text" :disabled="posting" :placeholder="placeholder" @keydown="onKeydown" @paste="onPaste" @compositionupdate="onCompositionUpdate" @compositionend="onCompositionEnd" /> <textarea v-model="text" class="text" :class="{ withCw: useCw }" ref="text" :disabled="posting" :placeholder="placeholder" @keydown="onKeydown" @paste="onPaste" @compositionupdate="onCompositionUpdate" @compositionend="onCompositionEnd" />
<XPostFormAttaches class="attaches" :files="files" @updated="updateFiles" @detach="detachFile" @changeSensitive="updateFileSensitive" @changeName="updateFileName"/> <XPostFormAttaches class="attaches" :files="files" @updated="updateFiles" @detach="detachFile" @changeSensitive="updateFileSensitive" @changeName="updateFileName"/>
@ -71,12 +72,14 @@ import { selectFile } from '@client/scripts/select-file';
import { notePostInterruptors, postFormActions } from '@client/store'; import { notePostInterruptors, postFormActions } from '@client/store';
import { isMobile } from '@client/scripts/is-mobile'; import { isMobile } from '@client/scripts/is-mobile';
import { throttle } from 'throttle-debounce'; import { throttle } from 'throttle-debounce';
import MkInfo from '@client/components/ui/info.vue';
export default defineComponent({ export default defineComponent({
components: { components: {
XNotePreview, XNotePreview,
XPostFormAttaches: defineAsyncComponent(() => import('./post-form-attaches.vue')), XPostFormAttaches: defineAsyncComponent(() => import('./post-form-attaches.vue')),
XPollEditor: defineAsyncComponent(() => import('./poll-editor.vue')) XPollEditor: defineAsyncComponent(() => import('./poll-editor.vue')),
MkInfo,
}, },
inject: ['modal'], inject: ['modal'],
@ -143,6 +146,7 @@ export default defineComponent({
autocomplete: null, autocomplete: null,
draghover: false, draghover: false,
quoteId: null, quoteId: null,
hasNotSpecifiedMentions: false,
recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]'), recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]'),
imeText: '', imeText: '',
typing: throttle(3000, () => { typing: throttle(3000, () => {
@ -214,6 +218,18 @@ export default defineComponent({
} }
}, },
watch: {
text() {
this.checkMissingMention();
},
visibleUsers: {
handler() {
this.checkMissingMention();
},
deep: true
}
},
mounted() { mounted() {
if (this.initialText) { if (this.initialText) {
this.text = this.initialText; this.text = this.initialText;
@ -338,6 +354,32 @@ export default defineComponent({
this.$watch('localOnly', () => this.saveDraft()); this.$watch('localOnly', () => this.saveDraft());
}, },
checkMissingMention() {
if (this.visibility === 'specified') {
const ast = mfm.parse(this.text);
for (const x of extractMentions(ast)) {
if (!this.visibleUsers.some(u => (u.username === x.username) && (u.host == x.host))) {
this.hasNotSpecifiedMentions = true;
return;
}
}
this.hasNotSpecifiedMentions = false;
}
},
addMissingMention() {
const ast = mfm.parse(this.text);
for (const x of extractMentions(ast)) {
if (!this.visibleUsers.some(u => (u.username === x.username) && (u.host == x.host))) {
os.api('users/show', { username: x.username, host: x.host }).then(user => {
this.visibleUsers.push(user);
});
}
}
},
togglePoll() { togglePoll() {
if (this.poll) { if (this.poll) {
this.poll = null; this.poll = null;
@ -741,6 +783,10 @@ export default defineComponent({
} }
} }
> .hasNotSpecifiedMentions {
margin: 0 20px 16px 20px;
}
> .cw, > .cw,
> .text { > .text {
display: block; display: block;

View file

@ -85,6 +85,8 @@ export default defineComponent({
display: flex; display: flex;
> .avatar { > .avatar {
position: sticky;
top: calc(var(--stickyTop, 0px) + 16px);
display: block; display: block;
width: 54px; width: 54px;
height: 54px; height: 54px;
@ -274,6 +276,11 @@ export default defineComponent({
background: $me-balloon-color; background: $me-balloon-color;
text-align: left; text-align: left;
::selection {
color: var(--accent);
background-color: #fff;
}
&.noText { &.noText {
background: transparent; background: transparent;
} }

View file

@ -1,265 +1,261 @@
<template> <template>
<div class="mwysmxbg"> <div class="mwysmxbg">
<div class="_section"> <div class="_isolated">{{ $ts._mfm.intro }}</div>
<div class="_content"> <div class="section _block">
<p>{{ $ts._mfm.intro }}</p> <div class="title">{{ $ts._mfm.mention }}</div>
</div> <div class="content">
</div>
<div class="_section">
<div class="_title">{{ $ts._mfm.mention }}</div>
<div class="_content">
<p>{{ $ts._mfm.mentionDescription }}</p> <p>{{ $ts._mfm.mentionDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_mention"/> <Mfm :text="preview_mention"/>
<MkTextarea v-model:value="preview_mention"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_mention"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.hashtag }}</div> <div class="title">{{ $ts._mfm.hashtag }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.hashtagDescription }}</p> <p>{{ $ts._mfm.hashtagDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_hashtag"/> <Mfm :text="preview_hashtag"/>
<MkTextarea v-model:value="preview_hashtag"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_hashtag"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.url }}</div> <div class="title">{{ $ts._mfm.url }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.urlDescription }}</p> <p>{{ $ts._mfm.urlDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_url"/> <Mfm :text="preview_url"/>
<MkTextarea v-model:value="preview_url"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_url"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.link }}</div> <div class="title">{{ $ts._mfm.link }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.linkDescription }}</p> <p>{{ $ts._mfm.linkDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_link"/> <Mfm :text="preview_link"/>
<MkTextarea v-model:value="preview_link"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_link"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.emoji }}</div> <div class="title">{{ $ts._mfm.emoji }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.emojiDescription }}</p> <p>{{ $ts._mfm.emojiDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_emoji"/> <Mfm :text="preview_emoji"/>
<MkTextarea v-model:value="preview_emoji"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_emoji"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.bold }}</div> <div class="title">{{ $ts._mfm.bold }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.boldDescription }}</p> <p>{{ $ts._mfm.boldDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_bold"/> <Mfm :text="preview_bold"/>
<MkTextarea v-model:value="preview_bold"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_bold"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.small }}</div> <div class="title">{{ $ts._mfm.small }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.smallDescription }}</p> <p>{{ $ts._mfm.smallDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_small"/> <Mfm :text="preview_small"/>
<MkTextarea v-model:value="preview_small"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_small"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.quote }}</div> <div class="title">{{ $ts._mfm.quote }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.quoteDescription }}</p> <p>{{ $ts._mfm.quoteDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_quote"/> <Mfm :text="preview_quote"/>
<MkTextarea v-model:value="preview_quote"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_quote"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.center }}</div> <div class="title">{{ $ts._mfm.center }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.centerDescription }}</p> <p>{{ $ts._mfm.centerDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_center"/> <Mfm :text="preview_center"/>
<MkTextarea v-model:value="preview_center"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_center"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.inlineCode }}</div> <div class="title">{{ $ts._mfm.inlineCode }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.inlineCodeDescription }}</p> <p>{{ $ts._mfm.inlineCodeDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_inlineCode"/> <Mfm :text="preview_inlineCode"/>
<MkTextarea v-model:value="preview_inlineCode"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_inlineCode"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.blockCode }}</div> <div class="title">{{ $ts._mfm.blockCode }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.blockCodeDescription }}</p> <p>{{ $ts._mfm.blockCodeDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_blockCode"/> <Mfm :text="preview_blockCode"/>
<MkTextarea v-model:value="preview_blockCode"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_blockCode"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.inlineMath }}</div> <div class="title">{{ $ts._mfm.inlineMath }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.inlineMathDescription }}</p> <p>{{ $ts._mfm.inlineMathDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_inlineMath"/> <Mfm :text="preview_inlineMath"/>
<MkTextarea v-model:value="preview_inlineMath"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_inlineMath"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.search }}</div> <div class="title">{{ $ts._mfm.search }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.searchDescription }}</p> <p>{{ $ts._mfm.searchDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_search"/> <Mfm :text="preview_search"/>
<MkTextarea v-model:value="preview_search"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_search"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.flip }}</div> <div class="title">{{ $ts._mfm.flip }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.flipDescription }}</p> <p>{{ $ts._mfm.flipDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_flip"/> <Mfm :text="preview_flip"/>
<MkTextarea v-model:value="preview_flip"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_flip"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.font }}</div> <div class="title">{{ $ts._mfm.font }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.fontDescription }}</p> <p>{{ $ts._mfm.fontDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_font"/> <Mfm :text="preview_font"/>
<MkTextarea v-model:value="preview_font"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_font"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.x2 }}</div> <div class="title">{{ $ts._mfm.x2 }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.x2Description }}</p> <p>{{ $ts._mfm.x2Description }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_x2"/> <Mfm :text="preview_x2"/>
<MkTextarea v-model:value="preview_x2"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_x2"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.x3 }}</div> <div class="title">{{ $ts._mfm.x3 }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.x3Description }}</p> <p>{{ $ts._mfm.x3Description }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_x3"/> <Mfm :text="preview_x3"/>
<MkTextarea v-model:value="preview_x3"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_x3"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.x4 }}</div> <div class="title">{{ $ts._mfm.x4 }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.x4Description }}</p> <p>{{ $ts._mfm.x4Description }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_x4"/> <Mfm :text="preview_x4"/>
<MkTextarea v-model:value="preview_x4"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_x4"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.blur }}</div> <div class="title">{{ $ts._mfm.blur }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.blurDescription }}</p> <p>{{ $ts._mfm.blurDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_blur"/> <Mfm :text="preview_blur"/>
<MkTextarea v-model:value="preview_blur"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_blur"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.jelly }}</div> <div class="title">{{ $ts._mfm.jelly }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.jellyDescription }}</p> <p>{{ $ts._mfm.jellyDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_jelly"/> <Mfm :text="preview_jelly"/>
<MkTextarea v-model:value="preview_jelly"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_jelly"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.tada }}</div> <div class="title">{{ $ts._mfm.tada }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.tadaDescription }}</p> <p>{{ $ts._mfm.tadaDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_tada"/> <Mfm :text="preview_tada"/>
<MkTextarea v-model:value="preview_tada"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_tada"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.jump }}</div> <div class="title">{{ $ts._mfm.jump }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.jumpDescription }}</p> <p>{{ $ts._mfm.jumpDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_jump"/> <Mfm :text="preview_jump"/>
<MkTextarea v-model:value="preview_jump"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_jump"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.bounce }}</div> <div class="title">{{ $ts._mfm.bounce }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.bounceDescription }}</p> <p>{{ $ts._mfm.bounceDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_bounce"/> <Mfm :text="preview_bounce"/>
<MkTextarea v-model:value="preview_bounce"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_bounce"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.spin }}</div> <div class="title">{{ $ts._mfm.spin }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.spinDescription }}</p> <p>{{ $ts._mfm.spinDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_spin"/> <Mfm :text="preview_spin"/>
<MkTextarea v-model:value="preview_spin"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_spin"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.shake }}</div> <div class="title">{{ $ts._mfm.shake }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.shakeDescription }}</p> <p>{{ $ts._mfm.shakeDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_shake"/> <Mfm :text="preview_shake"/>
<MkTextarea v-model:value="preview_shake"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_shake"><span>MFM</span></MkTextarea>
</div> </div>
</div> </div>
</div> </div>
<div class="_section"> <div class="section _block">
<div class="_title">{{ $ts._mfm.twitch }}</div> <div class="title">{{ $ts._mfm.twitch }}</div>
<div class="_content"> <div class="content">
<p>{{ $ts._mfm.twitchDescription }}</p> <p>{{ $ts._mfm.twitchDescription }}</p>
<div class="preview _panel"> <div class="preview">
<Mfm :text="preview_twitch"/> <Mfm :text="preview_twitch"/>
<MkTextarea v-model:value="preview_twitch"><span>MFM</span></MkTextarea> <MkTextarea v-model:value="preview_twitch"><span>MFM</span></MkTextarea>
</div> </div>
@ -318,8 +314,29 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.mwysmxbg { .mwysmxbg {
.preview { > .section {
> .title {
position: sticky;
z-index: 1;
top: var(--stickyTop, 0px);
padding: 16px; padding: 16px;
font-weight: bold;
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: var(--X16);
}
> .content {
> p {
margin: 0;
padding: 16px;
}
> .preview {
border-top: solid 0.5px var(--divider);
padding: 16px;
}
}
} }
} }
</style> </style>

View file

@ -1,8 +1,6 @@
<template> <template>
<div class="xcukqgmh _root" v-if="page" :key="page.id" v-size="{ max: [450] }"> <div class="xcukqgmh _root _magnetParent" v-if="page" :key="page.id" v-size="{ max: [450] }">
<div class="_magnet"></div> <div class="_block _magnetChild main">
<div class="_block main">
<!-- <!--
<div class="header"> <div class="header">
<h1>{{ page.title }}</h1> <h1>{{ page.title }}</h1>

View file

@ -1,6 +1,5 @@
<template> <template>
<FormBase> <FormBase>
<FormSwitch v-model:value="titlebar">{{ $ts.showTitlebar }}</FormSwitch>
<FormSwitch v-model:value="showFixedPostForm">{{ $ts.showFixedPostForm }}</FormSwitch> <FormSwitch v-model:value="showFixedPostForm">{{ $ts.showFixedPostForm }}</FormSwitch>
<FormSelect v-model:value="lang"> <FormSelect v-model:value="lang">
@ -137,7 +136,6 @@ export default defineComponent({
useOsNativeEmojis: defaultStore.makeGetterSetter('useOsNativeEmojis'), useOsNativeEmojis: defaultStore.makeGetterSetter('useOsNativeEmojis'),
disableShowingAnimatedImages: defaultStore.makeGetterSetter('disableShowingAnimatedImages'), disableShowingAnimatedImages: defaultStore.makeGetterSetter('disableShowingAnimatedImages'),
loadRawImages: defaultStore.makeGetterSetter('loadRawImages'), loadRawImages: defaultStore.makeGetterSetter('loadRawImages'),
titlebar: defaultStore.makeGetterSetter('titlebar'),
imageNewTab: defaultStore.makeGetterSetter('imageNewTab'), imageNewTab: defaultStore.makeGetterSetter('imageNewTab'),
nsfw: defaultStore.makeGetterSetter('nsfw'), nsfw: defaultStore.makeGetterSetter('nsfw'),
disablePagesScript: defaultStore.makeGetterSetter('disablePagesScript'), disablePagesScript: defaultStore.makeGetterSetter('disablePagesScript'),
@ -182,10 +180,6 @@ export default defineComponent({
this.reloadAsk(); this.reloadAsk();
}, },
titlebar() {
this.reloadAsk();
},
instanceTicker() { instanceTicker() {
this.reloadAsk(); this.reloadAsk();
}, },

View file

@ -1,11 +1,10 @@
<template> <template>
<div class="cmuxhskf _root" v-hotkey.global="keymap"> <div class="cmuxhskf _root _magnetParent" v-hotkey.global="keymap">
<div class="new" v-if="queue > 0" :style="{ width: width + 'px' }"><button class="_buttonPrimary" @click="top()">{{ $ts.newNoteRecived }}</button></div> <div class="new" v-if="queue > 0"><button class="_buttonPrimary" @click="top()">{{ $ts.newNoteRecived }}</button></div>
<div class="_magnet"></div>
<XTutorial v-if="$store.reactiveState.tutorial.value != -1" class="tutorial _block"/> <XTutorial v-if="$store.reactiveState.tutorial.value != -1" class="tutorial _block"/>
<XPostForm v-if="$store.reactiveState.showFixedPostForm.value" class="post-form _block" fixed/> <XPostForm v-if="$store.reactiveState.showFixedPostForm.value" class="post-form _block" fixed/>
<div class="tabs _block"> <div class="tabs _block _magnetChild">
<div class="left"> <div class="left">
<button class="_button tab" @click="() => { src = 'home'; saveSrc(); }" :class="{ active: src === 'home' }" v-tooltip="$ts._timelines.home"><Fa :icon="faHome"/></button> <button class="_button tab" @click="() => { src = 'home'; saveSrc(); }" :class="{ active: src === 'home' }" v-tooltip="$ts._timelines.home"><Fa :icon="faHome"/></button>
<button class="_button tab" @click="() => { src = 'local'; saveSrc(); }" :class="{ active: src === 'local' }" v-tooltip="$ts._timelines.local" v-if="isLocalTimelineAvailable"><Fa :icon="faComments"/></button> <button class="_button tab" @click="() => { src = 'local'; saveSrc(); }" :class="{ active: src === 'local' }" v-tooltip="$ts._timelines.local" v-if="isLocalTimelineAvailable"><Fa :icon="faComments"/></button>
@ -64,7 +63,6 @@ export default defineComponent({
channel: null, channel: null,
menuOpened: false, menuOpened: false,
queue: 0, queue: 0,
width: 0,
[symbols.PAGE_INFO]: computed(() => ({ [symbols.PAGE_INFO]: computed(() => ({
title: this.$ts.timeline, title: this.$ts.timeline,
icon: this.src === 'local' ? faComments : this.src === 'social' ? faShareAlt : this.src === 'global' ? faGlobe : faHome, icon: this.src === 'local' ? faComments : this.src === 'social' ? faShareAlt : this.src === 'global' ? faGlobe : faHome,
@ -126,10 +124,6 @@ export default defineComponent({
} }
}, },
mounted() {
this.width = this.$el.offsetWidth;
},
methods: { methods: {
before() { before() {
Progress.start(); Progress.start();
@ -140,7 +134,6 @@ export default defineComponent({
}, },
queueUpdated(q) { queueUpdated(q) {
if (this.$el.offsetWidth !== 0) this.width = this.$el.offsetWidth;
this.queue = q; this.queue = q;
}, },
@ -223,8 +216,10 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.cmuxhskf { .cmuxhskf {
> .new { > .new {
position: fixed; position: sticky;
top: calc(var(--stickyTop, 0px) + 16px);
z-index: 1000; z-index: 1000;
width: 100%;
> button { > button {
display: block; display: block;

View file

@ -198,6 +198,7 @@
<div v-if="user.pinnedNotes.length > 0"> <div v-if="user.pinnedNotes.length > 0">
<XNote v-for="note in user.pinnedNotes" class="note _block" :note="note" @update:note="pinnedNoteUpdated(note, $event)" :key="note.id" :pinned="true"/> <XNote v-for="note in user.pinnedNotes" class="note _block" :note="note" @update:note="pinnedNoteUpdated(note, $event)" :key="note.id" :pinned="true"/>
</div> </div>
<MkInfo v-else-if="$i && $i.id === user.id">{{ $ts.userPagePinTip }}</MkInfo>
<XPhotos :user="user" :key="user.id"/> <XPhotos :user="user" :key="user.id"/>
<XActivity :user="user" :key="user.id"/> <XActivity :user="user" :key="user.id"/>
</div> </div>
@ -229,6 +230,7 @@ import MkContainer from '@client/components/ui/container.vue';
import MkFolder from '@client/components/ui/folder.vue'; import MkFolder from '@client/components/ui/folder.vue';
import MkRemoteCaution from '@client/components/remote-caution.vue'; import MkRemoteCaution from '@client/components/remote-caution.vue';
import MkTab from '@client/components/tab.vue'; import MkTab from '@client/components/tab.vue';
import MkInfo from '@client/components/ui/info.vue';
import Progress from '@client/scripts/loading'; import Progress from '@client/scripts/loading';
import parseAcct from '@/misc/acct/parse'; import parseAcct from '@/misc/acct/parse';
import { getScrollPosition } from '@client/scripts/scroll'; import { getScrollPosition } from '@client/scripts/scroll';
@ -247,6 +249,7 @@ export default defineComponent({
MkRemoteCaution, MkRemoteCaution,
MkFolder, MkFolder,
MkTab, MkTab,
MkInfo,
XFollowList: defineAsyncComponent(() => import('./follow-list.vue')), XFollowList: defineAsyncComponent(() => import('./follow-list.vue')),
XClips: defineAsyncComponent(() => import('./clips.vue')), XClips: defineAsyncComponent(() => import('./clips.vue')),
XPages: defineAsyncComponent(() => import('./pages.vue')), XPages: defineAsyncComponent(() => import('./pages.vue')),

View file

@ -184,10 +184,6 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'device', where: 'device',
default: 'full' as 'full' | 'icon' default: 'full' as 'full' | 'icon'
}, },
titlebar: {
where: 'device',
default: true
},
reportError: { reportError: {
where: 'device', where: 'device',
default: false default: false

View file

@ -366,10 +366,6 @@ hr {
border-radius: var(--radius); border-radius: var(--radius);
} }
._magnet {
margin-bottom: calc(var(--margin) * -1);
}
@media (max-width: 500px) { @media (max-width: 500px) {
._root { ._root {
--root-margin: 0; --root-margin: 0;
@ -377,6 +373,12 @@ hr {
} }
} }
._magnetParent {
._magnetChild:not(* + ._magnetChild) {
margin-top: 0;
}
}
._narrow_ ._card { ._narrow_ ._card {
> ._title { > ._title {
padding: 16px; padding: 16px;

View file

@ -16,8 +16,6 @@
panelShadow: '" 0 8px 24px rgb(0 0 0 / 25%)', panelShadow: '" 0 8px 24px rgb(0 0 0 / 25%)',
panelHeaderBg: '@panel', panelHeaderBg: '@panel',
panelHeaderDivider: '@divider', panelHeaderDivider: '@divider',
infoFg: '@accent',
infoBg: 'rgb(0, 0, 0)',
header: ':alpha<0.7<@panel', header: ':alpha<0.7<@panel',
navBg: '#363636', navBg: '#363636',
renote: '@accent', renote: '@accent',

View file

@ -6,7 +6,7 @@
</div> </div>
<main class="main _panel" @contextmenu.stop="onContextmenu"> <main class="main _panel" @contextmenu.stop="onContextmenu">
<header v-if="$store.state.titlebar" class="header" @click="onHeaderClick"> <header class="header" @click="onHeaderClick">
<XHeader :info="pageInfo"/> <XHeader :info="pageInfo"/>
</header> </header>
<div class="content" :class="{ _flat_: !fullView }"> <div class="content" :class="{ _flat_: !fullView }">

View file

@ -2,8 +2,8 @@
<div class="mk-app" :class="{ wallpaper }"> <div class="mk-app" :class="{ wallpaper }">
<XSidebar ref="nav" class="sidebar"/> <XSidebar ref="nav" class="sidebar"/>
<div class="contents" ref="contents" :class="{ withHeader: $store.state.titlebar }" @contextmenu.stop="onContextmenu"> <div class="contents" ref="contents" @contextmenu.stop="onContextmenu">
<header v-if="$store.state.titlebar" class="header" ref="header" @click="onHeaderClick"> <header class="header" ref="header" @click="onHeaderClick">
<XHeader :info="pageInfo"/> <XHeader :info="pageInfo"/>
</header> </header>
<main ref="main"> <main ref="main">
@ -260,10 +260,7 @@ export default defineComponent({
width: 100%; width: 100%;
min-width: 0; min-width: 0;
--stickyTop: #{$header-height}; --stickyTop: #{$header-height};
&.withHeader {
padding-top: $header-height; padding-top: $header-height;
}
> .header { > .header {
position: fixed; position: fixed;

View file

@ -22,7 +22,7 @@
</div> </div>
</div> </div>
<div class="deliver"> <div class="deliver">
<div class="label">Deliver queue<Fa :icon="faExclamationTriangle" v-if="inbox.waiting > 0" class="icon"/></div> <div class="label">Deliver queue<Fa :icon="faExclamationTriangle" v-if="deliver.waiting > 0" class="icon"/></div>
<div class="values"> <div class="values">
<div> <div>
<div>Process</div> <div>Process</div>

View file

@ -6613,10 +6613,10 @@ methods@^1.1.2:
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
mfm-js@0.14.0: mfm-js@0.15.0:
version "0.14.0" version "0.15.0"
resolved "https://registry.yarnpkg.com/mfm-js/-/mfm-js-0.14.0.tgz#0952ed6f0dd8553866bde7e646c3d5d3d23aeae9" resolved "https://registry.yarnpkg.com/mfm-js/-/mfm-js-0.15.0.tgz#b7dea4225a992ac4fd873ad6b2cad069f171dc24"
integrity sha512-snCiszquj6DIOARdgJfI8b6o9PbojAmJe1thrsBkUTxG+XG27rCOmjEL1kc1705XraJo0aVCLR9vE6YmjHiUQg== integrity sha512-JW7AAQzXejo60JGwx+wzodkp45XKYBEq4bYlMDcxjmi2e+P0IOhAcpz2HPBbzxnO/4X3WPuklU8B16RUZpFFdg==
dependencies: dependencies:
twemoji-parser "13.0.x" twemoji-parser "13.0.x"