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:
commit
c17b8ce575
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
37
src/renderer/components/utils/scroll.js
Normal file
37
src/renderer/components/utils/scroll.js
Normal 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)
|
||||
}
|
Loading…
Reference in New Issue
Block a user