Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
EbiseLutica committed Jan 7, 2025
2 parents 7ef4fec + b3a874f commit 382f233
Show file tree
Hide file tree
Showing 14 changed files with 141 additions and 60 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG-EBISSKEY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

Ebisskeyとしての変更履歴です。Misskeyのリリースノートは [CHANGELOG](/CHANGELOG.md) を確認してください。

## 2024.11.0-sh.3
* ✨️ 新機能! テキストエリアの自動リサイズ機能
* Ebisskey Labsから有効化できます
* Ebisskey Labs: 投稿フォームをウィンドウ化する機能が正常に動作しない為、一旦無効化しました
* エアリプ機能: 「連合なし」が適用されない不具合を修正
* エアリプ機能: 入力欄にメンションが入ってしまう不具合を修正
* エアリプ機能: パブリックノートに対してエアリプするとき、公開範囲が[デフォルトの公開範囲]で固定されてしまう不具合を修正
* 公開範囲の色分け機能:機能フラグをオフにしていても表示されてしまう不具合を修正

## 2024.11.0-sh.2
* エアリプ機能
* 公開範囲の色分け機能
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/components/MkNote.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
:class="[$style.root, { [$style.showActionsOnlyHover]: defaultStore.state.showNoteActionsOnlyHover, [$style.skipRender]: defaultStore.state.skipNoteRender }]"
:tabindex="isDeleted ? '-1' : '0'"
>
<ShVisibilityColoring v-if="!appearNote.channel && (appearNote.visibility !== 'public' || appearNote.localOnly)" :visibility="appearNote.visibility" :localOnly="appearNote.localOnly ?? false"/>
<ShVisibilityColoring v-if="defaultStore.state.useNoteVisibilityColoring && !appearNote.channel && (appearNote.visibility !== 'public' || appearNote.localOnly)" :visibility="appearNote.visibility" :localOnly="appearNote.localOnly ?? false"/>
<MkNoteSub v-if="appearNote.reply && !renoteCollapsed" :note="appearNote.reply" :class="$style.replyTo"/>
<div v-if="pinned" :class="$style.tip"><i class="ti ti-pin"></i> {{ i18n.ts.pinnedNote }}</div>
<!--<div v-if="appearNote._prId_" class="tip"><i class="ti ti-speakerphone"></i> {{ i18n.ts.promotion }}<button class="_textButton hide" @click="readPromo()">{{ i18n.ts.hideThisNote }} <i class="ti ti-x"></i></button></div>-->
Expand Down
16 changes: 11 additions & 5 deletions packages/frontend/src/components/MkPostForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only
@dragleave="onDragleave"
@drop.stop="onDrop"
>
<ShVisibilityColoring v-if="!channel && (visibility !== 'public' || localOnly)" :visibility="visibility" :localOnly="localOnly"/>
<ShVisibilityColoring v-if="defaultStore.state.useNoteVisibilityColoring && !channel && (visibility !== 'public' || localOnly)" :visibility="visibility" :localOnly="localOnly"/>
<header :class="$style.header">
<div :class="$style.headerLeft">
<button v-if="!fixed" :class="$style.cancel" class="_button" @click="cancel"><i class="ti ti-x"></i></button>
Expand All @@ -21,7 +21,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
<div :class="$style.headerRight">
<template v-if="!(channel != null && fixed)">
<button v-if="channel == null" ref="visibilityButton" v-click-anime v-tooltip="i18n.ts.visibility" :disabled="isAirReply" :class="['_button', $style.headerRightItem, $style.visibility]" @click="setVisibility">
<button v-if="channel == null" ref="visibilityButton" v-click-anime v-tooltip="i18n.ts.visibility" :class="['_button', $style.headerRightItem, $style.visibility]" @click="setVisibility">
<span v-if="visibility === 'public'"><i class="ti ti-world"></i></span>
<span v-if="visibility === 'home'"><i class="ti ti-home"></i></span>
<span v-if="visibility === 'followers'"><i class="ti ti-lock"></i></span>
Expand All @@ -33,7 +33,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<span :class="$style.headerRightButtonText">{{ channel.name }}</span>
</button>
</template>
<button v-click-anime v-tooltip="i18n.ts._visibility.disableFederation" class="_button" :class="[$style.headerRightItem, { [$style.danger]: localOnly }]" :disabled="channel != null || visibility === 'specified' || isAirReply" @click="toggleLocalOnly">
<button v-click-anime v-tooltip="i18n.ts._visibility.disableFederation" class="_button" :class="[$style.headerRightItem, { [$style.danger]: localOnly }]" :disabled="channel != null || visibility === 'specified'" @click="toggleLocalOnly">
<span v-if="!localOnly"><i class="ti ti-rocket"></i></span>
<span v-else><i class="ti ti-rocket-off"></i></span>
</button>
Expand Down Expand Up @@ -72,7 +72,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<input v-show="useCw" ref="cwInputEl" v-model="cw" :class="$style.cw" :placeholder="i18n.ts.annotation" @keydown="onKeydown" @keyup="onKeyup" @compositionend="onCompositionEnd">
<div :class="[$style.textOuter, { [$style.withCw]: useCw }]">
<div v-if="channel" :class="$style.colorBar" :style="{ background: channel.color }"></div>
<textarea ref="textareaEl" v-model="text" :class="[$style.text]" :disabled="posting || posted" :readonly="textAreaReadOnly" :placeholder="placeholder" data-cy-post-form-text @keydown="onKeydown" @keyup="onKeyup" @paste="onPaste" @compositionupdate="onCompositionUpdate" @compositionend="onCompositionEnd"/>
<textarea ref="textareaEl" v-model="text" v-autosize :class="[$style.text]" :disabled="posting || posted" :readonly="textAreaReadOnly" :placeholder="placeholder" data-cy-post-form-text @keydown="onKeydown" @keyup="onKeyup" @paste="onPaste" @compositionupdate="onCompositionUpdate" @compositionend="onCompositionEnd"/>
<div v-if="maxTextLength - textLength < 100" :class="['_acrylic', $style.textCount, { [$style.textOver]: textLength > maxTextLength }]">{{ maxTextLength - textLength }}</div>
</div>
<input v-show="withHashtags" ref="hashtagsInputEl" v-model="hashtags" :class="$style.hashtags" :placeholder="i18n.ts.hashtags" list="hashtags">
Expand Down Expand Up @@ -294,7 +294,7 @@ if (props.mention) {
text.value += ' ';
}

if (props.reply && (props.reply.user.username !== $i.username || (props.reply.user.host != null && props.reply.user.host !== host))) {
if (props.reply && !props.isAirReply && (props.reply.user.username !== $i.username || (props.reply.user.host != null && props.reply.user.host !== host))) {
text.value = `@${props.reply.user.username}${props.reply.user.host != null ? '@' + toASCII(props.reply.user.host) : ''} `;
}

Expand Down Expand Up @@ -355,6 +355,12 @@ if (props.reply && ['home', 'followers', 'specified'].includes(props.reply.visib
}
}

// Shrimpia エアリプ機能を用いる場合の処理
if (props.reply && props.isAirReply) {
visibility.value = props.reply.visibility;
localOnly.value = props.reply.localOnly ?? false;
}

if (props.specified) {
visibility.value = 'specified';
pushVisibleUser(props.specified);
Expand Down
1 change: 1 addition & 0 deletions packages/frontend/src/components/MkTextarea.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only
ref="inputEl"
v-model="v"
v-adaptive-border
v-autosize
:class="[$style.textarea, { _monospace: code }]"
:disabled="disabled"
:required="required"
Expand Down
22 changes: 22 additions & 0 deletions packages/frontend/src/directives/autosize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Directive } from 'vue';
import { defaultStore } from '@/store.js';

const onInput = (arg: Event | HTMLTextAreaElement) => {
const el = 'target' in arg ? (arg.target as HTMLTextAreaElement) : arg;
// 先にautoをしておかないと、縮まってくれない
el.style.height = 'auto';
el.style.height = `${el.scrollHeight}px`;
};

export default {
mounted(el: HTMLTextAreaElement) {
if (!defaultStore.state.useTextAreaAutoSize) return;
onInput(el);
el.addEventListener('input', onInput);
el.style.resize = 'none';
el.style.overflow = 'hidden';
},
unmounted(el: HTMLTextAreaElement) {
el.removeEventListener('input', onInput);
},
} as Directive;
2 changes: 2 additions & 0 deletions packages/frontend/src/directives/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import clickAnime from './click-anime.js';
import panel from './panel.js';
import adaptiveBorder from './adaptive-border.js';
import adaptiveBg from './adaptive-bg.js';
import autosize from './autosize.js';

export default function(app: App) {
for (const [key, value] of Object.entries(directives)) {
Expand All @@ -36,4 +37,5 @@ export const directives = {
'panel': panel,
'adaptive-border': adaptiveBorder,
'adaptive-bg': adaptiveBg,
'autosize': autosize,
};
6 changes: 2 additions & 4 deletions packages/frontend/src/os.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import * as Misskey from 'misskey-js';
import type { ComponentProps as CP } from 'vue-component-type-helpers';
import type { Form, GetFormResultType } from '@/scripts/form.js';
import type { MenuItem } from '@/types/menu.js';
import type { PostFormProps } from '@/types/post-form.js';
import { misskeyApi } from '@/scripts/misskey-api.js';
import { defaultStore } from '@/store.js';
import { i18n } from '@/i18n.js';
Expand All @@ -25,12 +26,10 @@ import MkEmojiPickerDialog from '@/components/MkEmojiPickerDialog.vue';
import MkPopupMenu from '@/components/MkPopupMenu.vue';
import MkContextMenu from '@/components/MkContextMenu.vue';
import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
import { defaultStore } from './store.js';
import { pleaseLogin } from '@/scripts/please-login.js';
import { showMovedDialog } from '@/scripts/show-moved-dialog.js';
import { getHTMLElementOrNull } from '@/scripts/get-dom-node-or-null.js';
import { focusParent } from '@/scripts/focus.js';
import type { PostFormProps } from '@/types/post-form.js';

export const openingWindowsCount = ref(0);

Expand Down Expand Up @@ -709,8 +708,7 @@ export function post(props: PostFormProps = {}): Promise<void> {
// Vueが渡されたコンポーネントに内部的に__propsというプロパティを生やす影響で、
// 複数のpost formを開いたときに場合によってはエラーになる
// もちろん複数のpost formを開けること自体Misskeyサイドのバグなのだが
const component = defaultStore.state.usePostFormWindow ? MkPostFormWindow : MkPostFormDialog;
const { dispose } = popup(component, props, {
const { dispose } = popup(MkPostFormDialog, props, {
closed: () => {
resolve();
dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #header><i class="ti ti-align-left"></i> {{ i18n.ts._pages.blocks.text }}</template>

<section>
<textarea ref="inputEl" v-model="text" :class="$style.textarea"></textarea>
<textarea ref="inputEl" v-model="text" v-autosize :class="$style.textarea"></textarea>
</section>
</XContainer>
</template>

<script lang="ts" setup>

import { watch, ref, shallowRef, onMounted, onUnmounted } from 'vue';
import * as Misskey from 'misskey-js';
import XContainer from '../page-editor.container.vue';
Expand Down
126 changes: 80 additions & 46 deletions packages/frontend/src/pages/settings/ebisskey.vue
Original file line number Diff line number Diff line change
Expand Up @@ -54,88 +54,122 @@
<div>まだ開発中の機能を試してみませんか。一部の機能はちゃんと動かないかもしれません。</div>

<!-- エアリプ機能 -->
<MkFolder open>
<template #label><i class="ti ti-bubble-text"/> エアリプ機能</template>
<div class="_gaps_m">
<div>特定のノートに曖昧な返信を行うための、公開範囲を合わせた投稿ボタンを有効化します。</div>
<MkSwitch v-model="useAirReply">
エアリプ機能を有効にする
</MkSwitch>
<MkSelect v-if="useAirReply" v-model="airReplyButtonPlacement">
<template #label>ボタンの位置</template>
<option value="noteMenu">ノートのメニュー</option>
<option value="renoteMenu">リノートボタンのメニュー</option>
<option value="noteFooter">ノートの下部</option>
</MkSelect>
</div>
</MkFolder>
<div class="_panel _padding _gaps_m">
<MkSwitch v-model="useAirReply">
エアリプ機能
<template #caption>
特定のノートに曖昧な返信を行うための、公開範囲を合わせた投稿ボタンを有効化します。
</template>
</MkSwitch>
<MkSelect v-if="useAirReply" v-model="airReplyButtonPlacement">
<template #label>ボタンの位置</template>
<option value="noteMenu">ノートのメニュー</option>
<option value="renoteMenu">リノートボタンのメニュー</option>
<option value="noteFooter">ノートの下部</option>
</MkSelect>
</div>

<MkFolder open>
<template #label><i class="ti ti-tag"/> 公開範囲に応じた色分け</template>
<div class="_gaps_m">
<div>ノートの公開範囲に応じて、特殊な色付き表示を行います。</div>
<MkSwitch v-model="useNoteVisibilityColoring">
色分けを有効にする
</MkSwitch>
<div class="_panel _padding _gaps_m">
<MkSwitch v-model="useNoteVisibilityColoring">
公開範囲に応じた色分け
<template #caption>
ノートの公開範囲に応じて、特殊な色付き表示を行います。
</template>
</MkSwitch>
<template v-if="useNoteVisibilityColoring">
<MkColorInput v-model="noteVisibilityColorHome">
<template #label>{{ i18n.ts._visibility.home }}</template>
</MkColorInput>
<MkColorInput v-model="noteVisibilityColorFollowers">
<template #label>{{ i18n.ts._visibility.followers }}</template>
</MkColorInput>
<MkColorInput v-model="noteVisibilityColorSpecified">
<template #label>{{ i18n.ts._visibility.specified }}</template>
</MkColorInput>
<MkColorInput v-model="noteVisibilityColorLocalOnly">
<template #label>{{ i18n.ts._visibility.public }}({{ i18n.ts._visibility.disableFederation }})</template>
</MkColorInput>
<MkButton v-if="noteVisibilityColorChanged" primary @click="saveColors"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton>
</template>
</div>

<template v-if="useNoteVisibilityColoring">
<MkColorInput v-model="noteVisibilityColorHome">
<template #label>{{ i18n.ts._visibility.home }}</template>
</MkColorInput>
<MkColorInput v-model="noteVisibilityColorFollowers">
<template #label>{{ i18n.ts._visibility.followers }}</template>
</MkColorInput>
<MkColorInput v-model="noteVisibilityColorSpecified">
<template #label>{{ i18n.ts._visibility.specified }}</template>
</MkColorInput>
<MkColorInput v-model="noteVisibilityColorLocalOnly">
<template #label>{{ i18n.ts._visibility.disableFederation }}</template>
</MkColorInput>
<div class="_panel _padding _gaps_m">
<MkSwitch v-model="useTextAreaAutoSize">
テキストエリアの自動サイズ調整
<template #caption>
入力したテキストの行数に合わせて長文の入力欄(例:投稿フォーム)の高さを自動調整します。<br/>
一部のブラウザで正常に動作しないかもしれません。
</template>
</div>
</MkFolder>
</MkSwitch>
</div>

<MkSwitch v-model="usePostFormWindow">
<!-- 不具合で動かないため一度オフ -->
<!-- <MkSwitch v-model="usePostFormWindow">
投稿フォームをウィンドウとして表示
</MkSwitch>
</MkSwitch> -->
</div>
</FormSection>
</div>
</template>

<script lang="ts" setup>
import { computed, watch } from 'vue';
import { computed, ref, watch } from 'vue';
import MkSwitch from '@/components/MkSwitch.vue';
import FormSection from '@/components/form/section.vue';
import { defaultStore } from '@/store';
import { definePageMetadata } from '@/scripts/page-metadata';
import { i18n } from '@/i18n';
import { reloadAsk } from '@/scripts/reload-ask.js';
import MkFolder from '@/components/MkFolder.vue';
import MkSelect from '@/components/MkSelect.vue';
import MkColorInput from '@/components/MkColorInput.vue';
import MkButton from '@/components/MkButton.vue';
const nicknameEnabled = computed(defaultStore.makeGetterSetter('nicknameEnabled'));
const stealEnabled = computed(defaultStore.makeGetterSetter('stealEnabled'));
const infoButtonForNoteActionsEnabled = computed(defaultStore.makeGetterSetter('infoButtonForNoteActionsEnabled'));
const rememberPostFormToggleStateEnabled = computed(defaultStore.makeGetterSetter('rememberPostFormToggleStateEnabled'));
const featuredTimelineEnabled = computed(defaultStore.makeGetterSetter('featuredTimelineEnabled'));
const usePostFormWindow = computed(defaultStore.makeGetterSetter('usePostFormWindow'));
const useAirReply = computed(defaultStore.makeGetterSetter('useAirReply'));
const airReplyButtonPlacement = computed(defaultStore.makeGetterSetter('airReplyButtonPlacement'));
const useNoteVisibilityColoring = computed(defaultStore.makeGetterSetter('useNoteVisibilityColoring'));
const noteVisibilityColorHome = computed(defaultStore.makeGetterSetter('noteVisibilityColorHome'));
const noteVisibilityColorFollowers = computed(defaultStore.makeGetterSetter('noteVisibilityColorFollowers'));
const noteVisibilityColorSpecified = computed(defaultStore.makeGetterSetter('noteVisibilityColorSpecified'));
const noteVisibilityColorLocalOnly = computed(defaultStore.makeGetterSetter('noteVisibilityColorLocalOnly'));
const useTextAreaAutoSize = computed(defaultStore.makeGetterSetter('useTextAreaAutoSize'));
const noteVisibilityColorHome = ref(defaultStore.state.noteVisibilityColorHome);
const noteVisibilityColorFollowers = ref(defaultStore.state.noteVisibilityColorFollowers);
const noteVisibilityColorSpecified = ref(defaultStore.state.noteVisibilityColorSpecified);
const noteVisibilityColorLocalOnly = ref(defaultStore.state.noteVisibilityColorLocalOnly);
const noteVisibilityColorChanged = ref(false);
watch([
noteVisibilityColorHome,
noteVisibilityColorFollowers,
noteVisibilityColorSpecified,
noteVisibilityColorLocalOnly,
], () => {
noteVisibilityColorChanged.value = true;
});
watch([
stealEnabled,
infoButtonForNoteActionsEnabled,
useAirReply,
airReplyButtonPlacement,
useNoteVisibilityColoring,
useTextAreaAutoSize,
], async () => {
await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
});
function saveColors() {
if (noteVisibilityColorChanged.value) {
defaultStore.set('noteVisibilityColorHome', noteVisibilityColorHome.value);
defaultStore.set('noteVisibilityColorFollowers', noteVisibilityColorFollowers.value);
defaultStore.set('noteVisibilityColorSpecified', noteVisibilityColorSpecified.value);
defaultStore.set('noteVisibilityColorLocalOnly', noteVisibilityColorLocalOnly.value);
noteVisibilityColorChanged.value = false;
}
}
const headerActions = computed(() => []);
const headerTabs = computed(() => []);
Expand Down
1 change: 1 addition & 0 deletions packages/frontend/src/pages/user/home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<textarea
ref="memoTextareaEl"
v-model="memoDraft"
v-autosize
rows="1"
@focus="isEditingMemo = true"
@blur="updateMemo"
Expand Down
4 changes: 4 additions & 0 deletions packages/frontend/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,10 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'account',
default: '#B93E43',
},
useTextAreaAutoSize: {
where: 'account',
default: false,
},
ebiNoteViewEnabledLab: {
where: 'account',
default: false,
Expand Down
4 changes: 4 additions & 0 deletions packages/frontend/src/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,10 @@ rt {
overflow: clip;
}

._padding {
padding: var(--MI-margin);
}

._margin {
margin: var(--MI-margin) 0;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/widgets/WidgetAiscript.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #header>{{ i18n.ts._widgets.aiscript }}</template>

<div class="uylguesu _monospace">
<textarea v-model="widgetProps.script" placeholder="(1 + 1)"></textarea>
<textarea v-model="widgetProps.script" v-autosize placeholder="(1 + 1)"></textarea>
<button class="_buttonPrimary" @click="run">RUN</button>
<div class="logs">
<div v-for="log in logs" :key="log.id" class="log" :class="{ print: log.print }">{{ log.text }}</div>
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/widgets/WidgetMemo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #header>{{ i18n.ts._widgets.memo }}</template>

<div :class="$style.root">
<textarea v-model="text" :style="`height: ${widgetProps.height}px;`" :class="$style.textarea" :placeholder="i18n.ts.placeholder" @input="onChange"></textarea>
<textarea v-model="text" v-autosize :style="`height: ${widgetProps.height}px;`" :class="$style.textarea" :placeholder="i18n.ts.placeholder" @input="onChange"></textarea>
<button :class="$style.save" :disabled="!changed" class="_buttonPrimary" @click="saveMemo">{{ i18n.ts.save }}</button>
</div>
</MkContainer>
Expand Down

0 comments on commit 382f233

Please sign in to comment.