1
0
mirror of https://github.com/h3poteto/whalebird-desktop synced 2024-12-31 19:17:44 +01:00

Merge pull request #443 from h3poteto/iss-441

refs #441 Add scroll top button in timeline
This commit is contained in:
AkiraFukushima 2018-07-19 22:48:56 +09:00 committed by GitHub
commit c17b8ce575
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 221 additions and 52 deletions

View File

@ -35,6 +35,7 @@ export default {
width: 100%;
overflow: auto;
transition: all 0.5s;
scroll-behavior: smooth;
}
.timeline-wrapper-with-side-bar {
@ -42,6 +43,7 @@ export default {
width: -webkit-calc(100% - 320px);
overflow: auto;
transition: all 0.5s;
scroll-behavior: smooth;
}
}
</style>

View File

@ -1,22 +1,32 @@
<template>
<div id="favourites">
<div v-shortkey="{linux: ['ctrl', 'r'], mac: ['meta', 'r']}" @shortkey="reload()">
</div>
<div class="fav" v-for="message in favourites" v-bind:key="message.id">
<toot :message="message" :filter="filter" v-on:update="updateToot" v-on:delete="deleteToot"></toot>
</div>
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor">
</div>
<div id="favourites">
<div v-shortkey="{linux: ['ctrl', 'r'], mac: ['meta', 'r']}" @shortkey="reload()">
</div>
<div class="fav" v-for="message in favourites" v-bind:key="message.id">
<toot :message="message" :filter="filter" v-on:update="updateToot" v-on:delete="deleteToot"></toot>
</div>
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor">
</div>
<div class="upper" v-show="!heading">
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle>
</el-button>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
import Toot from './Cards/Toot'
import scrollTop from '../../utils/scroll'
export default {
name: 'favourites',
components: { Toot },
data () {
return {
heading: true
}
},
computed: {
...mapState({
backgroundColor: state => state.App.theme.background_color,
@ -77,6 +87,12 @@ export default {
})
})
}
// for upper
if ((event.target.scrollTop > 10) && this.heading) {
this.heading = false
} else if ((event.target.scrollTop <= 10) && !this.heading) {
this.heading = true
}
},
async reload () {
this.$store.commit('TimelineSpace/changeLoading', true)
@ -107,6 +123,12 @@ export default {
} finally {
this.$store.commit('TimelineSpace/changeLoading', false)
}
},
upper () {
scrollTop(
document.getElementById('scrollable'),
0
)
}
}
}
@ -120,4 +142,10 @@ export default {
.loading-card:empty {
height: 0;
}
.upper {
position: fixed;
bottom: 20px;
right: 20px;
}
</style>

View File

@ -9,12 +9,17 @@
</div>
</transition-group>
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor"></div>
<div class="upper" v-show="!heading">
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle>
</el-button>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
import Toot from '../Cards/Toot'
import scrollTop from '../../../utils/scroll'
export default {
name: 'tag',
@ -151,6 +156,12 @@ export default {
} finally {
this.$store.commit('TimelineSpace/changeLoading', false)
}
},
upper () {
scrollTop(
document.getElementById('scrollable'),
0
)
}
}
}
@ -178,5 +189,11 @@ export default {
.loading-card:empty {
height: 0;
}
.upper {
position: fixed;
bottom: 20px;
right: 20px;
}
</style>
<style src="@/assets/timeline-transition.scss"></style>

View File

@ -1,21 +1,26 @@
<template>
<div id="home">
<div class="unread">{{ unread.length > 0 ? unread.length : '' }}</div>
<div v-shortkey="{linux: ['ctrl', 'r'], mac: ['meta', 'r']}" @shortkey="reload()">
</div>
<transition-group name="timeline" tag="div">
<div class="home-timeline" v-for="(message, index) in timeline" v-bind:key="index">
<toot :message="message" :filter="filter" :key="message.id" v-on:update="updateToot" v-on:delete="deleteToot"></toot>
</div>
</transition-group>
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor">
</div>
<div id="home">
<div class="unread">{{ unread.length > 0 ? unread.length : '' }}</div>
<div v-shortkey="{linux: ['ctrl', 'r'], mac: ['meta', 'r']}" @shortkey="reload()">
</div>
<transition-group name="timeline" tag="div">
<div class="home-timeline" v-for="(message, index) in timeline" v-bind:key="index">
<toot :message="message" :filter="filter" :key="message.id" v-on:update="updateToot" v-on:delete="deleteToot"></toot>
</div>
</transition-group>
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor">
</div>
<div class="upper" v-show="!heading">
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle>
</el-button>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
import Toot from './Cards/Toot'
import scrollTop from '../../utils/scroll'
export default {
name: 'home',
@ -118,6 +123,12 @@ export default {
} finally {
this.$store.commit('TimelineSpace/changeLoading', false)
}
},
upper () {
scrollTop(
document.getElementById('scrollable'),
0
)
}
}
}
@ -146,6 +157,12 @@ export default {
.loading-card:empty {
height: 0;
}
.upper {
position: fixed;
bottom: 20px;
right: 20px;
}
}
</style>
<style src="@/assets/timeline-transition.scss"></style>

View File

@ -9,12 +9,17 @@
</div>
</transition-group>
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor"></div>
<div class="upper" v-show="!heading">
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle>
</el-button>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
import Toot from '../Cards/Toot'
import scrollTop from '../../../utils/scroll'
export default {
name: 'list',
@ -147,6 +152,12 @@ export default {
} finally {
this.$store.commit('TimelineSpace/changeLoading', false)
}
},
upper () {
scrollTop(
document.getElementById('scrollable'),
0
)
}
}
}
@ -174,5 +185,11 @@ export default {
.loading-card:empty {
height: 0;
}
.upper {
position: fixed;
bottom: 20px;
right: 20px;
}
</style>
<style src="@/assets/timeline-transition.scss"></style>

View File

@ -1,21 +1,26 @@
<template>
<div id="local">
<div class="unread">{{ unread.length > 0 ? unread.length : '' }}</div>
<div v-shortkey="{linux: ['ctrl', 'r'], mac: ['meta', 'r']}" @shortkey="reload()">
</div>
<transition-group name="timeline" tag="div">
<div class="local-timeline" v-for="message in timeline" v-bind:key="message.id">
<toot :message="message" :filter="filter" v-on:update="updateToot" v-on:delete="deleteToot"></toot>
</div>
</transition-group>
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor">
</div>
<div id="local">
<div class="unread">{{ unread.length > 0 ? unread.length : '' }}</div>
<div v-shortkey="{linux: ['ctrl', 'r'], mac: ['meta', 'r']}" @shortkey="reload()">
</div>
<transition-group name="timeline" tag="div">
<div class="local-timeline" v-for="message in timeline" v-bind:key="message.id">
<toot :message="message" :filter="filter" v-on:update="updateToot" v-on:delete="deleteToot"></toot>
</div>
</transition-group>
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor">
</div>
<div class="upper" v-show="!heading">
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle>
</el-button>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
import Toot from './Cards/Toot'
import scrollTop from '../../utils/scroll'
export default {
name: 'local',
@ -117,6 +122,12 @@ export default {
} finally {
this.$store.commit('TimelineSpace/changeLoading', false)
}
},
upper () {
scrollTop(
document.getElementById('scrollable'),
0
)
}
}
}
@ -145,6 +156,12 @@ export default {
.loading-card:empty {
height: 0;
}
.upper {
position: fixed;
bottom: 20px;
right: 20px;
}
}
</style>
<style src="@/assets/timeline-transition.scss"></style>

View File

@ -1,21 +1,26 @@
<template>
<div id="notifications">
<div class="unread">{{ unread.length > 0 ? unread.length : '' }}</div>
<div v-shortkey="{linux: ['ctrl', 'r'], mac: ['meta', 'r']}" @shortkey="reload()">
</div>
<transition-group name="timeline" tag="div">
<div class="notifications" v-for="message in notifications" v-bind:key="message.id">
<notification :message="message" :filter="filter"></notification>
</div>
</transition-group>
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor">
</div>
<div id="notifications">
<div class="unread">{{ unread.length > 0 ? unread.length : '' }}</div>
<div v-shortkey="{linux: ['ctrl', 'r'], mac: ['meta', 'r']}" @shortkey="reload()">
</div>
<transition-group name="timeline" tag="div">
<div class="notifications" v-for="message in notifications" v-bind:key="message.id">
<notification :message="message" :filter="filter"></notification>
</div>
</transition-group>
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor">
</div>
<div class="upper" v-show="!heading">
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle>
</el-button>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
import Notification from './Cards/Notification'
import scrollTop from '../../utils/scroll'
export default {
name: 'notifications',
@ -107,6 +112,12 @@ export default {
} finally {
this.$store.commit('TimelineSpace/changeLoading', false)
}
},
upper () {
scrollTop(
document.getElementById('scrollable'),
0
)
}
}
}
@ -135,6 +146,12 @@ export default {
.loading-card:empty {
height: 0;
}
.upper {
position: fixed;
bottom: 20px;
right: 20px;
}
}
</style>
<style src="@/assets/timeline-transition.scss"></style>

View File

@ -1,21 +1,26 @@
<template>
<div id="public">
<div class="unread">{{ unread.length > 0 ? unread.length : '' }}</div>
<div v-shortkey="{linux: ['ctrl', 'r'], mac: ['meta', 'r']}" @shortkey="reload()">
</div>
<transition-group name="timeline" tag="div">
<div class="public-timeline" v-for="message in timeline" v-bind:key="message.id">
<toot :message="message" :filter="filter" v-on:update="updateToot" v-on:delete="deleteToot"></toot>
</div>
</transition-group>
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor">
</div>
<div id="public">
<div class="unread">{{ unread.length > 0 ? unread.length : '' }}</div>
<div v-shortkey="{linux: ['ctrl', 'r'], mac: ['meta', 'r']}" @shortkey="reload()">
</div>
<transition-group name="timeline" tag="div">
<div class="public-timeline" v-for="message in timeline" v-bind:key="message.id">
<toot :message="message" :filter="filter" v-on:update="updateToot" v-on:delete="deleteToot"></toot>
</div>
</transition-group>
<div class="loading-card" v-loading="lazyLoading" :element-loading-background="backgroundColor">
</div>
<div class="upper" v-show="!heading">
<el-button type="primary" icon="el-icon-arrow-up" @click="upper" circle>
</el-button>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
import Toot from './Cards/Toot'
import scrollTop from '../../utils/scroll'
export default {
name: 'public',
@ -140,6 +145,12 @@ export default {
} finally {
this.$store.commit('TimelineSpace/changeLoading', false)
}
},
upper () {
scrollTop(
document.getElementById('scrollable'),
0
)
}
}
}
@ -168,6 +179,12 @@ export default {
.loading-card:empty {
height: 0;
}
.upper {
position: fixed;
bottom: 20px;
right: 20px;
}
}
</style>
<style src="@/assets/timeline-transition.scss"></style>

View File

@ -0,0 +1,37 @@
/**
* Scroll to top of the element.
* @param element a target dom element
* @param point scroll target point of the element
**/
export default function scrollTop (element, point = 0) {
const start = element.scrollTop
const range = start - point
// Progress of scroll: 0 ~ 100
let progress = 0
/**
* Scroll calling recursion.
**/
const move = function () {
progress++
const nextPos = start - range * (range / 200) * easeOut(progress / 100)
// Stop the recursion
if (nextPos <= 0) {
element.scrollTop = 0
return
}
element.scrollTop = nextPos
requestAnimationFrame(move)
}
requestAnimationFrame(move)
}
/**
* easeOut
**/
const easeOut = function (p) {
return p * (2 - p)
}