Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85823877
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
17 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/App.js b/src/App.js
index e924896727..a052e058ea 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,43 +1,46 @@
import UserPanel from './components/user_panel/user_panel.vue'
import NavPanel from './components/nav_panel/nav_panel.vue'
import Notifications from './components/notifications/notifications.vue'
import UserFinder from './components/user_finder/user_finder.vue'
+import WhoToFollowPanel from './components/who_to_follow_panel/who_to_follow_panel.vue'
import InstanceSpecificPanel from './components/instance_specific_panel/instance_specific_panel.vue'
import ChatPanel from './components/chat_panel/chat_panel.vue'
export default {
name: 'app',
components: {
UserPanel,
NavPanel,
Notifications,
UserFinder,
- ChatPanel,
- InstanceSpecificPanel
+ WhoToFollowPanel,
+ InstanceSpecificPanel,
+ ChatPanel
},
data: () => ({
mobileActivePanel: 'timeline'
}),
computed: {
currentUser () { return this.$store.state.users.currentUser },
background () {
return this.currentUser.background_image || this.$store.state.config.background
},
logoStyle () { return { 'background-image': `url(${this.$store.state.config.logo})` } },
style () { return { 'background-image': `url(${this.background})` } },
sitename () { return this.$store.state.config.name },
chat () { return this.$store.state.chat.channel.state === 'joined' },
+ showWhoToFollowPanel () { return this.$store.state.config.showWhoToFollowPanel },
showInstanceSpecificPanel () { return this.$store.state.config.showInstanceSpecificPanel }
},
methods: {
activatePanel (panelName) {
this.mobileActivePanel = panelName
},
scrollToTop () {
window.scrollTo(0, 0)
},
logout () {
this.$store.dispatch('logout')
}
}
}
diff --git a/src/App.vue b/src/App.vue
index 2a910bc06b..1d8dd6c8f1 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,43 +1,44 @@
<template>
<div id="app" v-bind:style="style" class="base02-background">
<nav class='container base02-background base05' @click="scrollToTop()" id="nav">
<div class='inner-nav' :style="logoStyle">
<div class='item'>
<router-link :to="{ name: 'root'}">{{sitename}}</router-link>
</div>
<div class='item right'>
<user-finder class="nav-icon"></user-finder>
<router-link :to="{ name: 'settings'}"><i class="icon-cog nav-icon"></i></router-link>
<a href="#" v-if="currentUser" @click.prevent="logout"><i class="icon-logout nav-icon" :title="$t('login.logout')"></i></a>
</div>
</div>
</nav>
<div class="container" id="content">
<div class="panel-switcher">
<button @click="activatePanel('sidebar')" class="base02-background base05">Sidebar</button>
<button @click="activatePanel('timeline')" class="base02-background base05">Timeline</button>
</div>
<div class="sidebar-flexer" :class="{ 'mobile-hidden': mobileActivePanel != 'sidebar'}">
<div class="sidebar-bounds">
<div class="sidebar-scroller">
<div class="sidebar">
<user-panel></user-panel>
<nav-panel></nav-panel>
<instance-specific-panel v-if="showInstanceSpecificPanel"></instance-specific-panel>
+ <who-to-follow-panel v-if="currentUser && showWhoToFollowPanel"></who-to-follow-panel>
<chat-panel v-if="currentUser && chat"></chat-panel>
<notifications v-if="currentUser"></notifications>
</div>
</div>
</div>
</div>
<div class="main" :class="{ 'mobile-hidden': mobileActivePanel != 'timeline' }">
<transition name="fade">
<router-view></router-view>
</transition>
</div>
</div>
</div>
</template>
<script src="./App.js"></script>
<style lang="scss" src="./App.scss"></style>
diff --git a/src/components/who_to_follow_panel/who_to_follow_panel.js b/src/components/who_to_follow_panel/who_to_follow_panel.js
new file mode 100644
index 0000000000..49653c8190
--- /dev/null
+++ b/src/components/who_to_follow_panel/who_to_follow_panel.js
@@ -0,0 +1,179 @@
+const WhoToFollowPanel = {
+ data: () => ({
+ img1: '/images/avi.png',
+ link1: null,
+ name1: '',
+ img2: '/images/avi.png',
+ link2: null,
+ name2: '',
+ img3: '/images/avi.png',
+ link3: null,
+ name3: ''
+ }),
+ computed: {
+ user: function () {
+ return this.$store.state.users.currentUser.screen_name
+ },
+ moreUrl: function () {
+ var host = window.location.hostname
+ var user = this.user
+ var url = 'https://vinayaka.distsn.org/?' +
+ encodeURIComponent(host) + '+' + encodeURIComponent(user)
+ return url
+ },
+ showWhoToFollowPanel () {
+ return this.$store.state.config.showWhoToFollowPanel
+ }
+ },
+ watch: {
+ user: function (user, oldUser) {
+ function showUsers (panel, users, aHost, aUser) {
+ var cn
+ var index = 0
+ var random = Math.floor(Math.random() * 10)
+ for (cn = random; cn < users.length; cn = cn + 10) {
+ var user
+ user = users[cn]
+ var host
+ host = user.host
+ var username
+ if (user.username) {
+ username = user.username
+ } else {
+ username = user.user
+ }
+ var img
+ if (user.avatar) {
+ img = user.avatar
+ } else {
+ img = '/images/avi.png'
+ }
+ var link = 'https://' + host + '/users/' + username
+ var name = username + '@' + host
+ if ((!user.following) &&
+ (!user.blacklisted) &&
+ (!(host === aHost && username === aUser))) {
+ if (index === 0) {
+ panel.img1 = img
+ panel.link1 = link
+ panel.name1 = name
+ } else if (index === 1) {
+ panel.img2 = img
+ panel.link2 = link
+ panel.name2 = name
+ } else if (index === 2) {
+ panel.img3 = img
+ panel.link3 = link
+ panel.name3 = name
+ }
+ index = index + 1
+ if (index > 2) {
+ break
+ }
+ }
+ }
+ }
+ function getUsers (panel) {
+ var user = panel.$store.state.users.currentUser.screen_name
+ if (user) {
+ panel.name1 = 'Loading...'
+ panel.name2 = 'Loading...'
+ panel.name3 = 'Loading...'
+ var host = window.location.hostname
+ var url = 'https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-simple-api.cgi?' +
+ encodeURIComponent(host) + '+' + encodeURIComponent(user)
+ window.fetch(url, {mode: 'cors'}).then(function (response) {
+ if (response.ok) {
+ return response.json()
+ } else {
+ panel.name1 = ''
+ panel.name2 = ''
+ panel.name3 = ''
+ }
+ }).then(function (users) {
+ showUsers(panel, users, host, user)
+ })
+ }
+ }
+ if (this.showWhoToFollowPanel) {
+ getUsers(this)
+ }
+ }
+ },
+ mounted:
+ function () {
+ function showUsers (panel, users, aHost, aUser) {
+ var cn
+ var index = 0
+ var random = Math.floor(Math.random() * 10)
+ for (cn = random; cn < users.length; cn = cn + 10) {
+ var user
+ user = users[cn]
+ var host
+ host = user.host
+ var username
+ if (user.username) {
+ username = user.username
+ } else {
+ username = user.user
+ }
+ var img
+ if (user.avatar) {
+ img = user.avatar
+ } else {
+ img = '/images/avi.png'
+ }
+ var link = 'https://' + host + '/users/' + username
+ var name = username + '@' + host
+ if ((!user.following) &&
+ (!user.blacklisted) &&
+ (!(host === aHost && username === aUser))) {
+ if (index === 0) {
+ panel.img1 = img
+ panel.link1 = link
+ panel.name1 = name
+ } else if (index === 1) {
+ panel.img2 = img
+ panel.link2 = link
+ panel.name2 = name
+ } else if (index === 2) {
+ panel.img3 = img
+ panel.link3 = link
+ panel.name3 = name
+ }
+ index = index + 1
+ if (index > 2) {
+ break
+ }
+ }
+ }
+ }
+ function getUsers (panel) {
+ var user = panel.user
+ if (user) {
+ panel.name1 = 'Loading...'
+ panel.name2 = 'Loading...'
+ panel.name3 = 'Loading...'
+ var host = window.location.hostname
+ var url = 'https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-simple-api.cgi?' +
+ encodeURIComponent(host) + '+' + encodeURIComponent(user)
+ window.fetch(url, {mode: 'cors'}).then(function (response) {
+ if (response.ok) {
+ return response.json()
+ } else {
+ panel.name1 = ''
+ panel.name2 = ''
+ panel.name3 = ''
+ }
+ }).then(function (users) {
+ showUsers(panel, users, host, user)
+ })
+ }
+ }
+ if (this.showWhoToFollowPanel) {
+ getUsers(this)
+ }
+ }
+}
+
+export default WhoToFollowPanel
diff --git a/src/components/who_to_follow_panel/who_to_follow_panel.vue b/src/components/who_to_follow_panel/who_to_follow_panel.vue
new file mode 100644
index 0000000000..fff966abca
--- /dev/null
+++ b/src/components/who_to_follow_panel/who_to_follow_panel.vue
@@ -0,0 +1,37 @@
+<template>
+ <div class="who-to-follow-panel">
+ <div class="panel panel-default base01-background">
+ <div class="panel-heading timeline-heading base02-background base04">
+ <div class="title">
+ Who to follow
+ </div>
+ </div>
+ <div class="panel-body who-to-follow">
+ <p>
+ <img v-bind:src="img1"/> <a v-bind:href="link1" target="_blank">{{ name1 }}</a><br>
+ <img v-bind:src="img2"/> <a v-bind:href="link2" target="_blank">{{ name2 }}</a><br>
+ <img v-bind:src="img3"/> <a v-bind:href="link3" target="_blank">{{ name3 }}</a><br>
+ <img v-bind:src="$store.state.config.logo"> <a v-bind:href="moreUrl" target="_blank">More</a>
+ </p>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script src="./who_to_follow_panel.js" ></script>
+
+<style lang="scss">
+ .who-to-follow * {
+ vertical-align: middle;
+ }
+ .who-to-follow img {
+ width: 32px;
+ height: 32px;
+ }
+ .who-to-follow p {
+ line-height: 40px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+</style>
diff --git a/src/main.js b/src/main.js
index 6f8c00f04f..5c74da3af6 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,173 +1,174 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
import Vuex from 'vuex'
import App from './App.vue'
import PublicTimeline from './components/public_timeline/public_timeline.vue'
import PublicAndExternalTimeline from './components/public_and_external_timeline/public_and_external_timeline.vue'
import FriendsTimeline from './components/friends_timeline/friends_timeline.vue'
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 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 apiModule from './modules/api.js'
import configModule from './modules/config.js'
import chatModule from './modules/chat.js'
import VueTimeago from 'vue-timeago'
import VueI18n from 'vue-i18n'
import createPersistedState from './lib/persisted_state.js'
import messages from './i18n/messages.js'
import VueChatScroll from 'vue-chat-scroll'
const currentLocale = (window.navigator.language || 'en').split('-')[0]
Vue.use(Vuex)
Vue.use(VueRouter)
Vue.use(VueTimeago, {
locale: currentLocale === 'ja' ? 'ja' : 'en',
locales: {
'en': require('../static/timeago-en.json'),
'ja': require('../static/timeago-ja.json')
}
})
Vue.use(VueI18n)
Vue.use(VueChatScroll)
const persistedStateOptions = {
paths: [
'config.hideAttachments',
'config.hideAttachmentsInConv',
'config.hideNsfw',
'config.autoLoad',
'config.hoverPreview',
'config.streaming',
'config.muteWords',
'config.customTheme',
'users.lastLoginName'
]
}
const store = new Vuex.Store({
modules: {
statuses: statusesModule,
users: usersModule,
api: apiModule,
config: configModule,
chat: chatModule
},
plugins: [createPersistedState(persistedStateOptions)],
strict: false // Socket modifies itself, let's ignore this for now.
// strict: process.env.NODE_ENV !== 'production'
})
const i18n = new VueI18n({
locale: currentLocale,
fallbackLocale: 'en',
messages
})
window.fetch('/api/statusnet/config.json')
.then((res) => res.json())
.then((data) => {
const {name, closed: registrationClosed, textlimit} = data.site
store.dispatch('setOption', { name: 'name', value: name })
store.dispatch('setOption', { name: 'registrationOpen', value: (registrationClosed === '0') })
store.dispatch('setOption', { name: 'textlimit', value: parseInt(textlimit) })
})
window.fetch('/static/config.json')
.then((res) => res.json())
.then((data) => {
- const {theme, background, logo, showInstanceSpecificPanel} = data
+ const {theme, background, logo, showWhoToFollowPanel, showInstanceSpecificPanel} = data
store.dispatch('setOption', { name: 'theme', value: theme })
store.dispatch('setOption', { name: 'background', value: background })
store.dispatch('setOption', { name: 'logo', value: logo })
+ store.dispatch('setOption', { name: 'showWhoToFollowPanel', value: showWhoToFollowPanel })
store.dispatch('setOption', { name: 'showInstanceSpecificPanel', value: showInstanceSpecificPanel })
if (data['chatDisabled']) {
store.dispatch('disableChat')
}
const routes = [
{ name: 'root', path: '/', redirect: data['defaultPath'] || '/main/all' },
{ path: '/main/all', component: PublicAndExternalTimeline },
{ path: '/main/public', component: PublicTimeline },
{ path: '/main/friends', component: FriendsTimeline },
{ path: '/tag/:tag', component: TagTimeline },
{ name: 'conversation', path: '/notice/:id', component: ConversationPage, meta: { dontScroll: true } },
{ name: 'user-profile', path: '/users/:id', component: UserProfile },
{ name: 'mentions', path: '/:username/mentions', component: Mentions },
{ name: 'settings', path: '/settings', component: Settings },
{ name: 'registration', path: '/registration', component: Registration },
{ name: 'user-settings', path: '/user-settings', component: UserSettings }
]
const router = new VueRouter({
mode: 'history',
routes,
scrollBehavior: (to, from, savedPosition) => {
if (to.matched.some(m => m.meta.dontScroll)) {
return false
}
return savedPosition || { x: 0, y: 0 }
}
})
/* eslint-disable no-new */
new Vue({
router,
store,
i18n,
el: '#app',
render: h => h(App)
})
})
window.fetch('/static/terms-of-service.html')
.then((res) => res.text())
.then((html) => {
store.dispatch('setOption', { name: 'tos', value: html })
})
window.fetch('/api/pleroma/emoji.json')
.then(
(res) => res.json()
.then(
(values) => {
const emoji = Object.keys(values).map((key) => {
return { shortcode: key, image_url: values[key] }
})
store.dispatch('setOption', { name: 'customEmoji', value: emoji })
store.dispatch('setOption', { name: 'pleromaBackend', value: true })
},
(failure) => {
store.dispatch('setOption', { name: 'pleromaBackend', value: false })
}
),
(error) => console.log(error)
)
window.fetch('/static/emoji.json')
.then((res) => res.json())
.then((values) => {
const emoji = Object.keys(values).map((key) => {
return { shortcode: key, image_url: false, 'utf': values[key] }
})
store.dispatch('setOption', { name: 'emoji', value: emoji })
})
window.fetch('/instance/panel.html')
.then((res) => res.text())
.then((html) => {
store.dispatch('setOption', { name: 'instanceSpecificPanelContent', value: html })
})
diff --git a/static/config.json b/static/config.json
index 6c9c27dab2..23fdf8a8f9 100644
--- a/static/config.json
+++ b/static/config.json
@@ -1,8 +1,9 @@
{
"theme": "pleroma-dark",
"background": "/static/bg.jpg",
"logo": "/static/logo.png",
"defaultPath": "/main/all",
"chatDisabled": false,
+ "showWhoToFollowPanel": false,
"showInstanceSpecificPanel": false
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Oct 29, 9:54 AM (19 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1795213
Default Alt Text
(17 KB)
Attached To
Mode
rPUFE pleroma-fe-upstream
Attached
Detach File
Event Timeline