summaryrefslogtreecommitdiff
path: root/packages/frontend/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/frontend/src')
-rw-r--r--packages/frontend/src/components/MkTimeline.vue10
-rw-r--r--packages/frontend/src/pages/explore.vue2
-rw-r--r--packages/frontend/src/pages/role.vue27
-rw-r--r--packages/frontend/src/ui/deck.vue1
-rw-r--r--packages/frontend/src/ui/deck/column-core.vue2
-rw-r--r--packages/frontend/src/ui/deck/deck-store.ts1
-rw-r--r--packages/frontend/src/ui/deck/role-timeline-column.vue67
7 files changed, 105 insertions, 5 deletions
diff --git a/packages/frontend/src/components/MkTimeline.vue b/packages/frontend/src/components/MkTimeline.vue
index 6741e7a18b..fb0a3a4b67 100644
--- a/packages/frontend/src/components/MkTimeline.vue
+++ b/packages/frontend/src/components/MkTimeline.vue
@@ -15,6 +15,7 @@ const props = defineProps<{
list?: string;
antenna?: string;
channel?: string;
+ role?: string;
sound?: boolean;
}>();
@@ -121,6 +122,15 @@ if (props.src === 'antenna') {
channelId: props.channel,
});
connection.on('note', prepend);
+} else if (props.src === 'role') {
+ endpoint = 'roles/notes';
+ query = {
+ roleId: props.role,
+ };
+ connection = stream.useChannel('roleTimeline', {
+ roleId: props.role,
+ });
+ connection.on('note', prepend);
}
const pagination = {
diff --git a/packages/frontend/src/pages/explore.vue b/packages/frontend/src/pages/explore.vue
index 2131188dde..5f3728b677 100644
--- a/packages/frontend/src/pages/explore.vue
+++ b/packages/frontend/src/pages/explore.vue
@@ -1,7 +1,7 @@
<template>
<MkStickyContainer>
<template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template>
- <div class="lznhrdub">
+ <div>
<div v-if="tab === 'featured'">
<XFeatured/>
</div>
diff --git a/packages/frontend/src/pages/role.vue b/packages/frontend/src/pages/role.vue
index 2e9d3d6169..f2645394a2 100644
--- a/packages/frontend/src/pages/role.vue
+++ b/packages/frontend/src/pages/role.vue
@@ -1,13 +1,16 @@
<template>
<MkStickyContainer>
- <template #header><MkPageHeader/></template>
+ <template #header><MkPageHeader v-model:tab="tab" :tabs="headerTabs"/></template>
- <MkSpacer :content-max="1200">
+ <MkSpacer v-if="tab === 'users'" :content-max="1200">
<div class="_gaps_s">
<div v-if="role">{{ role.description }}</div>
<MkUserList :pagination="users" :extractor="(item) => item.user"/>
</div>
</MkSpacer>
+ <MkSpacer v-else-if="tab === 'timeline'" :content-max="700">
+ <MkTimeline ref="timeline" src="role" :role="props.role"/>
+ </MkSpacer>
</MkStickyContainer>
</template>
@@ -16,11 +19,17 @@ import { computed, watch } from 'vue';
import * as os from '@/os';
import MkUserList from '@/components/MkUserList.vue';
import { definePageMetadata } from '@/scripts/page-metadata';
+import { i18n } from '@/i18n';
+import MkTimeline from '@/components/MkTimeline.vue';
-const props = defineProps<{
+const props = withDefaults(defineProps<{
role: string;
-}>();
+ initialTab?: string;
+}>(), {
+ initialTab: 'users',
+});
+let tab = $ref(props.initialTab);
let role = $ref();
watch(() => props.role, () => {
@@ -39,6 +48,16 @@ const users = $computed(() => ({
},
}));
+const headerTabs = $computed(() => [{
+ key: 'users',
+ icon: 'ti ti-users',
+ title: i18n.ts.users,
+}, {
+ key: 'timeline',
+ icon: 'ti ti-pencil',
+ title: i18n.ts.timeline,
+}]);
+
definePageMetadata(computed(() => ({
title: role?.name,
icon: 'ti ti-badge',
diff --git a/packages/frontend/src/ui/deck.vue b/packages/frontend/src/ui/deck.vue
index 4db7c9413a..33e752513b 100644
--- a/packages/frontend/src/ui/deck.vue
+++ b/packages/frontend/src/ui/deck.vue
@@ -152,6 +152,7 @@ const addColumn = async (ev) => {
'channel',
'mentions',
'direct',
+ 'roleTimeline',
];
const { canceled, result: column } = await os.select({
diff --git a/packages/frontend/src/ui/deck/column-core.vue b/packages/frontend/src/ui/deck/column-core.vue
index 083e91bb03..8e7addf359 100644
--- a/packages/frontend/src/ui/deck/column-core.vue
+++ b/packages/frontend/src/ui/deck/column-core.vue
@@ -10,6 +10,7 @@
<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)"/>
+<XRoleTimelineColumn v-else-if="column.type === 'roleTimeline'" :column="column" :is-stacked="isStacked" @parent-focus="emit('parent-focus', $event)"/>
</template>
<script lang="ts" setup>
@@ -23,6 +24,7 @@ import XNotificationsColumn from './notifications-column.vue';
import XWidgetsColumn from './widgets-column.vue';
import XMentionsColumn from './mentions-column.vue';
import XDirectColumn from './direct-column.vue';
+import XRoleTimelineColumn from './role-timeline-column.vue';
import { Column } from './deck-store';
defineProps<{
diff --git a/packages/frontend/src/ui/deck/deck-store.ts b/packages/frontend/src/ui/deck/deck-store.ts
index 1420ad8b30..a6784e9849 100644
--- a/packages/frontend/src/ui/deck/deck-store.ts
+++ b/packages/frontend/src/ui/deck/deck-store.ts
@@ -22,6 +22,7 @@ export type Column = {
antennaId?: string;
listId?: string;
channelId?: string;
+ roleId?: string;
includingTypes?: typeof notificationTypes[number][];
tl?: 'home' | 'local' | 'social' | 'global';
};
diff --git a/packages/frontend/src/ui/deck/role-timeline-column.vue b/packages/frontend/src/ui/deck/role-timeline-column.vue
new file mode 100644
index 0000000000..5783b3f071
--- /dev/null
+++ b/packages/frontend/src/ui/deck/role-timeline-column.vue
@@ -0,0 +1,67 @@
+<template>
+<XColumn :menu="menu" :column="column" :is-stacked="isStacked" @parent-focus="$event => emit('parent-focus', $event)">
+ <template #header>
+ <i class="ti ti-badge"></i><span style="margin-left: 8px;">{{ column.name }}</span>
+ </template>
+
+ <MkTimeline v-if="column.roleId" ref="timeline" src="role" :role="column.roleId" @after="() => emit('loaded')"/>
+</XColumn>
+</template>
+
+<script lang="ts" setup>
+import { onMounted } from 'vue';
+import XColumn from './column.vue';
+import { updateColumn, Column } from './deck-store';
+import MkTimeline from '@/components/MkTimeline.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 MkTimeline>>();
+
+onMounted(() => {
+ if (props.column.roleId == null) {
+ setRole();
+ }
+});
+
+async function setRole() {
+ const roles = await os.api('roles/list');
+ const { canceled, result: role } = await os.select({
+ title: i18n.ts.role,
+ items: roles.map(x => ({
+ value: x, text: x.name,
+ })),
+ default: props.column.roleId,
+ });
+ if (canceled) return;
+ updateColumn(props.column.id, {
+ roleId: role.id,
+ });
+}
+
+const menu = [{
+ icon: 'ti ti-pencil',
+ text: i18n.ts.role,
+ action: setRole,
+}];
+
+/*
+function focus() {
+ timeline.focus();
+}
+
+defineExpose({
+ focus,
+});
+*/
+</script>