Compare commits

..

No commits in common. "8aa4f6882accef549e198b54be1cf579a522884c" and "0316db4072a4d8baeccc8df71633a6d3175d7ddf" have entirely different histories.

12 changed files with 215 additions and 615 deletions

622
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -8,17 +8,15 @@
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"@primer/css": "^14.1.0",
"bulma": "^0.7.5", "bulma": "^0.7.5",
"event-source-polyfill": "0.0.16", "event-source-polyfill": "0.0.16",
"isomorphic-fetch": "^2.2.1", "isomorphic-fetch": "^2.2.1",
"lodash": "latest", "lodash": "latest",
"micropub-helper": "^1.4.0", "micropub-helper": "^1.4.0",
"moment": "^2.22.2", "moment": "^2.22.2",
"node-sass": "^4.14.1", "node-sass": "^4.12.0",
"rel-scraper": "github:grantcodes/rel-scraper", "rel-scraper": "github:grantcodes/rel-scraper",
"sass-loader": "^7.2.0", "sass-loader": "^7.2.0",
"tailwindcss": "1.1.4",
"vue": "^2.5.17", "vue": "^2.5.17",
"vue-router": "^3.0.1", "vue-router": "^3.0.1",
"vuex": "^3.0.1" "vuex": "^3.0.1"
@ -27,8 +25,6 @@
"@vue/cli-plugin-babel": "^3.10.0", "@vue/cli-plugin-babel": "^3.10.0",
"@vue/cli-plugin-eslint": "^3.0.0-rc.10", "@vue/cli-plugin-eslint": "^3.0.0-rc.10",
"@vue/cli-service": "^3.10.0", "@vue/cli-service": "^3.10.0",
"postcss-node-sass": "^2.1.8",
"postcss-scss": "^2.0.0",
"vue-template-compiler": "^2.5.17" "vue-template-compiler": "^2.5.17"
}, },
"eslintConfig": { "eslintConfig": {

View File

@ -35,7 +35,6 @@
if (item) { if (item) {
let loginData = JSON.parse(item) let loginData = JSON.parse(item)
this.$store.dispatch('isLoggedIn', loginData) this.$store.dispatch('isLoggedIn', loginData)
this.$store.dispatch('startEventListening', '?action=events')
} }
} }
} }

View File

@ -27,7 +27,7 @@
</div> </div>
<h3 class="title is-6" v-if="currentItem.name" v-text="currentItem.name"></h3> <h3 class="title is-6" v-if="currentItem.name" v-text="currentItem.name"></h3>
<div class="content" v-html="main_content"></div> <div class="content is-pre" v-html="main_content"></div>
<div class="photos"> <div class="photos">
<div class="photo" v-for="photo in photo_rest" :key="photo"> <div class="photo" v-for="photo in photo_rest" :key="photo">
@ -42,7 +42,6 @@
<a @click="like">Like</a> <a @click="like">Like</a>
&middot; <a @click.prevent="openReply">Reply</a> &middot; <a @click.prevent="openReply">Reply</a>
&middot; <a @click.prevent="repost">Repost</a> &middot; <a @click.prevent="repost">Repost</a>
&middot; <a @click.prevent="openBookmark">Bookmark</a>
&middot; <a @click.prevent="$emit('followFeed', author_url)" title="Try to follow the feed this item comes from">Follow</a> &middot; <a @click.prevent="$emit('followFeed', author_url)" title="Try to follow the feed this item comes from">Follow</a>
&middot; <a @click.prevent="debug">Debug</a> &middot; <a @click.prevent="debug">Debug</a>
</span> </span>
@ -65,53 +64,23 @@
</div> </div>
</div> </div>
</div> </div>
<div class="media" v-if="bookmarking">
<div class="media-content">
<div class="field">
<div class="control">
<input type="text" class="input" placeholder="Title" v-model="bookmarkTitle">
</div>
</div>
<div class="field">
<label class="label">Add a note</label>
<div class="control">
<textarea class="textarea" v-model="bookmarkDescription"></textarea>
</div>
</div>
<div class="field">
<syndication-buttons v-model="selected" :targets="targets"/>
</div>
<div class="field">
<div class="control">
<button class="button is-primary" @click="bookmark">Bookmark</button>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import moment from 'moment' import moment from 'moment'
import SyndicationButtons from "@/components/SyndicationButtons";
export default { export default {
name: "Entry", name: "Entry",
components: {SyndicationButtons},
props: ['item'], props: ['item'],
data() { data() {
return { return {
'replying': false, 'replying': false,
'replyText': '', 'replyText': '',
'showFooterButtons': true, 'showFooterButtons': true
bookmarking: false,
bookmarkTitle: '',
bookmarkDescription: '',
targets: [],
selected: []
} }
}, },
@ -153,30 +122,6 @@ export default {
}, },
}) })
}, },
openBookmark() {
this.bookmarking = true
this.bookmarkTitle = this.author_name + ' - ' + this.currentItem.name
this.bookmarkDescription = ''
this.selected = []
this.$store.dispatch('fetchSyndicationTargets')
.then(res => this.targets = res['syndicate-to'])
},
bookmark() {
this.$store.dispatch('micropubPost', {
'type': ['h-entry'],
'properties': {
'bookmark-of': [this.currentItem.url],
'name': [this.bookmarkTitle],
'content': [this.bookmarkDescription ],
'mp-syndicate-to': this.selected
},
}).then(() => {
this.bookmarkTitle = '';
this.bookmarkDescription = '';
this.selected = []
this.bookmarking = false
})
},
hasRef(key) { hasRef(key) {
if (this.item.hasOwnProperty(key) && this.item.hasOwnProperty('refs')) { if (this.item.hasOwnProperty(key) && this.item.hasOwnProperty('refs')) {
if (this.item.refs.hasOwnProperty(this.item[key])) { if (this.item.refs.hasOwnProperty(this.item[key])) {
@ -344,5 +289,4 @@ export default {
.is-pre { .is-pre {
white-space: pre-wrap; white-space: pre-wrap;
} }
</style> </style>

View File

@ -11,9 +11,6 @@
<textarea class="textarea" v-model="newPost"></textarea> <textarea class="textarea" v-model="newPost"></textarea>
</div> </div>
</div> </div>
<div class="field">
<syndication-buttons v-model="selectedTargets" :targets="targets"/>
</div>
<div class="level"> <div class="level">
<div class="level-left"> <div class="level-left">
<div class="level-item"> <div class="level-item">
@ -36,30 +33,20 @@
</template> </template>
<script> <script>
import SyndicationButtons from "@/components/SyndicationButtons";
export default { export default {
name: "NewPost", name: "NewPost",
components:{
SyndicationButtons
},
data() { data() {
return { return {
newPost: '', newPost: '',
targets: [], tags: [{name:"twitter"},{name:"instagram"}]
selectedTargets: []
} }
}, },
mounted() {
this.$store.dispatch('fetchSyndicationTargets')
.then(res => this.targets = res['syndicate-to'])
},
methods: { methods: {
post() { post() {
this.$store.dispatch('micropubPost', { this.$store.dispatch('micropubPost', {
'type': ['h-entry'], 'type': ['h-entry'],
'properties': { 'properties': {
'content': [this.newPost], 'content': [this.newPost]
'mp-syndicate-to': this.selectedTargets,
}, },
}).then(() => { }).then(() => {
this.newPost = ''; this.newPost = '';

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="short-timeline"> <div style="margin-top: 20px">
<div class="box small-item" style="margin-bottom: 4px" v-for="(item, i) in timeline.items" :key="i"> <div class="box small-item" style="margin-bottom: 4px" v-for="(item, i) in timeline.items" :key="i">
<div class="name" v-text="text(item)"></div> <div class="name" v-text="text(item)"></div>
<div class="time" v-text="niceTime(item)"></div> <div class="time" v-text="niceTime(item)"></div>
@ -36,13 +36,8 @@
</script> </script>
<style scoped> <style scoped>
.short-timeline {
margin-top: 20px;
position: fixed;
max-width: 280px;
}
.small-item { .small-item {
font-size: 12px; font-size: 10px;
} }
.box { .box {
padding: 6px; padding: 6px;

View File

@ -1,43 +0,0 @@
<template>
<div>
<div v-for="(target, i) in targets" :key="i" style="display: inline-block; margin: 0 3px 3px 0">
<label>
<input type="checkbox" class="is-hidden cb-target" v-model="selected" :value="target.uid"/>
<span class="tag is-light" v-text="target.name"></span>
</label>
</div>
</div>
</template>
<script>
export default {
name: 'syndication-buttons',
data() {
return {
selected: [],
}
},
props: {
value: [],
targets: {}
},
mounted() {
this.selected = this.value
},
watch: {
selected(newSelection) {
this.$emit('update', newSelection)
}
}
}
</script>
<style scoped>
.tag {
cursor: pointer;
}
.cb-target:checked + .tag {
background-color: #23d160;
color: #fff;
}
</style>

View File

@ -59,7 +59,7 @@
.then(() => { .then(() => {
item._is_read = true item._is_read = true
}).then(() => { }).then(() => {
// this.$store.dispatch('fetchChannels') this.$store.dispatch('fetchChannels')
}) })
}, },
handleScroll() { handleScroll() {
@ -77,7 +77,7 @@
child.$props.item._is_read = true child.$props.item._is_read = true
let item = child.$props.item let item = child.$props.item
this.markRead(this.channel.uid, item).then(() => { this.markRead(this.channel.uid, item).then(() => {
// this.$store.dispatch('fetchChannels') this.$store.dispatch('fetchChannels')
}) })
} }
} }

View File

@ -4,7 +4,6 @@ import router from './router'
import store from './store' import store from './store'
import 'bulma' import 'bulma'
import '@/styles.scss' import '@/styles.scss'
import '@primer/css/utilities/index.scss';
Vue.config.productionTip = false Vue.config.productionTip = false

View File

@ -63,9 +63,6 @@ export default new Vuex.Store({
state.microsubEndpoint = endpoints.microsubEndpoint state.microsubEndpoint = endpoints.microsubEndpoint
}, },
createEventSource(state, url) { createEventSource(state, url) {
if (state.eventSource !== null) {
state.eventSource.close()
}
state.eventSource = new EventSource(state.microsubEndpoint + url + "&access_token=" + state.access_token, { state.eventSource = new EventSource(state.microsubEndpoint + url + "&access_token=" + state.access_token, {
// headers: { // headers: {
// 'Authorization': 'Bearer ' + this.state.access_token // 'Authorization': 'Bearer ' + this.state.access_token
@ -86,24 +83,15 @@ export default new Vuex.Store({
state.eventSource.addEventListener('error', evt => { state.eventSource.addEventListener('error', evt => {
// eslint-disable-next-line // eslint-disable-next-line
console.log(evt) console.log(evt)
if (evt.message === "network error") {
state.eventSource.close()
}
}) })
state.eventSource.addEventListener('new item', evt => { state.eventSource.addEventListener('new item', evt => {
// eslint-disable-next-line // eslint-disable-next-line
console.log(evt) console.log(evt)
try { let item = JSON.parse(evt.data)
let newItemMsg = JSON.parse(evt.data) // eslint-disable-next-line
if (state.channel.uid === newItemMsg.channel) { state.timeline.items = [...state.timeline.items, item]
state.timeline.items = [...state.timeline.items, newItemMsg.item] state.globalTimeline.items = _.take([item, ...state.globalTimeline.items], 10)
}
state.globalTimeline.items = _.takeRight([...state.globalTimeline.items, newItemMsg.item], 10)
} catch (e) {
// eslint-disable-next-line
console.log(e)
}
}) })
state.eventSource.addEventListener('new item in channel', evt => { state.eventSource.addEventListener('new item in channel', evt => {
// eslint-disable-next-line // eslint-disable-next-line
@ -164,13 +152,7 @@ export default new Vuex.Store({
commit('newAccessToken', response) commit('newAccessToken', response)
}, },
markRead(x, {channel, entry}) { markRead(x, {channel, entry}) {
let entries = ''; let url = this.state.microsubEndpoint + '?action=timeline&method=mark_read&channel=' + encodeURIComponent(channel) + '&entry=' + encodeURIComponent(entry);
if (Array.isArray(entry)) {
entries = _(entry).map(uid => '&entry[]='+encodeURIComponent(uid)).join("")
} else {
entries = '&entry=' + encodeURIComponent(entry)
}
let url = this.state.microsubEndpoint + '?action=timeline&method=mark_read&channel=' + encodeURIComponent(channel) + entries;
return fetch(url, { return fetch(url, {
method: 'POST', method: 'POST',
headers: { headers: {
@ -178,13 +160,6 @@ export default new Vuex.Store({
} }
}) })
}, },
fetchSyndicationTargets() {
let micropub = new Micropub({
token: this.state.access_token,
micropubEndpoint: this.state.micropubEndpoint
})
return micropub.query('syndicate-to')
},
micropubPost(_, mf2post) { micropubPost(_, mf2post) {
let micropub = new Micropub({ let micropub = new Micropub({
token: this.state.access_token, token: this.state.access_token,
@ -218,23 +193,21 @@ export default new Vuex.Store({
}) })
}, },
bottomReached() { bottomReached() {
// eslint-disable-next-line let count = 0
console.log('bottomReached') let uids = []
let items = this.state.timeline.items let items = this.state.timeline.items
// eslint-disable-next-line uids = _.map(_.filter(items, item => !item._is_read), item => item._id)
console.log(items)
let uids = _(items).reject('_is_read').map('_id').value()
// eslint-disable-next-line
console.log(uids)
items.forEach((item) => { items.forEach((item) => {
if (item && !item._is_read) { if (item && !item._is_read) {
item._is_read = true item._is_read = true
count++;
} }
}) })
if (uids.length > 0) { if (count > 0) {
return this.dispatch('markRead', {channel: this.state.channel.uid, 'entry': uids}) this.dispatch('markRead', {channel: this.state.channel.uid, 'entry[]': uids})
.then(() => {
this.dispatch('fetchChannels')
})
} }
}, },
startEventListening({commit}, url) { startEventListening({commit}, url) {

View File

@ -1,11 +1,8 @@
//@import 'bulmaswatch.min.css'; @import 'bulmaswatch.min.css';
.mb-20 { .mb-20 {
margin-bottom: 20px; margin-bottom: 20px;
} }
.mt-20 { .mt-20 {
margin-top: 20px; margin-top: 20px;
} }

View File

@ -111,6 +111,7 @@
mounted() { mounted() {
if (this.$store.state.logged_in) { if (this.$store.state.logged_in) {
this.$store.dispatch('startEventListening', '?action=events')
this.$store.dispatch('fetchChannels') this.$store.dispatch('fetchChannels')
this.$store.dispatch('fetchTimeline', {uid: this.uid}) this.$store.dispatch('fetchTimeline', {uid: this.uid})
} }