タイムラインを特定の日付にジャンプする機能
This commit is contained in:
parent
b0757129d5
commit
f3aef8df75
|
@ -707,6 +707,9 @@ emailNotification: "メール通知"
|
||||||
inChannelSearch: "チャンネル内検索"
|
inChannelSearch: "チャンネル内検索"
|
||||||
useReactionPickerForContextMenu: "右クリックでリアクションピッカーを開く"
|
useReactionPickerForContextMenu: "右クリックでリアクションピッカーを開く"
|
||||||
typingUsers: "{users}が入力中"
|
typingUsers: "{users}が入力中"
|
||||||
|
jumpToSpecifiedDate: "特定の日付にジャンプ"
|
||||||
|
showingPastTimeline: "過去のタイムラインを表示しています"
|
||||||
|
clear: "クリア"
|
||||||
|
|
||||||
_email:
|
_email:
|
||||||
_follow:
|
_follow:
|
||||||
|
|
|
@ -99,6 +99,9 @@
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<div class="instance">{{ instanceName }}</div>
|
<div class="instance">{{ instanceName }}</div>
|
||||||
<XHeaderClock class="clock"/>
|
<XHeaderClock class="clock"/>
|
||||||
|
<button class="_button button timetravel" @click="timetravel" v-tooltip="$ts.jumpToSpecifiedDate">
|
||||||
|
<Fa :icon="faCalendarAlt"/>
|
||||||
|
</button>
|
||||||
<button class="_button button search" v-if="tl.startsWith('channel:') && currentChannel" @click="inChannelSearch" v-tooltip="$ts.inChannelSearch">
|
<button class="_button button search" v-if="tl.startsWith('channel:') && currentChannel" @click="inChannelSearch" v-tooltip="$ts.inChannelSearch">
|
||||||
<Fa :icon="faSearch"/>
|
<Fa :icon="faSearch"/>
|
||||||
</button>
|
</button>
|
||||||
|
@ -115,8 +118,8 @@
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<XTimeline class="body" v-if="tl.startsWith('channel:')" src="channel" :key="tl" :channel="tl.replace('channel:', '')"/>
|
<XTimeline class="body" ref="tl" v-if="tl.startsWith('channel:')" src="channel" :key="tl" :channel="tl.replace('channel:', '')"/>
|
||||||
<XTimeline class="body" v-else :src="tl" :key="tl"/>
|
<XTimeline class="body" ref="tl" v-else :src="tl" :key="tl"/>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<XSide class="side" ref="side" @open="sideViewOpening = true" @close="sideViewOpening = false"/>
|
<XSide class="side" ref="side" @open="sideViewOpening = true" @close="sideViewOpening = false"/>
|
||||||
|
@ -131,7 +134,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, defineAsyncComponent } from 'vue';
|
import { defineComponent, defineAsyncComponent } from 'vue';
|
||||||
import { faLayerGroup, faBars, faHome, faCircle, faWindowMaximize, faColumns, faPencilAlt, faShareAlt, faSatelliteDish, faListUl, faSatellite, faCog, faSearch, faPlus, faStar, faAt, faLink, faEllipsisH, faGlobe } from '@fortawesome/free-solid-svg-icons';
|
import { faLayerGroup, faBars, faHome, faCircle, faWindowMaximize, faColumns, faPencilAlt, faShareAlt, faSatelliteDish, faListUl, faSatellite, faCog, faSearch, faPlus, faStar, faAt, faLink, faEllipsisH, faGlobe } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faBell, faStar as farStar, faEnvelope, faComments } from '@fortawesome/free-regular-svg-icons';
|
import { faBell, faStar as farStar, faEnvelope, faComments, faCalendarAlt } from '@fortawesome/free-regular-svg-icons';
|
||||||
import { instanceName, url } from '@/config';
|
import { instanceName, url } from '@/config';
|
||||||
import XSidebar from '@/components/sidebar.vue';
|
import XSidebar from '@/components/sidebar.vue';
|
||||||
import XWidgets from './widgets.vue';
|
import XWidgets from './widgets.vue';
|
||||||
|
@ -192,7 +195,7 @@ export default defineComponent({
|
||||||
menuDef: sidebarDef,
|
menuDef: sidebarDef,
|
||||||
sideViewOpening: false,
|
sideViewOpening: false,
|
||||||
instanceName,
|
instanceName,
|
||||||
faLayerGroup, faBars, faBell, faHome, faCircle, faPencilAlt, faShareAlt, faSatelliteDish, faListUl, faSatellite, faCog, faSearch, faPlus, faStar, farStar, faAt, faLink, faEllipsisH, faGlobe, faComments, faEnvelope,
|
faLayerGroup, faBars, faBell, faHome, faCircle, faPencilAlt, faShareAlt, faSatelliteDish, faListUl, faSatellite, faCog, faSearch, faPlus, faStar, farStar, faAt, faLink, faEllipsisH, faGlobe, faComments, faEnvelope, faCalendarAlt,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -244,6 +247,18 @@ export default defineComponent({
|
||||||
os.post();
|
os.post();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async timetravel() {
|
||||||
|
const { canceled, result: date } = await os.dialog({
|
||||||
|
title: this.$ts.date,
|
||||||
|
input: {
|
||||||
|
type: 'date'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (canceled) return;
|
||||||
|
|
||||||
|
this.$refs.tl.timetravel(new Date(date));
|
||||||
|
},
|
||||||
|
|
||||||
search() {
|
search() {
|
||||||
search();
|
search();
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
|
<div class="dbiokgaf info" v-if="date">
|
||||||
|
<MkInfo>{{ $ts.showingPastTimeline }} <button class="_textButton clear" @click="timetravel()">{{ $ts.clear }}</button></MkInfo>
|
||||||
|
</div>
|
||||||
<div class="dbiokgaf top" v-if="['home', 'local', 'social', 'global'].includes(src)">
|
<div class="dbiokgaf top" v-if="['home', 'local', 'social', 'global'].includes(src)">
|
||||||
<XPostForm/>
|
<XPostForm/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,11 +30,13 @@ import * as sound from '@/scripts/sound';
|
||||||
import { scrollToBottom, getScrollPosition, getScrollContainer } from '@/scripts/scroll';
|
import { scrollToBottom, getScrollPosition, getScrollContainer } from '@/scripts/scroll';
|
||||||
import follow from '@/directives/follow-append';
|
import follow from '@/directives/follow-append';
|
||||||
import XPostForm from './post-form.vue';
|
import XPostForm from './post-form.vue';
|
||||||
|
import MkInfo from '@/components/ui/info.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
XNotes,
|
XNotes,
|
||||||
XPostForm,
|
XPostForm,
|
||||||
|
MkInfo,
|
||||||
},
|
},
|
||||||
|
|
||||||
directives: {
|
directives: {
|
||||||
|
@ -81,6 +86,7 @@ export default defineComponent({
|
||||||
top: 0,
|
top: 0,
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
typers: [],
|
typers: [],
|
||||||
|
date: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -186,7 +192,7 @@ export default defineComponent({
|
||||||
reversed,
|
reversed,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
params: init => ({
|
params: init => ({
|
||||||
untilDate: init ? undefined : (this.date ? this.date.getTime() : undefined),
|
untilDate: this.date?.getTime(),
|
||||||
...this.baseQuery, ...this.query
|
...this.baseQuery, ...this.query
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
@ -220,11 +226,20 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
this.queue = q;
|
this.queue = q;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
timetravel(date?: Date) {
|
||||||
|
this.date = date;
|
||||||
|
this.$refs.tl.reload();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.dbiokgaf.info{
|
||||||
|
padding: 16px 16px 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
.dbiokgaf.top {
|
.dbiokgaf.top {
|
||||||
padding: 16px 16px 0 16px;
|
padding: 16px 16px 0 16px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ export default define(meta, async (ps, user) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
//#region Construct query
|
//#region Construct query
|
||||||
const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
|
const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate)
|
||||||
.andWhere('note.channelId = :channelId', { channelId: channel.id })
|
.andWhere('note.channelId = :channelId', { channelId: channel.id })
|
||||||
.leftJoinAndSelect('note.user', 'user')
|
.leftJoinAndSelect('note.user', 'user')
|
||||||
.leftJoinAndSelect('note.channel', 'channel');
|
.leftJoinAndSelect('note.channel', 'channel');
|
||||||
|
|
Loading…
Reference in New Issue