mirror of
https://iceshrimp.dev/limepotato/jormungandr-bite.git
synced 2024-11-14 14:07:38 -07:00
Resolve #5942
This commit is contained in:
parent
c15e22128d
commit
7bb49f1352
5 changed files with 100 additions and 27 deletions
|
@ -4,6 +4,7 @@ ChangeLog
|
||||||
unreleased
|
unreleased
|
||||||
-------------------
|
-------------------
|
||||||
### ✨Improvements
|
### ✨Improvements
|
||||||
|
* 投稿詳細ページで前後の投稿を見れるように
|
||||||
* 自分のfollowersノートはRenoteできるように
|
* 自分のfollowersノートはRenoteできるように
|
||||||
* フォロー申請ページの調整
|
* フォロー申請ページの調整
|
||||||
* 壁紙設定の強化
|
* 壁紙設定の強化
|
||||||
|
|
|
@ -7,16 +7,23 @@
|
||||||
|
|
||||||
<mk-error v-if="error" @retry="init()"/>
|
<mk-error v-if="error" @retry="init()"/>
|
||||||
|
|
||||||
<x-list ref="notes" class="notes" :items="notes" v-slot="{ item: note }">
|
<div class="more" v-if="more && reversed" style="margin-bottom: var(--margin);">
|
||||||
<x-note :note="note" :detail="detail" :key="note.id"/>
|
|
||||||
</x-list>
|
|
||||||
|
|
||||||
<footer class="more" v-if="more">
|
|
||||||
<mk-button class="button" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" @click="fetchMore()" primary>
|
<mk-button class="button" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" @click="fetchMore()" primary>
|
||||||
<template v-if="!moreFetching">{{ $t('loadMore') }}</template>
|
<template v-if="!moreFetching">{{ $t('loadMore') }}</template>
|
||||||
<template v-if="moreFetching"><mk-loading inline/></template>
|
<template v-if="moreFetching"><mk-loading inline/></template>
|
||||||
</mk-button>
|
</mk-button>
|
||||||
</footer>
|
</div>
|
||||||
|
|
||||||
|
<x-list ref="notes" class="notes" :items="notes" v-slot="{ item: note }" :direction="reversed ? 'up' : 'down'" :reversed="reversed">
|
||||||
|
<x-note :note="note" :detail="detail" :key="note.id"/>
|
||||||
|
</x-list>
|
||||||
|
|
||||||
|
<div class="more" v-if="more && !reversed" style="margin-top: var(--margin);">
|
||||||
|
<mk-button class="button" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" @click="fetchMore()" primary>
|
||||||
|
<template v-if="!moreFetching">{{ $t('loadMore') }}</template>
|
||||||
|
<template v-if="moreFetching"><mk-loading inline/></template>
|
||||||
|
</mk-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -67,6 +74,10 @@ export default Vue.extend({
|
||||||
notes(): any[] {
|
notes(): any[] {
|
||||||
return this.extract ? this.extract(this.items) : this.items;
|
return this.extract ? this.extract(this.items) : this.items;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
reversed(): boolean {
|
||||||
|
return this.pagination.reversed;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -92,14 +103,14 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
|
|
||||||
> .notes {
|
> .notes {
|
||||||
> ::v-deep * {
|
> ::v-deep *:not(:last-child) {
|
||||||
margin-bottom: var(--marginFull);
|
margin-bottom: var(--marginFull);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.max-width_500px {
|
&.max-width_500px {
|
||||||
> .notes {
|
> .notes {
|
||||||
> ::v-deep * {
|
> ::v-deep *:not(:last-child) {
|
||||||
margin-bottom: var(--marginHalf);
|
margin-bottom: var(--marginHalf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,19 +4,32 @@
|
||||||
<portal to="title" v-if="note">{{ $t('noteOf', { user: note.user.name }) }}</portal>
|
<portal to="title" v-if="note">{{ $t('noteOf', { user: note.user.name }) }}</portal>
|
||||||
|
|
||||||
<transition name="zoom" mode="out-in">
|
<transition name="zoom" mode="out-in">
|
||||||
<x-note v-if="note" :note="note" :key="note.id" :detail="true"/>
|
<div v-if="note">
|
||||||
<div v-else-if="error">
|
<mk-button v-if="hasNext && !showNext" @click="showNext = true" primary style="margin: 0 auto var(--margin) auto;"><fa :icon="faChevronUp"/></mk-button>
|
||||||
|
<x-notes v-if="showNext" ref="next" :pagination="next"/>
|
||||||
|
<hr v-if="showNext"/>
|
||||||
|
|
||||||
|
<x-note :note="note" :key="note.id" :detail="true"/>
|
||||||
|
<div v-if="error">
|
||||||
<mk-error @retry="fetch()"/>
|
<mk-error @retry="fetch()"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<mk-button v-if="hasPrev && !showPrev" @click="showPrev = true" primary style="margin: var(--margin) auto 0 auto;"><fa :icon="faChevronDown"/></mk-button>
|
||||||
|
<hr v-if="showPrev"/>
|
||||||
|
<x-notes v-if="showPrev" ref="prev" :pagination="prev" style="margin-top: var(--margin);"/>
|
||||||
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import { faChevronUp, faChevronDown } from '@fortawesome/free-solid-svg-icons';
|
||||||
import i18n from '../i18n';
|
import i18n from '../i18n';
|
||||||
import Progress from '../scripts/loading';
|
import Progress from '../scripts/loading';
|
||||||
import XNote from '../components/note.vue';
|
import XNote from '../components/note.vue';
|
||||||
|
import XNotes from '../components/notes.vue';
|
||||||
|
import MkButton from '../components/ui/button.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n,
|
i18n,
|
||||||
|
@ -26,12 +39,36 @@ export default Vue.extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
XNote
|
XNote,
|
||||||
|
XNotes,
|
||||||
|
MkButton,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
note: null,
|
note: null,
|
||||||
|
hasPrev: false,
|
||||||
|
hasNext: false,
|
||||||
|
showPrev: false,
|
||||||
|
showNext: false,
|
||||||
error: null,
|
error: null,
|
||||||
|
prev: {
|
||||||
|
endpoint: 'users/notes',
|
||||||
|
limit: 10,
|
||||||
|
params: init => ({
|
||||||
|
userId: this.note.userId,
|
||||||
|
untilId: this.note.id,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
next: {
|
||||||
|
reversed: true,
|
||||||
|
endpoint: 'users/notes',
|
||||||
|
limit: 10,
|
||||||
|
params: init => ({
|
||||||
|
userId: this.note.userId,
|
||||||
|
sinceId: this.note.id,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
faChevronUp, faChevronDown
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -46,7 +83,22 @@ export default Vue.extend({
|
||||||
this.$root.api('notes/show', {
|
this.$root.api('notes/show', {
|
||||||
noteId: this.$route.params.note
|
noteId: this.$route.params.note
|
||||||
}).then(note => {
|
}).then(note => {
|
||||||
|
Promise.all([
|
||||||
|
this.$root.api('users/notes', {
|
||||||
|
userId: note.userId,
|
||||||
|
untilId: note.id,
|
||||||
|
limit: 1,
|
||||||
|
}),
|
||||||
|
this.$root.api('users/notes', {
|
||||||
|
userId: note.userId,
|
||||||
|
sinceId: note.id,
|
||||||
|
limit: 1,
|
||||||
|
}),
|
||||||
|
]).then(([prev, next]) => {
|
||||||
|
this.hasPrev = prev.length !== 0;
|
||||||
|
this.hasNext = next.length !== 0;
|
||||||
this.note = note;
|
this.note = note;
|
||||||
|
});
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
this.error = e;
|
this.error = e;
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
|
|
|
@ -64,18 +64,18 @@ export default (opts) => ({
|
||||||
if (params && params.then) params = await params;
|
if (params && params.then) params = await params;
|
||||||
const endpoint = typeof this.pagination.endpoint === 'function' ? this.pagination.endpoint() : this.pagination.endpoint;
|
const endpoint = typeof this.pagination.endpoint === 'function' ? this.pagination.endpoint() : this.pagination.endpoint;
|
||||||
await this.$root.api(endpoint, {
|
await this.$root.api(endpoint, {
|
||||||
|
...params,
|
||||||
limit: this.pagination.noPaging ? (this.pagination.limit || 10) : (this.pagination.limit || 10) + 1,
|
limit: this.pagination.noPaging ? (this.pagination.limit || 10) : (this.pagination.limit || 10) + 1,
|
||||||
...params
|
}).then(items => {
|
||||||
}).then(x => {
|
if (!this.pagination.noPaging && (items.length === (this.pagination.limit || 10) + 1)) {
|
||||||
if (!this.pagination.noPaging && (x.length === (this.pagination.limit || 10) + 1)) {
|
items.pop();
|
||||||
x.pop();
|
this.items = this.pagination.reversed ? [...items].reverse() : items;
|
||||||
this.items = x;
|
|
||||||
this.more = true;
|
this.more = true;
|
||||||
} else {
|
} else {
|
||||||
this.items = x;
|
this.items = this.pagination.reversed ? [...items].reverse() : items;
|
||||||
this.more = false;
|
this.more = false;
|
||||||
}
|
}
|
||||||
this.offset = x.length;
|
this.offset = items.length;
|
||||||
this.inited = true;
|
this.inited = true;
|
||||||
this.fetching = false;
|
this.fetching = false;
|
||||||
if (opts.after) opts.after(this, null);
|
if (opts.after) opts.after(this, null);
|
||||||
|
@ -93,23 +93,25 @@ export default (opts) => ({
|
||||||
if (params && params.then) params = await params;
|
if (params && params.then) params = await params;
|
||||||
const endpoint = typeof this.pagination.endpoint === 'function' ? this.pagination.endpoint() : this.pagination.endpoint;
|
const endpoint = typeof this.pagination.endpoint === 'function' ? this.pagination.endpoint() : this.pagination.endpoint;
|
||||||
await this.$root.api(endpoint, {
|
await this.$root.api(endpoint, {
|
||||||
|
...params,
|
||||||
limit: SECOND_FETCH_LIMIT + 1,
|
limit: SECOND_FETCH_LIMIT + 1,
|
||||||
...(this.pagination.offsetMode ? {
|
...(this.pagination.offsetMode ? {
|
||||||
offset: this.offset,
|
offset: this.offset,
|
||||||
|
} : this.pagination.reversed ? {
|
||||||
|
sinceId: this.items[0].id,
|
||||||
} : {
|
} : {
|
||||||
untilId: this.items[this.items.length - 1].id,
|
untilId: this.items[this.items.length - 1].id,
|
||||||
}),
|
}),
|
||||||
...params
|
}).then(items => {
|
||||||
}).then(x => {
|
if (items.length === SECOND_FETCH_LIMIT + 1) {
|
||||||
if (x.length === SECOND_FETCH_LIMIT + 1) {
|
items.pop();
|
||||||
x.pop();
|
this.items = this.pagination.reversed ? [...items].reverse().concat(this.items) : this.items.concat(items);
|
||||||
this.items = this.items.concat(x);
|
|
||||||
this.more = true;
|
this.more = true;
|
||||||
} else {
|
} else {
|
||||||
this.items = this.items.concat(x);
|
this.items = this.pagination.reversed ? [...items].reverse().concat(this.items) : this.items.concat(items);
|
||||||
this.more = false;
|
this.more = false;
|
||||||
}
|
}
|
||||||
this.offset += x.length;
|
this.offset += items.length;
|
||||||
this.moreFetching = false;
|
this.moreFetching = false;
|
||||||
}, e => {
|
}, e => {
|
||||||
this.moreFetching = false;
|
this.moreFetching = false;
|
||||||
|
|
|
@ -128,6 +128,13 @@ a {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
margin: var(--margin) 0 var(--margin) 0;
|
||||||
|
border: none;
|
||||||
|
height: 1px;
|
||||||
|
background: var(--divider);
|
||||||
|
}
|
||||||
|
|
||||||
#nprogress {
|
#nprogress {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
Loading…
Reference in a new issue