Add scrolling and marking as read (local only)

This commit is contained in:
Peter Stuifzand 2018-08-27 22:21:20 +02:00
parent 2b9d086948
commit 746ef03a63
6 changed files with 77 additions and 34 deletions

View File

@ -7,7 +7,7 @@
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>ekstereye</title> <title>ekstereye</title>
</head> </head>
<body> <body class="has-navbar-fixed-top">
<noscript> <noscript>
<strong>We're sorry but ekstereye doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> <strong>We're sorry but ekstereye doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript> </noscript>

View File

@ -1,6 +1,6 @@
<template> <template>
<div id="app"> <div id="app">
<nav id="nav" class="navbar is-primary"> <nav id="nav" class="navbar is-primary is-fixed-top">
<div class="container"> <div class="container">
<div class="navbar-brand"> <div class="navbar-brand">
<router-link to="/" class="navbar-item">Ekster</router-link> <router-link to="/" class="navbar-item">Ekster</router-link>
@ -19,9 +19,8 @@
</nav> </nav>
<div class="container"> <div class="container">
<router-view/> <router-view/>
<LoginModal :active="!this.$store.state.logged_in"></LoginModal>
</div> </div>
<LoginModal :active="!this.$store.state.logged_in"></LoginModal>
</div> </div>
</template> </template>

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="entry card"> <div :class="classes">
<div class="card-image" v-if="photo_first"> <div class="card-image" v-if="photo_first">
<figure class="image is-4by3"> <figure class="image">
<img :src="photo_first"/> <img :src="photo_first"/>
</figure> </figure>
</div> </div>
@ -27,7 +27,7 @@
<div class="debug" v-text="item" v-if="this.$store.state.debug"></div> <div class="debug" v-text="item" v-if="this.$store.state.debug"></div>
<a :href="item.url"> <a :href="item.url" target="_new">
<span class="published" v-html="item.published"></span> <span class="published" v-html="item.published"></span>
</a> </a>
</div> </div>
@ -42,6 +42,9 @@
props: ['item'], props: ['item'],
computed: { computed: {
classes() {
return {'entry': true, 'card': true, 'unread': !this.item._is_read}
},
main_content() { main_content() {
let content = this.item.content let content = this.item.content
if (content) { if (content) {
@ -89,6 +92,11 @@
<style scoped> <style scoped>
.entry { .entry {
border: 1px solid #ccc;
}
.unread {
box-shadow: 0 4px 8px 0 rgba(255, 255, 0, 0.8), 0 6px 20px 0 rgba(255, 255, 0, 0.5);
} }
.photos { .photos {

View File

@ -3,7 +3,6 @@
<div class="timeline--item" v-for="item in items" :key="item.id"> <div class="timeline--item" v-for="item in items" :key="item.id">
<TimelineEntry :item="item"/> <TimelineEntry :item="item"/>
</div> </div>
<div class="level"> <div class="level">
<div class="level-item"> <div class="level-item">
<button class="button" @click="prevPage" v-if="timeline.paging.before">Prev Page</button> <button class="button" @click="prevPage" v-if="timeline.paging.before">Prev Page</button>
@ -24,7 +23,7 @@
components: {TimelineEntry}, components: {TimelineEntry},
computed: { computed: {
items () { items() {
return this.timeline.items.filter((item) => { return this.timeline.items.filter((item) => {
return item.type === 'entry'; return item.type === 'entry';
}) })
@ -33,11 +32,32 @@
methods: { methods: {
nextPage() { nextPage() {
this.$emit('getPage', {uid: this.channel.uid, after: this.timeline.paging.after}) if (this.timeline.paging.after) {
this.$emit('getPage', {uid: this.channel.uid, after: this.timeline.paging.after})
}
}, },
prevPage() { prevPage() {
this.$emit('getPage', {uid: this.channel.uid, before: this.timeline.paging.before}) this.$emit('getPage', {uid: this.channel.uid, before: this.timeline.paging.before})
} }
},
mounted() {
window.onscroll = () => {
// let bottomOfWindow = document.documentElement.scrollTop + window.innerHeight === document.documentElement.offsetHeight;
let bottomOfWindow = document.documentElement.scrollTop + window.innerHeight === this.$el.offsetHeight + document.documentElement.offsetHeight + 20;
if (bottomOfWindow) {
this.$children.forEach((child) => {
child.$props.item._is_read = true
})
}
this.$children.forEach((child) => {
let rect = child.$el.getBoundingClientRect()
if (rect.top+rect.height < 100) {
child.$props.item._is_read = true
}
})
}
} }
} }
</script> </script>

View File

@ -22,14 +22,21 @@ export default new Vuex.Store({
state.channels = channels state.channels = channels
}, },
newTimeline(state, {channel, timeline}) { newTimeline(state, {channel, timeline}) {
state.timeline = timeline
state.channel = channel state.channel = channel
state.timeline = timeline
}, },
newAccessToken(state, {me, access_token, scope}) { newAccessToken(state, {me, access_token, scope}) {
state.logged_in = true state.logged_in = true
state.scope = scope state.scope = scope
state.me = me state.me = me
state.access_token = access_token state.access_token = access_token
},
clearTimeline(state, {channel}) {
state.channel = channel
state.timeline = {
items: [],
paging: {}
}
} }
}, },
@ -45,6 +52,9 @@ export default new Vuex.Store({
commit('newChannels', response.channels) commit('newChannels', response.channels)
}) })
}, },
switchChannel({commit}, channel) {
commit('clearTimeline', {channel: channel})
},
fetchTimeline({commit}, channel) { fetchTimeline({commit}, channel) {
let url = 'https://microsub.stuifzandapp.com/microsub?action=timeline&channel=' + channel.uid let url = 'https://microsub.stuifzandapp.com/microsub?action=timeline&channel=' + channel.uid
if (channel.after) { if (channel.after) {

View File

@ -1,18 +1,13 @@
<template> <template>
<div class="home"> <div class="home">
<div class="columns"> <Channels class="channels" :channels="this.$store.state.channels">
<div class="column is-2"> <div slot-scope="{ channel }">
<Channels class="channels" :channels="this.$store.state.channels"> <Channel :channel="channel" @channel-selected="selectChannel"></Channel>
<div slot-scope="{ channel }">
<Channel :channel="channel" @channel-selected="selectChannel"></Channel>
</div>
</Channels>
</div> </div>
<div class="column"> </Channels>
<Timeline class="timeline" :timeline="this.$store.state.timeline" :channel="this.$store.state.channel"
@getPage="getPage"></Timeline> <Timeline class="timeline" :timeline="this.$store.state.timeline" :channel="this.$store.state.channel"
</div> @getPage="getPage"></Timeline>
</div>
</div> </div>
</template> </template>
@ -30,12 +25,6 @@
Channel Channel
}, },
data() {
return {
showChannels: false
}
},
computed: { computed: {
uid() { uid() {
return this.$route.params.uid || 'home'; return this.$route.params.uid || 'home';
@ -44,13 +33,16 @@
methods: { methods: {
selectChannel(channel) { selectChannel(channel) {
this.$store.dispatch('fetchTimeline', channel) this.$store.dispatch('switchChannel', channel).then(() => {
this.showChannels = false this.$store.dispatch('fetchTimeline', channel).then(() => {
window.scrollTo({top: 0}) window.scrollTo({top: 0})
})
})
}, },
getPage(next) { getPage(next) {
this.$store.dispatch('fetchTimeline', next) this.$store.dispatch('fetchTimeline', next).then(() => {
window.scrollTo({top: 0}) window.scrollTo({top: 0})
})
} }
}, },
@ -67,5 +59,19 @@
.timeline { .timeline {
margin-top: 20px; margin-top: 20px;
width: 600px; width: 600px;
position: absolute;
left: 270px;
padding-bottom: 100px;
}
.channels {
position: fixed;
top: 52px;
height: calc(100vh - 52px);
width: 250px;
overflow-y: scroll;
overflow-x: hidden;
padding-bottom: 100px;
} }
</style> </style>