Merge branch 'develop' into feature/hash-routed

This commit is contained in:
Roger Braun 2017-03-10 13:27:58 +01:00
commit 112adcf8f8
20 changed files with 91 additions and 71 deletions

View file

@ -33,6 +33,7 @@ module.exports = {
fallback: [path.join(__dirname, '../node_modules')] fallback: [path.join(__dirname, '../node_modules')]
}, },
module: { module: {
noParse: /node_modules\/localforage\/dist\/localforage.js/,
preLoaders: [ preLoaders: [
{ {
test: /\.vue$/, test: /\.vue$/,

View file

@ -8,7 +8,7 @@
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div class="timeline"> <div class="timeline">
<status v-for="status in conversation" :key="status.id" v-bind:statusoid="status":expandable='false':focused="focused(status.id)"></status> <status v-for="status in conversation" :key="status.id" :statusoid="status" :expandable='false' :focused="focused(status.id)" :inConversation='true'></status>
</div> </div>
</div> </div>
</div> </div>

View file

@ -2,25 +2,12 @@ import Timeline from '../timeline/timeline.vue'
const Mentions = { const Mentions = {
computed: { computed: {
username () {
return this.$route.params.username
},
timeline () { timeline () {
return this.$store.state.statuses.timelines.mentions return this.$store.state.statuses.timelines.mentions
} }
}, },
components: { components: {
Timeline Timeline
},
created () {
this.$store.state.api.backendInteractor.fetchMentions({username: this.username})
.then((mentions) => {
this.$store.dispatch('addNewStatuses', {
statuses: mentions,
timeline: 'mentions',
showImmediately: true
})
})
} }
} }

View file

@ -1,7 +1,7 @@
<template> <template>
<div class="nav-panel"> <div class="nav-panel">
<div class="panel panel-default base02-background"> <div class="panel panel-default base02-background">
<ul> <ul class="base03-border">
<li v-if='currentUser'> <li v-if='currentUser'>
<router-link class="base01-background" to='/main/friends'> <router-link class="base01-background" to='/main/friends'>
Timeline Timeline
@ -38,6 +38,7 @@
.nav-panel li { .nav-panel li {
border-bottom: 1px solid; border-bottom: 1px solid;
border-color: inherit;
padding: 0; padding: 0;
&:first-child a { &:first-child a {
border-top-right-radius: 10px; border-top-right-radius: 10px;

View file

@ -33,7 +33,8 @@
// which does not happen with 10px vs 4px + 6px. // which does not happen with 10px vs 4px + 6px.
padding: 0.4em 0 0 10px; padding: 0.4em 0 0 10px;
display: flex; display: flex;
border-bottom: 1px solid silver; border-bottom: 1px solid;
border-bottom-color: inherit;
.text { .text {
@ -72,7 +73,8 @@
} }
&:last-child { &:last-child {
border: none border-bottom: none;
border-radius: 0 0 10px 10px;
} }
} }

View file

@ -6,7 +6,7 @@
Notifications Notifications
<button @click.prevent="markAsSeen" class="base06 base02-background read-button">Read!</button> <button @click.prevent="markAsSeen" class="base06 base02-background read-button">Read!</button>
</div> </div>
<div class="panel-body"> <div class="panel-body base03-border">
<div v-for="notification in visibleNotifications" class="notification" :class='{"unseen": !notification.seen}'> <div v-for="notification in visibleNotifications" class="notification" :class='{"unseen": !notification.seen}'>
<a :href="notification.action.user.statusnet_profile_url"> <a :href="notification.action.user.statusnet_profile_url">
<img class='avatar' :src="notification.action.user.profile_image_url_original"> <img class='avatar' :src="notification.action.user.profile_image_url_original">

View file

@ -4,6 +4,7 @@ const settings = {
data () { data () {
return { return {
hideAttachmentsLocal: this.$store.state.config.hideAttachments, hideAttachmentsLocal: this.$store.state.config.hideAttachments,
hideAttachmentsInConvLocal: this.$store.state.config.hideAttachmentsInConv,
hideNsfwLocal: this.$store.state.config.hideNsfw hideNsfwLocal: this.$store.state.config.hideNsfw
} }
}, },
@ -14,6 +15,9 @@ const settings = {
hideAttachmentsLocal (value) { hideAttachmentsLocal (value) {
this.$store.dispatch('setOption', { name: 'hideAttachments', value }) this.$store.dispatch('setOption', { name: 'hideAttachments', value })
}, },
hideAttachmentsInConvLocal (value) {
this.$store.dispatch('setOption', { name: 'hideAttachmentsInConv', value })
},
hideNsfwLocal (value) { hideNsfwLocal (value) {
this.$store.dispatch('setOption', { name: 'hideNsfw', value }) this.$store.dispatch('setOption', { name: 'hideNsfw', value })
} }

View file

@ -10,10 +10,20 @@
</div> </div>
<div class="setting-item"> <div class="setting-item">
<h2>Attachments</h2> <h2>Attachments</h2>
<ul class="setting-list">
<li>
<input type="checkbox" id="hideAttachments" v-model="hideAttachmentsLocal"> <input type="checkbox" id="hideAttachments" v-model="hideAttachmentsLocal">
<label for="hideAttachments">Hide Attachments</label> <label for="hideAttachments">Hide attachments in timeline</label>
</li>
<li>
<input type="checkbox" id="hideAttachmentsInConv" v-model="hideAttachmentsInConvLocal">
<label for="hideAttachmentsInConv">Hide attachments in conversations</label>
</li>
<li>
<input type="checkbox" id="hideNsfw" v-model="hideNsfwLocal"> <input type="checkbox" id="hideNsfw" v-model="hideNsfwLocal">
<label for="hideNsfw">Enable clickthrough NSFW attachment hiding</label> <label for="hideNsfw">Enable clickthrough NSFW attachment hiding</label>
</li>
</ul>
</div> </div>
</div> </div>
</div> </div>
@ -26,4 +36,7 @@
.setting-item { .setting-item {
margin: 1em 1em 1.4em; margin: 1em 1em 1.4em;
} }
.setting-list {
list-style-type: none;
}
</style> </style>

View file

@ -9,6 +9,7 @@ const Status = {
props: [ props: [
'statusoid', 'statusoid',
'expandable', 'expandable',
'inConversation',
'focused' 'focused'
], ],
data: () => ({ data: () => ({
@ -18,7 +19,10 @@ const Status = {
userExpanded: false userExpanded: false
}), }),
computed: { computed: {
hideAttachments () { return this.$store.state.config.hideAttachments }, hideAttachments () {
return (this.$store.state.config.hideAttachments && !this.inConversation) ||
(this.$store.state.config.hideAttachmentsInConv && this.inConversation)
},
retweet () { return !!this.statusoid.retweeted_status }, retweet () { return !!this.statusoid.retweeted_status },
retweeter () { return this.statusoid.user.name }, retweeter () { return this.statusoid.user.name },
status () { status () {
@ -32,7 +36,12 @@ const Status = {
return !!this.$store.state.users.currentUser return !!this.$store.state.users.currentUser
}, },
muted () { return !this.unmuted && this.status.user.muted }, muted () { return !this.unmuted && this.status.user.muted },
isReply () { return !!this.status.in_reply_to_status_id } isReply () { return !!this.status.in_reply_to_status_id },
borderColor () {
return {
borderBottomColor: this.$store.state.config.colors['base02']
}
}
}, },
components: { components: {
Attachment, Attachment,

View file

@ -1,5 +1,5 @@
<template> <template>
<div class="status-el base00-background" v-if="!status.deleted" v-bind:class="[{ 'expanded-status': !expandable }, { 'base01-background': focused }]"> <div class="status-el base00-background base03-border" v-if="!status.deleted" v-bind:class="[{ 'base01-background': focused }, { 'status-conversation': inConversation }]" >
<template v-if="muted"> <template v-if="muted">
<div class="media status container muted"> <div class="media status container muted">
<small><router-link :to="{ name: 'user-profile', params: { id: status.user.id } }">{{status.user.screen_name}}</router-link></small> <small><router-link :to="{ name: 'user-profile', params: { id: status.user.id } }">{{status.user.screen_name}}</router-link></small>
@ -73,18 +73,20 @@
<div class='status-actions'> <div class='status-actions'>
<div> <div>
<a href="#" v-on:click.prevent="toggleReplying"> <a href="#" v-on:click.prevent="toggleReplying">
<i class='fa icon-reply'></i> <i class="fa icon-reply" :class="{'icon-reply-active': replying}"></i>
</a> </a>
</div> </div>
<retweet-button :status=status></retweet-button> <retweet-button :status=status></retweet-button>
<favorite-button :status=status></favorite-button> <favorite-button :status=status></favorite-button>
<delete-button :status=status></delete-button> <delete-button :status=status></delete-button>
</div> </div>
<post-status-form v-if="replying" :reply-to="status.id" :attentions="status.attentions" :repliedUser="status.user" v-on:posted="toggleReplying"></post-status-form>
</div> </div>
</div> </div>
</div> </div>
<div class="status base00-background container" v-if="replying">
<div class="reply-left"/>
<post-status-form class="reply-body" :reply-to="status.id" :attentions="status.attentions" :repliedUser="status.user" v-on:posted="toggleReplying"/>
</div>
</template> </template>
</div> </div>
</template> </template>
@ -98,6 +100,7 @@
overflow-wrap: break-word; overflow-wrap: break-word;
word-wrap: break-word; word-wrap: break-word;
word-break: break-word; word-break: break-word;
border-left-width: 0px;
.user-content { .user-content {
min-height: 52px; min-height: 52px;
@ -128,8 +131,8 @@
} }
} }
.expanded-status { .status-conversation {
border-left: 4px solid rgba(255, 48, 16, 0.65); border-left-style: solid;
} }
.status-actions { .status-actions {
@ -140,6 +143,10 @@
color: $blue; color: $blue;
} }
.icon-reply-active {
color: $blue;
}
.status .avatar { .status .avatar {
width: 48px; width: 48px;
} }
@ -151,6 +158,9 @@
.status { .status {
padding: 0.65em 0.7em 0.8em 0.8em; padding: 0.65em 0.7em 0.8em 0.8em;
border-bottom: 1px solid; border-bottom: 1px solid;
border-bottom-color: inherit;
border-left: 4px rgba(255, 48, 16, 0.65);
border-left-style: inherit;
} }
.muted button { .muted button {
margin-left: auto; margin-left: auto;
@ -168,4 +178,14 @@
margin-bottom: 1em; margin-bottom: 1em;
margin-top: 0.2em; margin-top: 0.2em;
} }
.reply-left {
flex: 0;
min-width: 48px;
}
.reply-body {
flex: 1;
}
</style> </style>

View file

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<conversation v-if="expanded" @toggleExpanded="toggleExpanded" :collapsable="true" :statusoid="statusoid"></conversation> <conversation v-if="expanded" @toggleExpanded="toggleExpanded" :collapsable="true" :statusoid="statusoid"></conversation>
<status v-if="!expanded" @toggleExpanded="toggleExpanded" :expandable="true" :statusoid="statusoid" :focused="false"></status> <status v-if="!expanded" @toggleExpanded="toggleExpanded" :expandable="true" :inConversation="false" :focused="false" :statusoid="statusoid"></status>
</div> </div>
</template> </template>

View file

@ -8,6 +8,9 @@ const Timeline = {
'timelineName', 'timelineName',
'title' 'title'
], ],
computed: {
timelineError () { return this.$store.state.statuses.error }
},
components: { components: {
Status, Status,
StatusOrConversation StatusOrConversation

View file

@ -4,13 +4,13 @@
<div class="title"> <div class="title">
{{title}} {{title}}
</div> </div>
<button @click.prevent="showNewStatuses" class="base06 base02-background loadmore-button" v-if="timeline.newStatusCount > 0 && !timeline.error"> <button @click.prevent="showNewStatuses" class="base06 base02-background loadmore-button" v-if="timeline.newStatusCount > 0 && !timelineError">
Show new ({{timeline.newStatusCount}}) Show new ({{timeline.newStatusCount}})
</button> </button>
<button @click.prevent class="base06 error no-press loadmore-button" v-if="timeline.error"> <button @click.prevent class="base06 error no-press loadmore-button" v-if="timelineError">
Error fetching updates Error fetching updates
</button> </button>
<button @click.prevent class="base04 base01-background no-press loadmore-button" v-if="!timeline.newStatusCount > 0 && !timeline.error"> <button @click.prevent class="base04 base01-background no-press loadmore-button" v-if="!timeline.newStatusCount > 0 && !timelineError">
Up-to-date Up-to-date
</button> </button>
</div> </div>
@ -18,9 +18,9 @@
<div class="timeline"> <div class="timeline">
<status-or-conversation v-for="status in timeline.visibleStatuses" :key="status.id" v-bind:statusoid="status"></status-or-conversation> <status-or-conversation v-for="status in timeline.visibleStatuses" :key="status.id" v-bind:statusoid="status"></status-or-conversation>
<a href="#" v-on:click.prevent='fetchOlderStatuses()' v-if="!timeline.loading"> <a href="#" v-on:click.prevent='fetchOlderStatuses()' v-if="!timeline.loading">
<div class="base01-background base05-border new-status-notification text-center">Load older statuses.</div> <div class="base01-background base03-border new-status-notification text-center">Load older statuses.</div>
</a> </a>
<div class="base01-background base05-border new-status-notification text-center" v-else>...</div> <div class="base01-background base03-border new-status-notification text-center" v-else>...</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -31,6 +31,7 @@ Vue.use(VueTimeago, {
const persistedStateOptions = { const persistedStateOptions = {
paths: [ paths: [
'config.hideAttachments', 'config.hideAttachments',
'config.hideAttachmentsInConv',
'config.hideNsfw', 'config.hideNsfw',
'statuses.notifications', 'statuses.notifications',
'users.users' 'users.users'

View file

@ -5,6 +5,7 @@ const defaultState = {
name: 'Pleroma FE', name: 'Pleroma FE',
colors: {}, colors: {},
hideAttachments: false, hideAttachments: false,
hideAttachmentsInConv: false,
hideNsfw: true hideNsfw: true
} }

View file

@ -8,6 +8,7 @@ export const defaultState = {
maxId: 0, maxId: 0,
notifications: [], notifications: [],
favorites: new Set(), favorites: new Set(),
error: false,
timelines: { timelines: {
mentions: { mentions: {
statuses: [], statuses: [],
@ -18,8 +19,7 @@ export const defaultState = {
newStatusCount: 0, newStatusCount: 0,
maxId: 0, maxId: 0,
minVisibleId: 0, minVisibleId: 0,
loading: false, loading: false
error: false
}, },
public: { public: {
statuses: [], statuses: [],
@ -30,8 +30,7 @@ export const defaultState = {
newStatusCount: 0, newStatusCount: 0,
maxId: 0, maxId: 0,
minVisibleId: 0, minVisibleId: 0,
loading: false, loading: false
error: false
}, },
publicAndExternal: { publicAndExternal: {
statuses: [], statuses: [],
@ -42,8 +41,7 @@ export const defaultState = {
newStatusCount: 0, newStatusCount: 0,
maxId: 0, maxId: 0,
minVisibleId: 0, minVisibleId: 0,
loading: false, loading: false
error: false
}, },
friends: { friends: {
statuses: [], statuses: [],
@ -54,8 +52,7 @@ export const defaultState = {
newStatusCount: 0, newStatusCount: 0,
maxId: 0, maxId: 0,
minVisibleId: 0, minVisibleId: 0,
loading: false, loading: false
error: false
} }
} }
} }
@ -298,8 +295,8 @@ export const mutations = {
const newStatus = state.allStatusesObject[id] const newStatus = state.allStatusesObject[id]
newStatus.nsfw = nsfw newStatus.nsfw = nsfw
}, },
setError (state, { timeline, value }) { setError (state, { value }) {
state.timelines[timeline].error = value state.error = value
}, },
markNotificationsAsSeen (state, notifications) { markNotificationsAsSeen (state, notifications) {
each(notifications, (notification) => { each(notifications, (notification) => {
@ -314,8 +311,8 @@ const statuses = {
addNewStatuses ({ rootState, commit }, { statuses, showImmediately = false, timeline = false, noIdUpdate = false }) { addNewStatuses ({ rootState, commit }, { statuses, showImmediately = false, timeline = false, noIdUpdate = false }) {
commit('addNewStatuses', { statuses, showImmediately, timeline, noIdUpdate, user: rootState.users.currentUser }) commit('addNewStatuses', { statuses, showImmediately, timeline, noIdUpdate, user: rootState.users.currentUser })
}, },
setError ({ rootState, commit }, { timeline, value }) { setError ({ rootState, commit }, { value }) {
commit('setError', { timeline, value }) commit('setError', { value })
}, },
deleteStatus ({ rootState, commit }, status) { deleteStatus ({ rootState, commit }, status) {
commit('setDeleted', { status }) commit('setDeleted', { status })

View file

@ -62,12 +62,6 @@ const fetchAllFollowing = ({username, credentials}) => {
.then((data) => data.json()) .then((data) => data.json())
} }
const fetchMentions = ({username, sinceId = 0, credentials}) => {
let url = `${MENTIONS_URL}?since_id=${sinceId}&screen_name=${username}`
return fetch(url, { headers: authHeaders(credentials) })
.then((data) => data.json())
}
const fetchConversation = ({id, credentials}) => { const fetchConversation = ({id, credentials}) => {
let url = `${CONVERSATION_URL}/${id}.json?count=100` let url = `${CONVERSATION_URL}/${id}.json?count=100`
return fetch(url, { headers: authHeaders(credentials) }) return fetch(url, { headers: authHeaders(credentials) })
@ -100,6 +94,7 @@ const fetchTimeline = ({timeline, credentials, since = false, until = false}) =>
const timelineUrls = { const timelineUrls = {
public: PUBLIC_TIMELINE_URL, public: PUBLIC_TIMELINE_URL,
friends: FRIENDS_TIMELINE_URL, friends: FRIENDS_TIMELINE_URL,
mentions: MENTIONS_URL,
'publicAndExternal': PUBLIC_AND_EXTERNAL_TIMELINE_URL 'publicAndExternal': PUBLIC_AND_EXTERNAL_TIMELINE_URL
} }
@ -192,7 +187,6 @@ const apiService = {
fetchTimeline, fetchTimeline,
fetchConversation, fetchConversation,
fetchStatus, fetchStatus,
fetchMentions,
fetchFriends, fetchFriends,
followUser, followUser,
unfollowUser, unfollowUser,

View file

@ -10,10 +10,6 @@ const backendInteractorService = (credentials) => {
return apiService.fetchConversation({id, credentials}) return apiService.fetchConversation({id, credentials})
} }
const fetchMentions = ({sinceId, username}) => {
return apiService.fetchMentions({sinceId, username, credentials})
}
const fetchFriends = () => { const fetchFriends = () => {
return apiService.fetchFriends({credentials}) return apiService.fetchFriends({credentials})
} }
@ -43,7 +39,6 @@ const backendInteractorService = (credentials) => {
const backendInteractorServiceInstance = { const backendInteractorServiceInstance = {
fetchStatus, fetchStatus,
fetchConversation, fetchConversation,
fetchMentions,
fetchFriends, fetchFriends,
followUser, followUser,
unfollowUser, unfollowUser,

View file

@ -45,6 +45,7 @@ const setStyle = (href, commit) => {
styleSheet.insertRule(`a { color: ${colors['base08']}`, 'index-max') styleSheet.insertRule(`a { color: ${colors['base08']}`, 'index-max')
styleSheet.insertRule(`body { color: ${colors['base05']}`, 'index-max') styleSheet.insertRule(`body { color: ${colors['base05']}`, 'index-max')
styleSheet.insertRule(`.base05-border { border-color: ${colors['base05']}`, 'index-max') styleSheet.insertRule(`.base05-border { border-color: ${colors['base05']}`, 'index-max')
styleSheet.insertRule(`.base03-border { border-color: ${colors['base03']}`, 'index-max')
body.style.display = 'initial' body.style.display = 'initial'
} }
cssEl.addEventListener('load', setDynamic) cssEl.addEventListener('load', setDynamic)

View file

@ -5,7 +5,7 @@ import apiService from '../api/api.service.js'
const update = ({store, statuses, timeline, showImmediately}) => { const update = ({store, statuses, timeline, showImmediately}) => {
const ccTimeline = camelCase(timeline) const ccTimeline = camelCase(timeline)
setError({store, timeline, value: false}) store.dispatch('setError', { value: false })
store.dispatch('addNewStatuses', { store.dispatch('addNewStatuses', {
timeline: ccTimeline, timeline: ccTimeline,
@ -14,15 +14,6 @@ const update = ({store, statuses, timeline, showImmediately}) => {
}) })
} }
const setError = ({store, timeline, value}) => {
const ccTimeline = camelCase(timeline)
store.dispatch('setError', {
timeline: ccTimeline,
value
})
}
const fetchAndUpdate = ({store, credentials, timeline = 'friends', older = false, showImmediately = false}) => { const fetchAndUpdate = ({store, credentials, timeline = 'friends', older = false, showImmediately = false}) => {
const args = { timeline, credentials } const args = { timeline, credentials }
const rootState = store.rootState || store.state const rootState = store.rootState || store.state
@ -36,7 +27,7 @@ const fetchAndUpdate = ({store, credentials, timeline = 'friends', older = false
return apiService.fetchTimeline(args) return apiService.fetchTimeline(args)
.then((statuses) => update({store, statuses, timeline, showImmediately}), .then((statuses) => update({store, statuses, timeline, showImmediately}),
() => setError({store, timeline, value: true})) () => store.dispatch('setError', { value: true }))
} }
const startFetching = ({ timeline = 'friends', credentials, store }) => { const startFetching = ({ timeline = 'friends', credentials, store }) => {