summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2023-02-09 10:35:28 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2023-02-09 10:35:28 +0900
commit7afee5977fe60f0e69e148f38974e02141c8f8c6 (patch)
treec0cb99fa15fc15734f0ab3635eae8cb027b6c2dc
parentrefactor(client): use css modules (diff)
downloadmisskey-7afee5977fe60f0e69e148f38974e02141c8f8c6.tar.gz
misskey-7afee5977fe60f0e69e148f38974e02141c8f8c6.tar.bz2
misskey-7afee5977fe60f0e69e148f38974e02141c8f8c6.zip
feat(client): add channel column to deck
-rw-r--r--CHANGELOG.md9
-rw-r--r--locales/ja-JP.yml2
-rw-r--r--packages/frontend/src/pages/channel.vue4
-rw-r--r--packages/frontend/src/pages/share.vue32
-rw-r--r--packages/frontend/src/pages/timeline.vue4
-rw-r--r--packages/frontend/src/ui/deck.vue1
-rw-r--r--packages/frontend/src/ui/deck/channel-column.vue71
-rw-r--r--packages/frontend/src/ui/deck/column-core.vue2
-rw-r--r--packages/frontend/src/ui/deck/deck-store.ts3
-rw-r--r--packages/frontend/src/widgets/WidgetPostForm.vue6
10 files changed, 110 insertions, 24 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a7f914bd4b..d7ee9ae169 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,15 @@
You should also include the user name that made the change.
-->
+
+## 13.x.x (unreleased)
+
+### Improvements
+- Client: デッキにチャンネルカラムを追加
+
+### Bugfixes
+-
+
## 13.5.2 (2023/02/08)
### Changes
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 6286367b50..8e8fddfb89 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -129,6 +129,7 @@ unblockConfirm: "ブロック解除しますか?"
suspendConfirm: "凍結しますか?"
unsuspendConfirm: "解凍しますか?"
selectList: "リストを選択"
+selectChannel: "チャンネルを選択"
selectAntenna: "アンテナを選択"
selectWidget: "ウィジェットを選択"
editWidgets: "ウィジェットを編集"
@@ -1922,5 +1923,6 @@ _deck:
tl: "タイムライン"
antenna: "アンテナ"
list: "リスト"
+ channel: "チャンネル"
mentions: "あなた宛て"
direct: "ダイレクト"
diff --git a/packages/frontend/src/pages/channel.vue b/packages/frontend/src/pages/channel.vue
index 96340a36b9..0fb33e30f7 100644
--- a/packages/frontend/src/pages/channel.vue
+++ b/packages/frontend/src/pages/channel.vue
@@ -23,7 +23,7 @@
</div>
</div>
- <XPostForm v-if="$i" :channel="channel" class="post-form _panel _margin" fixed/>
+ <MkPostForm v-if="$i" :channel="channel" class="post-form _panel _margin" fixed/>
<XTimeline :key="channelId" class="_margin" src="channel" :channel="channelId" @before="before" @after="after"/>
</div>
@@ -34,7 +34,7 @@
<script lang="ts" setup>
import { computed, inject, watch } from 'vue';
import MkContainer from '@/components/MkContainer.vue';
-import XPostForm from '@/components/MkPostForm.vue';
+import MkPostForm from '@/components/MkPostForm.vue';
import XTimeline from '@/components/MkTimeline.vue';
import XChannelFollowButton from '@/components/MkChannelFollowButton.vue';
import * as os from '@/os';
diff --git a/packages/frontend/src/pages/share.vue b/packages/frontend/src/pages/share.vue
index a7e797eeab..d8b956b6d1 100644
--- a/packages/frontend/src/pages/share.vue
+++ b/packages/frontend/src/pages/share.vue
@@ -29,7 +29,7 @@ import { noteVisibilities } from 'misskey-js';
import * as Acct from 'misskey-js/built/acct';
import * as Misskey from 'misskey-js';
import MkButton from '@/components/MkButton.vue';
-import XPostForm from '@/components/MkPostForm.vue';
+import MkPostForm from '@/components/MkPostForm.vue';
import * as os from '@/os';
import { mainRouter } from '@/router';
import { definePageMetadata } from '@/scripts/page-metadata';
@@ -69,14 +69,14 @@ async function init() {
...(visibleAccts ? visibleAccts.split(',').map(Acct.parse) : []),
]
// TypeScriptの指示通りに変換する
- .map(q => 'username' in q ? { username: q.username, host: q.host === null ? undefined : q.host } : q)
- .map(q => os.api('users/show', q)
- .then(user => {
- visibleUsers.push(user);
- }, () => {
- console.error(`Invalid user query: ${JSON.stringify(q)}`);
- }),
- ),
+ .map(q => 'username' in q ? { username: q.username, host: q.host === null ? undefined : q.host } : q)
+ .map(q => os.api('users/show', q)
+ .then(user => {
+ visibleUsers.push(user);
+ }, () => {
+ console.error(`Invalid user query: ${JSON.stringify(q)}`);
+ }),
+ ),
);
}
@@ -120,13 +120,13 @@ async function init() {
if (fileIds) {
await Promise.all(
fileIds.split(',')
- .map(fileId => os.api('drive/files/show', { fileId })
- .then(file => {
- files.push(file);
- }, () => {
- console.error(`Failed to fetch a file ${fileId}`);
- }),
- ),
+ .map(fileId => os.api('drive/files/show', { fileId })
+ .then(file => {
+ files.push(file);
+ }, () => {
+ console.error(`Failed to fetch a file ${fileId}`);
+ }),
+ ),
);
}
//#endregion
diff --git a/packages/frontend/src/pages/timeline.vue b/packages/frontend/src/pages/timeline.vue
index 080772951e..057409484c 100644
--- a/packages/frontend/src/pages/timeline.vue
+++ b/packages/frontend/src/pages/timeline.vue
@@ -4,7 +4,7 @@
<MkSpacer :content-max="800">
<div ref="rootEl" v-hotkey.global="keymap">
<XTutorial v-if="$i && $store.reactiveState.tutorial.value != -1" class="_panel" style="margin-bottom: var(--margin);"/>
- <XPostForm v-if="$store.reactiveState.showFixedPostForm.value" :class="$style.postForm" class="post-form _panel" fixed style="margin-bottom: var(--margin);"/>
+ <MkPostForm v-if="$store.reactiveState.showFixedPostForm.value" :class="$style.postForm" class="post-form _panel" fixed style="margin-bottom: var(--margin);"/>
<div v-if="queue > 0" :class="$style.new"><button class="_buttonPrimary" @click="top()">{{ i18n.ts.newNoteRecived }}</button></div>
<div :class="$style.tl">
@@ -24,7 +24,7 @@
<script lang="ts" setup>
import { defineAsyncComponent, computed, watch } from 'vue';
import XTimeline from '@/components/MkTimeline.vue';
-import XPostForm from '@/components/MkPostForm.vue';
+import MkPostForm from '@/components/MkPostForm.vue';
import { scroll } from '@/scripts/scroll';
import * as os from '@/os';
import { defaultStore } from '@/store';
diff --git a/packages/frontend/src/ui/deck.vue b/packages/frontend/src/ui/deck.vue
index fd6caaa58c..b09721dec9 100644
--- a/packages/frontend/src/ui/deck.vue
+++ b/packages/frontend/src/ui/deck.vue
@@ -146,6 +146,7 @@ const addColumn = async (ev) => {
'tl',
'antenna',
'list',
+ 'channel',
'mentions',
'direct',
];
diff --git a/packages/frontend/src/ui/deck/channel-column.vue b/packages/frontend/src/ui/deck/channel-column.vue
new file mode 100644
index 0000000000..5a84237c80
--- /dev/null
+++ b/packages/frontend/src/ui/deck/channel-column.vue
@@ -0,0 +1,71 @@
+<template>
+<XColumn :menu="menu" :column="column" :is-stacked="isStacked" @parent-focus="$event => emit('parent-focus', $event)">
+ <template #header>
+ <i class="ti ti-device-tv"></i><span style="margin-left: 8px;">{{ column.name }}</span>
+ </template>
+
+ <template v-if="column.channelId">
+ <div style="padding: 8px; text-align: center;">
+ <MkButton primary gradate rounded inline @click="post"><i class="ti ti-pencil"></i></MkButton>
+ </div>
+ <XTimeline ref="timeline" src="channel" :channel="column.channelId" @after="() => emit('loaded')"/>
+ </template>
+</XColumn>
+</template>
+
+<script lang="ts" setup>
+import { } from 'vue';
+import XColumn from './column.vue';
+import { updateColumn, Column } from './deck-store';
+import XTimeline from '@/components/MkTimeline.vue';
+import MkButton from '@/components/MkButton.vue';
+import * as os from '@/os';
+import { i18n } from '@/i18n';
+
+const props = defineProps<{
+ column: Column;
+ isStacked: boolean;
+}>();
+
+const emit = defineEmits<{
+ (ev: 'loaded'): void;
+ (ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
+}>();
+
+let timeline = $shallowRef<InstanceType<typeof XTimeline>>();
+
+if (props.column.channelId == null) {
+ setChannel();
+}
+
+async function setChannel() {
+ const channels = await os.api('channels/followed');
+ const { canceled, result: channel } = await os.select({
+ title: i18n.ts.selectChannel,
+ items: channels.map(x => ({
+ value: x, text: x.name,
+ })),
+ default: props.column.channelId,
+ });
+ if (canceled) return;
+ updateColumn(props.column.id, {
+ channelId: channel.id,
+ name: channel.name,
+ });
+}
+
+function post() {
+ os.post({
+ channel: {
+ id: props.column.channelId,
+ },
+ instant: true,
+ });
+}
+
+const menu = [{
+ icon: 'ti ti-pencil',
+ text: i18n.ts.selectChannel,
+ action: setChannel,
+}];
+</script>
diff --git a/packages/frontend/src/ui/deck/column-core.vue b/packages/frontend/src/ui/deck/column-core.vue
index 30c0dc5e1c..083e91bb03 100644
--- a/packages/frontend/src/ui/deck/column-core.vue
+++ b/packages/frontend/src/ui/deck/column-core.vue
@@ -6,6 +6,7 @@
<XNotificationsColumn v-else-if="column.type === 'notifications'" :column="column" :is-stacked="isStacked" @parent-focus="emit('parent-focus', $event)"/>
<XTlColumn v-else-if="column.type === 'tl'" :column="column" :is-stacked="isStacked" @parent-focus="emit('parent-focus', $event)"/>
<XListColumn v-else-if="column.type === 'list'" :column="column" :is-stacked="isStacked" @parent-focus="emit('parent-focus', $event)"/>
+<XChannelColumn v-else-if="column.type === 'channel'" :column="column" :is-stacked="isStacked" @parent-focus="emit('parent-focus', $event)"/>
<XAntennaColumn v-else-if="column.type === 'antenna'" :column="column" :is-stacked="isStacked" @parent-focus="emit('parent-focus', $event)"/>
<XMentionsColumn v-else-if="column.type === 'mentions'" :column="column" :is-stacked="isStacked" @parent-focus="emit('parent-focus', $event)"/>
<XDirectColumn v-else-if="column.type === 'direct'" :column="column" :is-stacked="isStacked" @parent-focus="emit('parent-focus', $event)"/>
@@ -17,6 +18,7 @@ import XMainColumn from './main-column.vue';
import XTlColumn from './tl-column.vue';
import XAntennaColumn from './antenna-column.vue';
import XListColumn from './list-column.vue';
+import XChannelColumn from './channel-column.vue';
import XNotificationsColumn from './notifications-column.vue';
import XWidgetsColumn from './widgets-column.vue';
import XMentionsColumn from './mentions-column.vue';
diff --git a/packages/frontend/src/ui/deck/deck-store.ts b/packages/frontend/src/ui/deck/deck-store.ts
index 56db7398e5..80c202a2ef 100644
--- a/packages/frontend/src/ui/deck/deck-store.ts
+++ b/packages/frontend/src/ui/deck/deck-store.ts
@@ -14,7 +14,7 @@ type ColumnWidget = {
export type Column = {
id: string;
- type: 'main' | 'widgets' | 'notifications' | 'tl' | 'antenna' | 'list' | 'mentions' | 'direct';
+ type: 'main' | 'widgets' | 'notifications' | 'tl' | 'antenna' | 'channel' | 'list' | 'mentions' | 'direct';
name: string | null;
width: number;
widgets?: ColumnWidget[];
@@ -22,6 +22,7 @@ export type Column = {
flexible?: boolean;
antennaId?: string;
listId?: string;
+ channelId?: string;
includingTypes?: typeof notificationTypes[number][];
tl?: 'home' | 'local' | 'social' | 'global';
};
diff --git a/packages/frontend/src/widgets/WidgetPostForm.vue b/packages/frontend/src/widgets/WidgetPostForm.vue
index 54226c1dbf..f8bebcbf96 100644
--- a/packages/frontend/src/widgets/WidgetPostForm.vue
+++ b/packages/frontend/src/widgets/WidgetPostForm.vue
@@ -1,12 +1,12 @@
<template>
-<XPostForm class="_panel mkw-postForm data-cy-mkw-postForm" :fixed="true" :autofocus="false"/>
+<MkPostForm class="_panel mkw-post-form data-cy-mkw-postForm" :fixed="true" :autofocus="false"/>
</template>
<script lang="ts" setup>
import { } from 'vue';
-import { GetFormResultType } from '@/scripts/form';
import { useWidgetPropsManager, Widget, WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps } from './widget';
-import XPostForm from '@/components/MkPostForm.vue';
+import { GetFormResultType } from '@/scripts/form';
+import MkPostForm from '@/components/MkPostForm.vue';
const name = 'postForm';