Compare commits
10 commits
develop
...
feature/gr
Author | SHA1 | Date | |
---|---|---|---|
|
c52173c64b | ||
|
cd87a6712d | ||
|
a284a52306 | ||
|
caf4c7fddf | ||
|
55925383b7 | ||
|
7a3e608455 | ||
|
d4de464ab5 | ||
|
54d3b0cd7e | ||
|
9c90b019d1 | ||
|
b25b993309 |
16 changed files with 548 additions and 16 deletions
225
src/components/group_card_content/group_card_content.vue
Normal file
225
src/components/group_card_content/group_card_content.vue
Normal file
|
@ -0,0 +1,225 @@
|
|||
<template>
|
||||
<div id="heading" class="group-panel-background" :style="headingStyle">
|
||||
<div class="panel-heading text-center">
|
||||
<div class='group-info'>
|
||||
<div class='container'>
|
||||
<router-link :to="{ name: 'group-page', params: { name: group.nickname } }">
|
||||
<img v-if="!!group.original_logo" :src="group.original_logo">
|
||||
<img v-else src="https://placehold.it/48x48">
|
||||
</router-link>
|
||||
<span class="glyphicon glyphicon-user"></span>
|
||||
<div class="name-and-screen-name">
|
||||
<div class='group-name'>{{group.nickname}}</div>
|
||||
<router-link :to="{ name: 'group-page', params: { name: group.nickname } }">
|
||||
<div class='group-full-name'>{{group.fullname}}</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="group-interactions">
|
||||
<div class="member" v-if="loggedIn">
|
||||
<span v-if="isMember">
|
||||
<button @click="leaveGroup" class="base04 base00-background pressed">
|
||||
{{ $t('group_card.leave') }}
|
||||
</button>
|
||||
</span>
|
||||
<span v-if="!isMember">
|
||||
<button @click="joinGroup" class="base05 base02-background">
|
||||
{{ $t('group_card.join') }}
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body group-panel-body">
|
||||
<div class="member-counts">
|
||||
<div class="member-count">
|
||||
<a href="#" v-on:click.prevent="setGroupView('statuses')"><h5 class="base05">{{ $t('user_card.statuses') }}</h5></a>
|
||||
</div>
|
||||
<div class="member-count">
|
||||
<a href="#" v-on:click.prevent="setGroupView('members')"><h5 class="base05">{{ $t('group_card.members') }}</h5></a>
|
||||
<span class="base05">{{group.member_count}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<p>{{group.description}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: [ 'group', 'isMember' ],
|
||||
computed: {
|
||||
groupName () {
|
||||
return this.group.nickname
|
||||
},
|
||||
headingStyle () {
|
||||
let color = this.$store.state.config.colors['base00']
|
||||
if (color) {
|
||||
let rgb = this.$store.state.config.colors['base00'].match(/\d+/g)
|
||||
return {
|
||||
backgroundColor: `rgb(${Math.floor(rgb[0] * 0.53)}, ${Math.floor(rgb[1] * 0.56)}, ${Math.floor(rgb[2] * 0.59)})`,
|
||||
backgroundImage: `url(${this.group.cover_photo})`
|
||||
}
|
||||
}
|
||||
},
|
||||
loggedIn () {
|
||||
return !!this.$store.state.users.currentUser
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setMember (value) {
|
||||
this.$store.state.groups.groupMemberships[this.groupName] = value
|
||||
},
|
||||
joinGroup () {
|
||||
const store = this.$store
|
||||
store.state.api.backendInteractor.joinGroup({'groupName': this.groupName})
|
||||
.then((joinedGroup) => {
|
||||
store.commit('addNewGroup', joinedGroup)
|
||||
this.setMember(true)
|
||||
})
|
||||
},
|
||||
leaveGroup () {
|
||||
const store = this.$store
|
||||
store.state.api.backendInteractor.leaveGroup({'groupName': this.groupName})
|
||||
.then((leftGroup) => {
|
||||
store.commit('addNewGroup', leftGroup)
|
||||
this.setMember(false)
|
||||
})
|
||||
},
|
||||
setGroupView (v) {
|
||||
const store = this.$store
|
||||
store.commit('setGroupView', { v })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../_variables.scss';
|
||||
|
||||
.group-panel-background {
|
||||
background-size: cover;
|
||||
border-radius: 10px;
|
||||
|
||||
.panel-heading {
|
||||
padding: 0.6em 0em;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.group-panel-body {
|
||||
top: -0em;
|
||||
padding-top: 4em;
|
||||
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.group-info {
|
||||
color: white;
|
||||
padding: 0 16px 16px 16px;
|
||||
margin-bottom: -4em;
|
||||
|
||||
.container{
|
||||
padding: 16px 10px 4px 10px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
align-content: flex-start;
|
||||
justify-content: center;
|
||||
max-height: 56px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: 5px;
|
||||
flex: 1 0 100%;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
box-shadow: 0px 1px 8px rgba(0,0,0,0.75);
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
text-shadow: 0px 1px 1.5px rgba(0, 0, 0, 1.0);
|
||||
|
||||
.name-and-screen-name {
|
||||
display: block;
|
||||
margin-left: 0.6em;
|
||||
text-align: left;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.group-name{
|
||||
color: white;
|
||||
}
|
||||
|
||||
.group-full-name {
|
||||
color: white;
|
||||
font-weight: lighter;
|
||||
font-size: 15px;
|
||||
padding-right: 0.1em;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.group-interactions {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
|
||||
div {
|
||||
flex: 1;
|
||||
}
|
||||
margin-top: 0.7em;
|
||||
margin-bottom: -1.0em;
|
||||
|
||||
.following {
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
flex: 0 0 100%;
|
||||
margin: -0.7em 0.0em 0.3em 0.0em;
|
||||
padding-left: 16px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.mute {
|
||||
max-width: 220px;
|
||||
min-height: 28px;
|
||||
}
|
||||
|
||||
.follow {
|
||||
max-width: 220px;
|
||||
min-height: 28px;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 92%;
|
||||
height: 100%;
|
||||
}
|
||||
.pressed {
|
||||
border-bottom-color: rgba(255, 255, 255, 0.2);
|
||||
border-top-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.member-counts {
|
||||
display: flex;
|
||||
line-height:16px;
|
||||
padding: 1em 1.5em 0em 1em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.member-count {
|
||||
flex: 1;
|
||||
|
||||
h5 {
|
||||
font-size:1em;
|
||||
font-weight: bolder;
|
||||
margin: 0 0 0.25em;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
</style>
|
36
src/components/group_page/group_page.js
Normal file
36
src/components/group_page/group_page.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
import GroupCardContent from '../group_card_content/group_card_content.vue'
|
||||
import Timeline from '../timeline/timeline.vue'
|
||||
|
||||
const GroupPage = {
|
||||
created () {
|
||||
this.$store.dispatch('startFetching', { 'timeline': 'group', 'identifier': this.groupName })
|
||||
},
|
||||
destroyed () {
|
||||
this.$store.commit('clearTimeline', { timeline: 'group' })
|
||||
this.$store.dispatch('stopFetching', 'group')
|
||||
},
|
||||
computed: {
|
||||
timeline () { return this.$store.state.statuses.timelines.group },
|
||||
groupName () {
|
||||
return this.$route.params.name
|
||||
},
|
||||
group () {
|
||||
return this.$store.state.groups.groupsObject[this.groupName]
|
||||
},
|
||||
isMember () {
|
||||
return this.$store.state.groups.groupMemberships[this.groupName]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
groupName () {
|
||||
this.$store.commit('clearTimeline', { timeline: 'group' })
|
||||
this.$store.dispatch('startFetching', { 'timeline': 'group', 'identifier': this.groupName })
|
||||
}
|
||||
},
|
||||
components: {
|
||||
GroupCardContent,
|
||||
Timeline
|
||||
}
|
||||
}
|
||||
|
||||
export default GroupPage
|
21
src/components/group_page/group_page.vue
Normal file
21
src/components/group_page/group_page.vue
Normal file
|
@ -0,0 +1,21 @@
|
|||
<template>
|
||||
<div>
|
||||
<div v-if="group" class="group-page panel panel-default base00-background">
|
||||
<group-card-content :group="group" :isMember="isMember"></group-card-content>
|
||||
</div>
|
||||
<Timeline :title="'Group Timeline'" :group="group" v-bind:timeline="timeline" v-bind:timeline-name="'group'" :groupName="groupName" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script src="./group_page.js"></script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.group-page {
|
||||
flex: 2;
|
||||
flex-basis: 500px;
|
||||
padding-bottom: 10px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -74,6 +74,18 @@ const PostStatusForm = {
|
|||
name: '',
|
||||
img: image_url
|
||||
}))
|
||||
} else if (firstchar === '!') {
|
||||
const matchedGroups = filter(this.groups, (group) => group.nickname.match(this.textAtCaret.slice(1)))
|
||||
if (matchedGroups.length <= 0) {
|
||||
return false
|
||||
}
|
||||
/* eslint-disable */
|
||||
return map(take(matchedGroups, 5), ({nickname, original_logo}) => ({
|
||||
screen_name: `!${nickname}`,
|
||||
name: '',
|
||||
img: original_logo || 'https://placehold.it/48x48'
|
||||
}))
|
||||
/* eslint-enable */
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
|
@ -90,6 +102,9 @@ const PostStatusForm = {
|
|||
},
|
||||
emoji () {
|
||||
return this.$store.state.config.emoji || []
|
||||
},
|
||||
groups () {
|
||||
return this.$store.state.groups.groups
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -54,6 +54,11 @@
|
|||
{{status.in_reply_to_screen_name}}
|
||||
</router-link>
|
||||
</small>
|
||||
<small v-for="group in status.statusnet_in_groups"> |
|
||||
<router-link :to="{ name: 'group-page', params: { name: group.nickname } }">
|
||||
{{group.nickname}}
|
||||
</router-link>
|
||||
</small>
|
||||
<template v-if="isReply">
|
||||
<small>
|
||||
<a href="#" @click.prevent="gotoOriginal(status.in_reply_to_status_id)"><i class="icon-reply" @mouseenter="replyEnter(status.in_reply_to_status_id, $event)" @mouseout="replyLeave()"></i></a>
|
||||
|
|
|
@ -3,7 +3,7 @@ import Timeline from '../timeline/timeline.vue'
|
|||
const TagTimeline = {
|
||||
created () {
|
||||
this.$store.commit('clearTimeline', { timeline: 'tag' })
|
||||
this.$store.dispatch('startFetching', { 'tag': this.tag })
|
||||
this.$store.dispatch('startFetching', ['identifier', this.tag])
|
||||
},
|
||||
components: {
|
||||
Timeline
|
||||
|
@ -15,7 +15,7 @@ const TagTimeline = {
|
|||
watch: {
|
||||
tag () {
|
||||
this.$store.commit('clearTimeline', { timeline: 'tag' })
|
||||
this.$store.dispatch('startFetching', { 'tag': this.tag })
|
||||
this.$store.dispatch('startFetching', ['identifier', this.tag])
|
||||
}
|
||||
},
|
||||
destroyed () {
|
||||
|
|
|
@ -9,6 +9,7 @@ const Timeline = {
|
|||
'timelineName',
|
||||
'title',
|
||||
'userId',
|
||||
'groupName',
|
||||
'tag'
|
||||
],
|
||||
data () {
|
||||
|
@ -24,6 +25,9 @@ const Timeline = {
|
|||
friends () {
|
||||
return this.timeline.friends
|
||||
},
|
||||
members () {
|
||||
return this.timeline.members
|
||||
},
|
||||
viewing () {
|
||||
return this.timeline.viewing
|
||||
},
|
||||
|
@ -49,7 +53,7 @@ const Timeline = {
|
|||
timeline: this.timelineName,
|
||||
showImmediately,
|
||||
userId: this.userId,
|
||||
tag: this.tag
|
||||
identifier: this.tag || this.groupName
|
||||
})
|
||||
|
||||
// don't fetch followers for public, friend, twkn
|
||||
|
@ -57,6 +61,9 @@ const Timeline = {
|
|||
this.fetchFriends()
|
||||
this.fetchFollowers()
|
||||
}
|
||||
if (this.timelineName === 'group') {
|
||||
this.fetchGroup()
|
||||
}
|
||||
},
|
||||
destroyed () {
|
||||
window.removeEventListener('scroll', this.scrollLoad)
|
||||
|
@ -77,7 +84,7 @@ const Timeline = {
|
|||
older: true,
|
||||
showImmediately: true,
|
||||
userId: this.userId,
|
||||
tag: this.tag
|
||||
identifier: this.tag || this.groupName
|
||||
}).then(() => store.commit('setLoading', { timeline: this.timelineName, value: false }))
|
||||
},
|
||||
fetchFollowers () {
|
||||
|
@ -90,6 +97,17 @@ const Timeline = {
|
|||
this.$store.state.api.backendInteractor.fetchFriends({ id })
|
||||
.then((friends) => this.$store.dispatch('addFriends', { friends }))
|
||||
},
|
||||
fetchGroup () {
|
||||
const ident = this.groupName
|
||||
this.$store.dispatch('fetchGroup', { 'groupName': ident })
|
||||
this.$store.dispatch('fetchIsMember', { 'groupName': ident, 'id': this.$store.state.users.currentUser.id })
|
||||
this.$store.state.api.backendInteractor.fetchMembers({ 'groupName': ident })
|
||||
.then((members) => {
|
||||
this.$store.dispatch('addMembers', { members })
|
||||
this.$router.push('/groups/temp') // TODO FIX THIS
|
||||
this.$router.push(`/groups/${ident}`) // ;_;
|
||||
})
|
||||
},
|
||||
scrollLoad (e) {
|
||||
let height = Math.max(document.body.offsetHeight, document.body.scrollHeight)
|
||||
if (this.timeline.loading === false &&
|
||||
|
|
|
@ -48,6 +48,18 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="timeline panel panel-default" v-else-if="viewing == 'members'">
|
||||
<div class="panel-heading timeline-heading base01-background base04">
|
||||
<div class="title">
|
||||
{{$t('group_card.members')}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body base02-background">
|
||||
<div class="timeline">
|
||||
<user-card v-for="member in members" :user="member" :showFollows="false"></user-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script src="./timeline.js"></script>
|
||||
|
||||
|
|
|
@ -158,6 +158,11 @@ const en = {
|
|||
followees: 'Following',
|
||||
per_day: 'per day'
|
||||
},
|
||||
group_card: {
|
||||
members: 'Members',
|
||||
join: 'Join group',
|
||||
leave: 'Leave group'
|
||||
},
|
||||
timeline: {
|
||||
show_new: 'Show new',
|
||||
error_fetching: 'Error fetching updates',
|
||||
|
|
|
@ -9,12 +9,14 @@ import TagTimeline from './components/tag_timeline/tag_timeline.vue'
|
|||
import ConversationPage from './components/conversation-page/conversation-page.vue'
|
||||
import Mentions from './components/mentions/mentions.vue'
|
||||
import UserProfile from './components/user_profile/user_profile.vue'
|
||||
import GroupPage from './components/group_page/group_page.vue'
|
||||
import Settings from './components/settings/settings.vue'
|
||||
import Registration from './components/registration/registration.vue'
|
||||
import UserSettings from './components/user_settings/user_settings.vue'
|
||||
|
||||
import statusesModule from './modules/statuses.js'
|
||||
import usersModule from './modules/users.js'
|
||||
import groupsModule from './modules/groups.js'
|
||||
import apiModule from './modules/api.js'
|
||||
import configModule from './modules/config.js'
|
||||
|
||||
|
@ -55,6 +57,7 @@ const store = new Vuex.Store({
|
|||
modules: {
|
||||
statuses: statusesModule,
|
||||
users: usersModule,
|
||||
groups: groupsModule,
|
||||
api: apiModule,
|
||||
config: configModule
|
||||
},
|
||||
|
@ -70,6 +73,7 @@ const routes = [
|
|||
{ path: '/tag/:tag', component: TagTimeline },
|
||||
{ name: 'conversation', path: '/notice/:id', component: ConversationPage, meta: { dontScroll: true } },
|
||||
{ name: 'user-profile', path: '/users/:id', component: UserProfile },
|
||||
{ name: 'group-page', path: '/groups/:name', component: GroupPage },
|
||||
{ name: 'mentions', path: '/:username/mentions', component: Mentions },
|
||||
{ name: 'settings', path: '/settings', component: Settings },
|
||||
{ name: 'registration', path: '/registration', component: Registration },
|
||||
|
|
59
src/modules/groups.js
Normal file
59
src/modules/groups.js
Normal file
|
@ -0,0 +1,59 @@
|
|||
import { compact, map, each, merge } from 'lodash'
|
||||
|
||||
export const mergeOrAdd = (arr, obj, item) => {
|
||||
if (!item) { return false }
|
||||
const oldItem = obj[item.nickname]
|
||||
if (oldItem) {
|
||||
// We already have this, so only merge the new info.
|
||||
merge(oldItem, item)
|
||||
return {item: oldItem, new: false}
|
||||
} else {
|
||||
// This is a new item, prepare it
|
||||
arr.push(item)
|
||||
obj[item.nickname] = item
|
||||
return {item, new: true}
|
||||
}
|
||||
}
|
||||
|
||||
export const defaultState = {
|
||||
groups: [],
|
||||
groupsObject: {},
|
||||
groupMemberships: {}
|
||||
}
|
||||
|
||||
const groups = {
|
||||
state: defaultState,
|
||||
mutations: {
|
||||
addNewGroups (state, statuses) {
|
||||
each(statuses, (groups) => {
|
||||
each(groups, (group) => mergeOrAdd(state.groups, state.groupsObject, group))
|
||||
})
|
||||
},
|
||||
addNewGroup (state, group) {
|
||||
mergeOrAdd(state.groups, state.groupsObject, group)
|
||||
if (!state.groupMemberships[group.nickname]) {
|
||||
// insert some fake placeholder data
|
||||
state.groupMemberships[group.nickname] = {'is_member': false}
|
||||
}
|
||||
},
|
||||
addMembership (state, {groupName, membership}) {
|
||||
state.groupMemberships[groupName] = membership
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
fetchGroup (store, { groupName }) {
|
||||
store.rootState.api.backendInteractor.fetchGroup({ groupName })
|
||||
.then((group) => store.commit('addNewGroup', group))
|
||||
},
|
||||
fetchIsMember (store, { groupName, id }) {
|
||||
store.rootState.api.backendInteractor.fetchIsMember({id, groupName})
|
||||
.then((membership) => store.commit('addMembership', {groupName, 'membership': membership.is_member}))
|
||||
},
|
||||
addNewStatuses (store, { statuses }) {
|
||||
const groups = compact(map(statuses, 'statusnet_in_groups'))
|
||||
store.commit('addNewGroups', groups)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default groups
|
|
@ -93,6 +93,21 @@ export const defaultState = {
|
|||
followers: [],
|
||||
friends: [],
|
||||
viewing: 'statuses'
|
||||
},
|
||||
group: {
|
||||
statuses: [],
|
||||
statusesObject: {},
|
||||
faves: [],
|
||||
visibleStatuses: [],
|
||||
visibleStatusesObject: {},
|
||||
newStatusCount: 0,
|
||||
maxId: 0,
|
||||
minVisibleId: 0,
|
||||
loading: false,
|
||||
members: [],
|
||||
followers: [],
|
||||
friends: [],
|
||||
viewing: 'statuses'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -412,12 +427,18 @@ export const mutations = {
|
|||
// load followers / friends only when needed
|
||||
state.timelines['user'].viewing = v
|
||||
},
|
||||
setGroupView (state, { v }) {
|
||||
state.timelines['group'].viewing = v
|
||||
},
|
||||
addFriends (state, { friends }) {
|
||||
state.timelines['user'].friends = friends
|
||||
},
|
||||
addFollowers (state, { followers }) {
|
||||
state.timelines['user'].followers = followers
|
||||
},
|
||||
addMembers (state, { members }) {
|
||||
state.timelines['group'].members = members
|
||||
},
|
||||
markNotificationsAsSeen (state, notifications) {
|
||||
each(notifications, (notification) => {
|
||||
notification.seen = true
|
||||
|
@ -440,6 +461,9 @@ const statuses = {
|
|||
addFollowers ({ rootState, commit }, { followers }) {
|
||||
commit('addFollowers', { followers })
|
||||
},
|
||||
addMembers ({ rootState, commit }, { members }) {
|
||||
commit('addMembers', { members })
|
||||
},
|
||||
deleteStatus ({ rootState, commit }, status) {
|
||||
commit('setDeleted', { status })
|
||||
apiService.deleteStatus({ id: status.id, credentials: rootState.users.currentUser.credentials })
|
||||
|
|
|
@ -29,6 +29,14 @@ const QVITTER_USER_TIMELINE_URL = '/api/qvitter/statuses/user_timeline.json'
|
|||
const BLOCKING_URL = '/api/blocks/create.json'
|
||||
const UNBLOCKING_URL = '/api/blocks/destroy.json'
|
||||
const USER_URL = '/api/users/show.json'
|
||||
const GROUP_URL = '/api/statusnet/groups/show'
|
||||
const GROUP_TIMELINE_URL = '/api/statusnet/groups/timeline'
|
||||
const GROUP_JOINING_URL = '/api/statusnet/groups/join'
|
||||
const GROUP_LEAVING_URL = '/api/statusnet/groups/leave'
|
||||
const GROUP_CREATE_URL = '/api/statusnet/groups/create.json'
|
||||
const USER_MEMBERSHIPS_URL = '/api/statusnet/groups/list.json'
|
||||
const GROUP_MEMBERS_URL = '/api/statusnet/groups/membership'
|
||||
const GROUP_IS_MEMBER_URL = '/api/statusnet/groups/is_member.json'
|
||||
|
||||
import { each, map } from 'lodash'
|
||||
import 'whatwg-fetch'
|
||||
|
@ -254,14 +262,15 @@ const setUserMute = ({id, credentials, muted = true}) => {
|
|||
})
|
||||
}
|
||||
|
||||
const fetchTimeline = ({timeline, credentials, since = false, until = false, userId = false, tag = false}) => {
|
||||
const fetchTimeline = ({timeline, credentials, since = false, until = false, userId = false, identifier = false}) => {
|
||||
const timelineUrls = {
|
||||
public: PUBLIC_TIMELINE_URL,
|
||||
friends: FRIENDS_TIMELINE_URL,
|
||||
mentions: MENTIONS_URL,
|
||||
'publicAndExternal': PUBLIC_AND_EXTERNAL_TIMELINE_URL,
|
||||
user: QVITTER_USER_TIMELINE_URL,
|
||||
tag: TAG_TIMELINE_URL
|
||||
tag: TAG_TIMELINE_URL,
|
||||
group: GROUP_TIMELINE_URL
|
||||
}
|
||||
|
||||
let url = timelineUrls[timeline]
|
||||
|
@ -277,8 +286,8 @@ const fetchTimeline = ({timeline, credentials, since = false, until = false, use
|
|||
if (userId) {
|
||||
params.push(['user_id', userId])
|
||||
}
|
||||
if (tag) {
|
||||
url += `/${tag}.json`
|
||||
if (identifier) {
|
||||
url += `/${identifier}.json`
|
||||
}
|
||||
|
||||
const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&')
|
||||
|
@ -358,6 +367,65 @@ const fetchMutes = ({credentials}) => {
|
|||
}).then((data) => data.json())
|
||||
}
|
||||
|
||||
const fetchGroup = ({ groupName }) => {
|
||||
const url = `${GROUP_URL}/${groupName}.json`
|
||||
|
||||
return fetch(url).then((data) => data.json())
|
||||
}
|
||||
|
||||
const joinGroup = ({groupName, credentials}) => {
|
||||
const url = `${GROUP_JOINING_URL}/${groupName}.json`
|
||||
|
||||
return fetch(url, {
|
||||
headers: authHeaders(credentials),
|
||||
method: 'POST'
|
||||
}).then((data) => data.json())
|
||||
}
|
||||
|
||||
const leaveGroup = ({groupName, credentials}) => {
|
||||
const url = `${GROUP_LEAVING_URL}/${groupName}.json`
|
||||
|
||||
return fetch(url, {
|
||||
headers: authHeaders(credentials),
|
||||
method: 'POST'
|
||||
}).then((data) => data.json())
|
||||
}
|
||||
|
||||
const createGroup = ({params, credentials}) => {
|
||||
const form = new FormData()
|
||||
|
||||
each(params, (value, key) => {
|
||||
if (value) {
|
||||
form.append(key, value)
|
||||
}
|
||||
})
|
||||
|
||||
return fetch(GROUP_CREATE_URL, {
|
||||
method: 'POST',
|
||||
body: form
|
||||
})
|
||||
}
|
||||
|
||||
const fetchMemberships = ({id, credentials}) => {
|
||||
const url = `${USER_MEMBERSHIPS_URL}?user_id=${id}`
|
||||
|
||||
return fetch(url, {
|
||||
headers: authHeaders(credentials)
|
||||
}).then((data) => data.json())
|
||||
}
|
||||
|
||||
const fetchMembers = ({ groupName }) => {
|
||||
const url = `${GROUP_MEMBERS_URL}/${groupName}.json`
|
||||
|
||||
return fetch(url).then((data) => data.json())
|
||||
}
|
||||
|
||||
const fetchIsMember = ({id, groupName}) => {
|
||||
const url = `${GROUP_IS_MEMBER_URL}?user_id=${id}&group_name=${groupName}`
|
||||
|
||||
return fetch(url).then((data) => data.json())
|
||||
}
|
||||
|
||||
const apiService = {
|
||||
verifyCredentials,
|
||||
fetchTimeline,
|
||||
|
@ -384,7 +452,14 @@ const apiService = {
|
|||
updateBg,
|
||||
updateProfile,
|
||||
updateBanner,
|
||||
externalProfile
|
||||
externalProfile,
|
||||
fetchGroup,
|
||||
joinGroup,
|
||||
leaveGroup,
|
||||
createGroup,
|
||||
fetchMemberships,
|
||||
fetchMembers,
|
||||
fetchIsMember
|
||||
}
|
||||
|
||||
export default apiService
|
||||
|
|
|
@ -50,6 +50,32 @@ const backendInteractorService = (credentials) => {
|
|||
return apiService.setUserMute({id, muted, credentials})
|
||||
}
|
||||
|
||||
const fetchGroup = ({ groupName }) => {
|
||||
return apiService.fetchGroup({ groupName })
|
||||
}
|
||||
|
||||
const joinGroup = ({ groupName }) => {
|
||||
return apiService.joinGroup({groupName, credentials})
|
||||
}
|
||||
|
||||
const leaveGroup = ({ groupName }) => {
|
||||
return apiService.leaveGroup({groupName, credentials})
|
||||
}
|
||||
|
||||
const fetchMemberships = ({ id }) => {
|
||||
return apiService.fetchMemberships({id, credentials})
|
||||
}
|
||||
|
||||
const fetchMembers = ({ groupName }) => {
|
||||
return apiService.fetchMembers({ groupName })
|
||||
}
|
||||
|
||||
const fetchIsMember = ({id, groupName}) => {
|
||||
return apiService.fetchIsMember({id, groupName})
|
||||
}
|
||||
|
||||
const createGroup = (params) => apiService.createGroup({params, credentials})
|
||||
|
||||
const fetchMutes = () => apiService.fetchMutes({credentials})
|
||||
|
||||
const register = (params) => apiService.register(params)
|
||||
|
@ -80,7 +106,14 @@ const backendInteractorService = (credentials) => {
|
|||
updateBg,
|
||||
updateBanner,
|
||||
updateProfile,
|
||||
externalProfile
|
||||
externalProfile,
|
||||
fetchGroup,
|
||||
joinGroup,
|
||||
leaveGroup,
|
||||
createGroup,
|
||||
fetchMemberships,
|
||||
fetchMembers,
|
||||
fetchIsMember
|
||||
}
|
||||
|
||||
return backendInteractorServiceInstance
|
||||
|
|
|
@ -37,7 +37,7 @@ export const addPositionToWords = (words) => {
|
|||
export const splitIntoWords = (str) => {
|
||||
// Split at word boundaries
|
||||
const regex = /\b/
|
||||
const triggers = /[@#:]+$/
|
||||
const triggers = /[@#:!]+$/
|
||||
|
||||
let split = str.split(regex)
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ const update = ({store, statuses, timeline, showImmediately}) => {
|
|||
})
|
||||
}
|
||||
|
||||
const fetchAndUpdate = ({store, credentials, timeline = 'friends', older = false, showImmediately = false, userId = false, tag = false}) => {
|
||||
const fetchAndUpdate = ({store, credentials, timeline = 'friends', older = false, showImmediately = false, userId = false, identifier = false}) => {
|
||||
const args = { timeline, credentials }
|
||||
const rootState = store.rootState || store.state
|
||||
const timelineData = rootState.statuses.timelines[camelCase(timeline)]
|
||||
|
@ -26,16 +26,16 @@ const fetchAndUpdate = ({store, credentials, timeline = 'friends', older = false
|
|||
}
|
||||
|
||||
args['userId'] = userId
|
||||
args['tag'] = tag
|
||||
args['identifier'] = identifier
|
||||
|
||||
return apiService.fetchTimeline(args)
|
||||
.then((statuses) => update({store, statuses, timeline, showImmediately}),
|
||||
() => store.dispatch('setError', { value: true }))
|
||||
}
|
||||
|
||||
const startFetching = ({timeline = 'friends', credentials, store, userId = false, tag = false}) => {
|
||||
fetchAndUpdate({timeline, credentials, store, showImmediately: true, userId, tag})
|
||||
const boundFetchAndUpdate = () => fetchAndUpdate({ timeline, credentials, store, userId, tag })
|
||||
const startFetching = ({timeline = 'friends', credentials, store, userId = false, identifier = false}) => {
|
||||
fetchAndUpdate({timeline, credentials, store, showImmediately: true, userId, identifier})
|
||||
const boundFetchAndUpdate = () => fetchAndUpdate({ timeline, credentials, store, showImmediately: false, userId, identifier })
|
||||
return setInterval(boundFetchAndUpdate, 10000)
|
||||
}
|
||||
const timelineFetcher = {
|
||||
|
|
Loading…
Reference in a new issue