Page MenuHomePhorge

No OneTemporary

Authored By
Unknown
Size
19 KB
Referenced Files
None
Subscribers
None
diff --git a/src/App.js b/src/App.js
index e9cd5917d3..40f362d2c8 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,119 +1,121 @@
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 SearchBar from './components/search_bar/search_bar.vue'
import InstanceSpecificPanel from './components/instance_specific_panel/instance_specific_panel.vue'
import FeaturesPanel from './components/features_panel/features_panel.vue'
import WhoToFollowPanel from './components/who_to_follow_panel/who_to_follow_panel.vue'
import ChatPanel from './components/chat_panel/chat_panel.vue'
import MediaModal from './components/media_modal/media_modal.vue'
import SideDrawer from './components/side_drawer/side_drawer.vue'
import MobilePostStatusModal from './components/mobile_post_status_modal/mobile_post_status_modal.vue'
import MobileNav from './components/mobile_nav/mobile_nav.vue'
import UserReportingModal from './components/user_reporting_modal/user_reporting_modal.vue'
+import PostStatusModal from './components/post_status_modal/post_status_modal.vue'
import { windowWidth } from './services/window_utils/window_utils'
export default {
name: 'app',
components: {
UserPanel,
NavPanel,
Notifications,
SearchBar,
InstanceSpecificPanel,
FeaturesPanel,
WhoToFollowPanel,
ChatPanel,
MediaModal,
SideDrawer,
MobilePostStatusModal,
MobileNav,
- UserReportingModal
+ UserReportingModal,
+ PostStatusModal
},
data: () => ({
mobileActivePanel: 'timeline',
searchBarHidden: true,
supportsMask: window.CSS && window.CSS.supports && (
window.CSS.supports('mask-size', 'contain') ||
window.CSS.supports('-webkit-mask-size', 'contain') ||
window.CSS.supports('-moz-mask-size', 'contain') ||
window.CSS.supports('-ms-mask-size', 'contain') ||
window.CSS.supports('-o-mask-size', 'contain')
)
}),
created () {
// Load the locale from the storage
this.$i18n.locale = this.$store.state.config.interfaceLanguage
window.addEventListener('resize', this.updateMobileState)
},
destroyed () {
window.removeEventListener('resize', this.updateMobileState)
},
computed: {
currentUser () { return this.$store.state.users.currentUser },
background () {
return this.currentUser.background_image || this.$store.state.instance.background
},
enableMask () { return this.supportsMask && this.$store.state.instance.logoMask },
logoStyle () {
return {
'visibility': this.enableMask ? 'hidden' : 'visible'
}
},
logoMaskStyle () {
return this.enableMask ? {
'mask-image': `url(${this.$store.state.instance.logo})`
} : {
'background-color': this.enableMask ? '' : 'transparent'
}
},
logoBgStyle () {
return Object.assign({
'margin': `${this.$store.state.instance.logoMargin} 0`,
opacity: this.searchBarHidden ? 1 : 0
}, this.enableMask ? {} : {
'background-color': this.enableMask ? '' : 'transparent'
})
},
logo () { return this.$store.state.instance.logo },
bgStyle () {
return {
'background-image': `url(${this.background})`
}
},
bgAppStyle () {
return {
'--body-background-image': `url(${this.background})`
}
},
sitename () { return this.$store.state.instance.name },
chat () { return this.$store.state.chat.channel.state === 'joined' },
suggestionsEnabled () { return this.$store.state.instance.suggestionsEnabled },
showInstanceSpecificPanel () {
return this.$store.state.instance.showInstanceSpecificPanel &&
!this.$store.state.config.hideISP &&
this.$store.state.instance.instanceSpecificPanelContent
},
showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel },
isMobileLayout () { return this.$store.state.interface.mobileLayout }
},
methods: {
scrollToTop () {
window.scrollTo(0, 0)
},
logout () {
this.$router.replace('/main/public')
this.$store.dispatch('logout')
},
onSearchBarToggled (hidden) {
this.searchBarHidden = hidden
},
updateMobileState () {
const mobileLayout = windowWidth() <= 800
const changed = mobileLayout !== this.isMobileLayout
if (changed) {
this.$store.dispatch('setMobileLayout', mobileLayout)
}
}
}
}
diff --git a/src/App.vue b/src/App.vue
index 719e00a4d7..46d3ac42cf 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,117 +1,118 @@
<template>
<div
id="app"
:style="bgAppStyle"
>
<div
class="app-bg-wrapper"
:style="bgStyle"
/>
<MobileNav v-if="isMobileLayout" />
<nav
v-else
id="nav"
class="nav-bar container"
@click="scrollToTop()"
>
<div
class="logo"
:style="logoBgStyle"
>
<div
class="mask"
:style="logoMaskStyle"
/>
<img
:src="logo"
:style="logoStyle"
>
</div>
<div class="inner-nav">
<div class="item">
<router-link
class="site-name"
:to="{ name: 'root' }"
active-class="home"
>
{{ sitename }}
</router-link>
</div>
<div class="item right">
<search-bar
class="nav-icon mobile-hidden"
@toggled="onSearchBarToggled"
@click.stop.native
/>
<router-link
class="mobile-hidden"
:to="{ name: 'settings'}"
>
<i
class="button-icon icon-cog nav-icon"
:title="$t('nav.preferences')"
/>
</router-link>
<a
v-if="currentUser"
href="#"
class="mobile-hidden"
@click.prevent="logout"
><i
class="button-icon icon-logout nav-icon"
:title="$t('login.logout')"
/></a>
</div>
</div>
</nav>
<div
id="content"
class="container"
>
<div class="sidebar-flexer mobile-hidden">
<div class="sidebar-bounds">
<div class="sidebar-scroller">
<div class="sidebar">
<user-panel />
<div v-if="!isMobileLayout">
<nav-panel />
<instance-specific-panel v-if="showInstanceSpecificPanel" />
<features-panel v-if="!currentUser && showFeaturesPanel" />
<who-to-follow-panel v-if="currentUser && suggestionsEnabled" />
<notifications v-if="currentUser" />
</div>
</div>
</div>
</div>
</div>
<div class="main">
<div
v-if="!currentUser"
class="login-hint panel panel-default"
>
<router-link
:to="{ name: 'login' }"
class="panel-body"
>
{{ $t("login.hint") }}
</router-link>
</div>
<transition name="fade">
<router-view />
</transition>
</div>
<media-modal />
</div>
<chat-panel
v-if="currentUser && chat"
:floating="true"
class="floating-chat mobile-hidden"
/>
<MobilePostStatusModal />
<UserReportingModal />
+ <PostStatusModal />
<portal-target name="modal" />
</div>
</template>
<script src="./App.js"></script>
<style lang="scss" src="./App.scss"></style>
diff --git a/src/components/post_status_modal/post_status_modal.js b/src/components/post_status_modal/post_status_modal.js
new file mode 100644
index 0000000000..86a4e1d8b2
--- /dev/null
+++ b/src/components/post_status_modal/post_status_modal.js
@@ -0,0 +1,25 @@
+import PostStatusForm from '../post_status_form/post_status_form.vue'
+
+const PostStatusModal = {
+ components: {
+ PostStatusForm
+ },
+ computed: {
+ isLoggedIn () {
+ return !!this.$store.state.users.currentUser
+ },
+ isOpen () {
+ return this.isLoggedIn && this.$store.state.postStatus.modalActivated
+ },
+ params () {
+ return this.$store.state.postStatus.params
+ }
+ },
+ methods: {
+ closeModal () {
+ this.$store.dispatch('closePostStatusModal')
+ }
+ }
+}
+
+export default PostStatusModal
diff --git a/src/components/post_status_modal/post_status_modal.vue b/src/components/post_status_modal/post_status_modal.vue
new file mode 100644
index 0000000000..85a5401cff
--- /dev/null
+++ b/src/components/post_status_modal/post_status_modal.vue
@@ -0,0 +1,42 @@
+<template>
+ <div
+ v-if="isOpen"
+ class="post-form-modal-view modal-view"
+ @click="closeModal"
+ >
+ <div
+ class="post-form-modal-panel panel"
+ @click.stop=""
+ >
+ <div class="panel-heading">
+ {{ $t('post_status.new_status') }}
+ </div>
+ <PostStatusForm
+ class="panel-body"
+ @posted="closeModal"
+ />
+ </div>
+ </div>
+</template>
+
+<script src="./post_status_modal.js"></script>
+
+<style lang="scss">
+@import '../../_variables.scss';
+
+.post-form-modal-view {
+ align-items: flex-start;
+}
+
+.post-form-modal-panel {
+ flex-shrink: 0;
+ margin-top: 25%;
+ margin-bottom: 2em;
+ width: 100%;
+ max-width: 700px;
+
+ @media (orientation: landscape) {
+ margin-top: 8%;
+ }
+}
+</style>
diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js
index d42be9fc8f..0c200ad11b 100644
--- a/src/components/user_card/user_card.js
+++ b/src/components/user_card/user_card.js
@@ -1,176 +1,176 @@
import UserAvatar from '../user_avatar/user_avatar.vue'
import RemoteFollow from '../remote_follow/remote_follow.vue'
import ProgressButton from '../progress_button/progress_button.vue'
import ModerationTools from '../moderation_tools/moderation_tools.vue'
import { hex2rgb } from '../../services/color_convert/color_convert.js'
import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
export default {
props: [ 'user', 'switcher', 'selected', 'hideBio', 'rounded', 'bordered', 'allowZoomingAvatar' ],
data () {
return {
followRequestInProgress: false,
hideUserStatsLocal: typeof this.$store.state.config.hideUserStats === 'undefined'
? this.$store.state.instance.hideUserStats
: this.$store.state.config.hideUserStats,
betterShadow: this.$store.state.interface.browserSupport.cssFilter
}
},
created () {
this.$store.dispatch('fetchUserRelationship', this.user.id)
},
computed: {
classes () {
return [{
'user-card-rounded-t': this.rounded === 'top', // set border-top-left-radius and border-top-right-radius
'user-card-rounded': this.rounded === true, // set border-radius for all sides
'user-card-bordered': this.bordered === true // set border for all sides
}]
},
style () {
const color = this.$store.state.config.customTheme.colors
? this.$store.state.config.customTheme.colors.bg // v2
: this.$store.state.config.colors.bg // v1
if (color) {
const rgb = (typeof color === 'string') ? hex2rgb(color) : color
const tintColor = `rgba(${Math.floor(rgb.r)}, ${Math.floor(rgb.g)}, ${Math.floor(rgb.b)}, .5)`
const gradient = [
[tintColor, this.hideBio ? '60%' : ''],
this.hideBio ? [
color, '100%'
] : [
tintColor, ''
]
].map(_ => _.join(' ')).join(', ')
return {
backgroundColor: `rgb(${Math.floor(rgb.r * 0.53)}, ${Math.floor(rgb.g * 0.56)}, ${Math.floor(rgb.b * 0.59)})`,
backgroundImage: [
`linear-gradient(to bottom, ${gradient})`,
`url(${this.user.cover_photo})`
].join(', ')
}
}
},
isOtherUser () {
return this.user.id !== this.$store.state.users.currentUser.id
},
subscribeUrl () {
// eslint-disable-next-line no-undef
const serverUrl = new URL(this.user.statusnet_profile_url)
return `${serverUrl.protocol}//${serverUrl.host}/main/ostatus`
},
loggedIn () {
return this.$store.state.users.currentUser
},
dailyAvg () {
const days = Math.ceil((new Date() - new Date(this.user.created_at)) / (60 * 60 * 24 * 1000))
return Math.round(this.user.statuses_count / days)
},
userHighlightType: {
get () {
const data = this.$store.state.config.highlight[this.user.screen_name]
return (data && data.type) || 'disabled'
},
set (type) {
const data = this.$store.state.config.highlight[this.user.screen_name]
if (type !== 'disabled') {
this.$store.dispatch('setHighlight', { user: this.user.screen_name, color: (data && data.color) || '#FFFFFF', type })
} else {
this.$store.dispatch('setHighlight', { user: this.user.screen_name, color: undefined })
}
}
},
userHighlightColor: {
get () {
const data = this.$store.state.config.highlight[this.user.screen_name]
return data && data.color
},
set (color) {
this.$store.dispatch('setHighlight', { user: this.user.screen_name, color })
}
},
visibleRole () {
const rights = this.user.rights
if (!rights) { return }
const validRole = rights.admin || rights.moderator
const roleTitle = rights.admin ? 'admin' : 'moderator'
return validRole && roleTitle
}
},
components: {
UserAvatar,
RemoteFollow,
ModerationTools,
ProgressButton
},
methods: {
followUser () {
const store = this.$store
this.followRequestInProgress = true
requestFollow(this.user, store).then(() => {
this.followRequestInProgress = false
})
},
unfollowUser () {
const store = this.$store
this.followRequestInProgress = true
requestUnfollow(this.user, store).then(() => {
this.followRequestInProgress = false
store.commit('removeStatus', { timeline: 'friends', userId: this.user.id })
})
},
blockUser () {
this.$store.dispatch('blockUser', this.user.id)
},
unblockUser () {
this.$store.dispatch('unblockUser', this.user.id)
},
muteUser () {
this.$store.dispatch('muteUser', this.user.id)
},
unmuteUser () {
this.$store.dispatch('unmuteUser', this.user.id)
},
subscribeUser () {
return this.$store.dispatch('subscribeUser', this.user.id)
},
unsubscribeUser () {
return this.$store.dispatch('unsubscribeUser', this.user.id)
},
setProfileView (v) {
if (this.switcher) {
const store = this.$store
store.commit('setProfileView', { v })
}
},
linkClicked ({ target }) {
if (target.tagName === 'SPAN') {
target = target.parentNode
}
if (target.tagName === 'A') {
window.open(target.href, '_blank')
}
},
userProfileLink (user) {
return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)
},
reportUser () {
this.$store.dispatch('openUserReportingModal', this.user.id)
},
zoomAvatar () {
const attachment = {
url: this.user.profile_image_url_original,
mimetype: 'image'
}
this.$store.dispatch('setMedia', [attachment])
this.$store.dispatch('setCurrent', attachment)
},
mentionUser () {
-
+ this.$store.dispatch('openPostStatusModal', { replyTo: true, repliedUser: this.user })
}
}
}
diff --git a/src/main.js b/src/main.js
index b3256e8ed7..a43d31e24a 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,93 +1,95 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
import Vuex from 'vuex'
import interfaceModule from './modules/interface.js'
import instanceModule from './modules/instance.js'
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 oauthModule from './modules/oauth.js'
import authFlowModule from './modules/auth_flow.js'
import mediaViewerModule from './modules/media_viewer.js'
import oauthTokensModule from './modules/oauth_tokens.js'
import reportsModule from './modules/reports.js'
import pollsModule from './modules/polls.js'
+import postStatusModule from './modules/postStatus.js'
import VueI18n from 'vue-i18n'
import createPersistedState from './lib/persisted_state.js'
import pushNotifications from './lib/push_notifications_plugin.js'
import messages from './i18n/messages.js'
import VueChatScroll from 'vue-chat-scroll'
import VueClickOutside from 'v-click-outside'
import PortalVue from 'portal-vue'
import VTooltip from 'v-tooltip'
import afterStoreSetup from './boot/after_store.js'
const currentLocale = (window.navigator.language || 'en').split('-')[0]
Vue.use(Vuex)
Vue.use(VueRouter)
Vue.use(VueI18n)
Vue.use(VueChatScroll)
Vue.use(VueClickOutside)
Vue.use(PortalVue)
Vue.use(VTooltip)
const i18n = new VueI18n({
// By default, use the browser locale, we will update it if neccessary
locale: currentLocale,
fallbackLocale: 'en',
messages
})
const persistedStateOptions = {
paths: [
'config',
'users.lastLoginName',
'oauth'
]
};
(async () => {
const persistedState = await createPersistedState(persistedStateOptions)
const store = new Vuex.Store({
modules: {
i18n: {
getters: {
i18n: () => i18n
}
},
interface: interfaceModule,
instance: instanceModule,
statuses: statusesModule,
users: usersModule,
api: apiModule,
config: configModule,
chat: chatModule,
oauth: oauthModule,
authFlow: authFlowModule,
mediaViewer: mediaViewerModule,
oauthTokens: oauthTokensModule,
reports: reportsModule,
- polls: pollsModule
+ polls: pollsModule,
+ postStatus: postStatusModule
},
plugins: [persistedState, pushNotifications],
strict: false // Socket modifies itself, let's ignore this for now.
// strict: process.env.NODE_ENV !== 'production'
})
afterStoreSetup({ store, i18n })
})()
// These are inlined by webpack's DefinePlugin
/* eslint-disable */
window.___pleromafe_mode = process.env
window.___pleromafe_commit_hash = COMMIT_HASH
window.___pleromafe_dev_overrides = DEV_OVERRIDES
diff --git a/src/modules/postStatus.js b/src/modules/postStatus.js
new file mode 100644
index 0000000000..638c1fb202
--- /dev/null
+++ b/src/modules/postStatus.js
@@ -0,0 +1,25 @@
+const postStatus = {
+ state: {
+ params: null,
+ modalActivated: false
+ },
+ mutations: {
+ openPostStatusModal (state, params) {
+ state.params = params
+ state.modalActivated = true
+ },
+ closePostStatusModal (state) {
+ state.modalActivated = false
+ }
+ },
+ actions: {
+ openPostStatusModal ({ commit }, params) {
+ commit('openPostStatusModal', params)
+ },
+ closePostStatusModal ({ commit }) {
+ commit('closePostStatusModal')
+ }
+ }
+}
+
+export default postStatus

File Metadata

Mime Type
text/x-diff
Expires
Thu, Oct 29, 10:58 AM (21 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1798013
Default Alt Text
(19 KB)

Event Timeline