diff --git a/.babelrc b/.babelrc
index bc2b0e31ab..3c732dd1bc 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,5 +1,5 @@
{
- "presets": ["es2015", "stage-2", "env"],
- "plugins": ["transform-runtime", "lodash", "transform-vue-jsx"],
+ "presets": ["@babel/preset-env"],
+ "plugins": ["@babel/plugin-transform-runtime", "lodash", "@vue/babel-plugin-transform-vue-jsx"],
"comments": false
}
diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js
index f8968966c3..5cc0135e75 100644
--- a/build/webpack.base.conf.js
+++ b/build/webpack.base.conf.js
@@ -3,6 +3,7 @@ var config = require('../config')
var utils = require('./utils')
var projectRoot = path.resolve(__dirname, '../')
var ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin')
+var FontelloPlugin = require("fontello-webpack-plugin")
var env = process.env.NODE_ENV
// check env & config/index.js to decide weither to enable CSS Sourcemaps for the
@@ -11,6 +12,8 @@ var cssSourceMapDev = (env === 'development' && config.dev.cssSourceMap)
var cssSourceMapProd = (env === 'production' && config.build.productionSourceMap)
var useCssSourceMap = cssSourceMapDev || cssSourceMapProd
+var now = Date.now()
+
module.exports = {
entry: {
app: './src/main.js'
@@ -90,6 +93,14 @@ module.exports = {
new ServiceWorkerWebpackPlugin({
entry: path.join(__dirname, '..', 'src/sw.js'),
filename: 'sw-pleroma.js'
+ }),
+ new FontelloPlugin({
+ config: require('../static/fontello.json'),
+ name: 'fontello',
+ output: {
+ css: 'static/[name].' + now + '.css', // [hash] is not supported. Use the current timestamp instead for versioning.
+ font: 'static/font/[name].' + now + '.[ext]'
+ }
})
]
}
diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md
index 3536353725..0a9bbd7abc 100644
--- a/docs/CONFIGURATION.md
+++ b/docs/CONFIGURATION.md
@@ -77,6 +77,9 @@ Use custom image for NSFW'd images
### `showFeaturesPanel`
Show panel showcasing instance features/settings to logged-out visitors
+### `hideSitename`
+Hide instance name in header
+
## Indirect configuration
Some features are configured depending on how backend is configured. In general the approach is "if backend allows it there's no need to hide it, if backend doesn't allow it there's no need to show it.
@@ -96,3 +99,6 @@ Setting this will change the warning text that is displayed for direct messages.
ATTENTION: If you actually want the behavior to change. You will need to set the appropriate option at the backend. See the backend documentation for information about that.
DO NOT activate this without checking the backend configuration first!
+
+### Private Mode
+If the `private` instance setting is enabled in the backend, features that are not accessible without authentication, such as the timelines and search will be disabled for unauthenticated users.
diff --git a/index.html b/index.html
index 5d63238fb7..bc501dbb1a 100644
--- a/index.html
+++ b/index.html
@@ -7,8 +7,6 @@
H.M.S. Neckbeard
-
-
diff --git a/package.json b/package.json
index f039d41247..38936b2373 100644
--- a/package.json
+++ b/package.json
@@ -15,9 +15,8 @@
"lint-fix": "eslint --fix --ext .js,.vue src test/unit/specs test/e2e/specs"
},
"dependencies": {
+ "@babel/runtime": "^7.7.6",
"@chenfengyuan/vue-qrcode": "^1.0.0",
- "babel-plugin-add-module-exports": "^0.2.1",
- "babel-plugin-lodash": "^3.2.11",
"body-scroll-lock": "^2.6.4",
"chromatism": "^3.0.0",
"cropperjs": "^1.4.3",
@@ -40,20 +39,17 @@
"whatwg-fetch": "^2.0.3"
},
"devDependencies": {
- "@babel/polyfill": "^7.0.0",
+ "@babel/core": "^7.7.5",
+ "@babel/plugin-transform-runtime": "^7.7.6",
+ "@babel/preset-env": "^7.7.6",
+ "@babel/register": "^7.7.4",
+ "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0",
+ "@vue/babel-plugin-transform-vue-jsx": "^1.1.2",
"@vue/test-utils": "^1.0.0-beta.26",
"autoprefixer": "^6.4.0",
- "babel-core": "^6.0.0",
"babel-eslint": "^7.0.0",
- "babel-helper-vue-jsx-merge-props": "^2.0.3",
- "babel-loader": "^7.0.0",
- "babel-plugin-syntax-jsx": "^6.18.0",
- "babel-plugin-transform-runtime": "^6.0.0",
- "babel-plugin-transform-vue-jsx": "3",
- "babel-preset-env": "^1.7.0",
- "babel-preset-es2015": "^6.0.0",
- "babel-preset-stage-2": "^6.0.0",
- "babel-register": "^6.0.0",
+ "babel-loader": "^8.0.6",
+ "babel-plugin-lodash": "^3.3.4",
"chai": "^3.5.0",
"chalk": "^1.1.3",
"chromedriver": "^2.21.2",
@@ -72,6 +68,7 @@
"eventsource-polyfill": "^0.9.6",
"express": "^4.13.3",
"file-loader": "^3.0.1",
+ "fontello-webpack-plugin": "https://github.com/w3geo/fontello-webpack-plugin.git#6149eac8f2672ab6da089e8802fbfcac98487186",
"function-bind": "^1.0.2",
"html-webpack-plugin": "^3.0.0",
"http-proxy-middleware": "^0.17.2",
diff --git a/src/App.js b/src/App.js
index 3a5ee3b8df..778c467b07 100644
--- a/src/App.js
+++ b/src/App.js
@@ -92,6 +92,7 @@ export default {
},
sitename () { return this.$store.state.instance.name },
chat () { return this.$store.state.chat.channel.state === 'joined' },
+ hideSitename () { return this.$store.state.instance.hideSitename },
suggestionsEnabled () { return this.$store.state.instance.suggestionsEnabled },
showInstanceSpecificPanel () {
return this.$store.state.instance.showInstanceSpecificPanel &&
@@ -99,7 +100,8 @@ export default {
this.$store.state.instance.instanceSpecificPanelContent
},
showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel },
- isMobileLayout () { return this.$store.state.interface.mobileLayout }
+ isMobileLayout () { return this.$store.state.interface.mobileLayout },
+ privateMode () { return this.$store.state.instance.private }
},
methods: {
scrollToTop () {
diff --git a/src/App.scss b/src/App.scss
index da5eadec2a..4a54083860 100644
--- a/src/App.scss
+++ b/src/App.scss
@@ -865,3 +865,31 @@ nav {
.btn.btn-default {
min-height: 28px;
}
+
+.animate-spin {
+ animation: spin 2s infinite linear;
+ display: inline-block;
+}
+
+@keyframes spin {
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ transform: rotate(359deg);
+ }
+}
+
+.new-status-notification {
+ position:relative;
+ margin-top: -1px;
+ font-size: 1.1em;
+ border-width: 1px 0 0 0;
+ border-style: solid;
+ border-color: var(--border, $fallback--border);
+ padding: 10px;
+ z-index: 1;
+ background-color: $fallback--fg;
+ background-color: var(--panel, $fallback--fg);
+}
diff --git a/src/App.vue b/src/App.vue
index 750248818a..609cc6697e 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -31,6 +31,7 @@
{
copyInstanceOption('alwaysShowSubjectInput')
copyInstanceOption('noAttachmentLinks')
copyInstanceOption('showFeaturesPanel')
+ copyInstanceOption('hideSitename')
return store.dispatch('setTheme', config['theme'])
}
@@ -218,12 +219,21 @@ const getNodeInfo = async ({ store }) => {
store.dispatch('setInstanceOption', { name: 'backendVersion', value: software.version })
store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: software.name === 'pleroma' })
+ const priv = metadata.private
+ store.dispatch('setInstanceOption', { name: 'private', value: priv })
+
const frontendVersion = window.___pleromafe_commit_hash
store.dispatch('setInstanceOption', { name: 'frontendVersion', value: frontendVersion })
store.dispatch('setInstanceOption', { name: 'tagPolicyAvailable', value: metadata.federation.mrf_policies.includes('TagPolicy') })
const federation = metadata.federation
store.dispatch('setInstanceOption', { name: 'federationPolicy', value: federation })
+ store.dispatch('setInstanceOption', {
+ name: 'federating',
+ value: typeof federation.enabled === 'undefined'
+ ? true
+ : federation.enabled
+ })
const accounts = metadata.staffAccounts
await resolveStaffAccounts({ store, accounts })
diff --git a/src/components/login_form/login_form.js b/src/components/login_form/login_form.js
index 0b574a048b..0d8f1da65a 100644
--- a/src/components/login_form/login_form.js
+++ b/src/components/login_form/login_form.js
@@ -58,7 +58,7 @@ const LoginForm = {
).then((result) => {
if (result.error) {
if (result.error === 'mfa_required') {
- this.requireMFA({ app: app, settings: result })
+ this.requireMFA({ settings: result })
} else if (result.identifier === 'password_reset_required') {
this.$router.push({ name: 'password-reset', params: { passwordResetRequested: true } })
} else {
diff --git a/src/components/mfa_form/recovery_form.js b/src/components/mfa_form/recovery_form.js
index 7a3cc22d51..b25c65dd3b 100644
--- a/src/components/mfa_form/recovery_form.js
+++ b/src/components/mfa_form/recovery_form.js
@@ -8,18 +8,23 @@ export default {
}),
computed: {
...mapGetters({
- authApp: 'authFlow/app',
authSettings: 'authFlow/settings'
}),
- ...mapState({ instance: 'instance' })
+ ...mapState({
+ instance: 'instance',
+ oauth: 'oauth'
+ })
},
methods: {
...mapMutations('authFlow', ['requireTOTP', 'abortMFA']),
...mapActions({ login: 'authFlow/login' }),
clearError () { this.error = false },
submit () {
+ const { clientId, clientSecret } = this.oauth
+
const data = {
- app: this.authApp,
+ clientId,
+ clientSecret,
instance: this.instance.server,
mfaToken: this.authSettings.mfa_token,
code: this.code
diff --git a/src/components/mfa_form/totp_form.js b/src/components/mfa_form/totp_form.js
index 778bf8dce1..b774f2d0cd 100644
--- a/src/components/mfa_form/totp_form.js
+++ b/src/components/mfa_form/totp_form.js
@@ -7,18 +7,23 @@ export default {
}),
computed: {
...mapGetters({
- authApp: 'authFlow/app',
authSettings: 'authFlow/settings'
}),
- ...mapState({ instance: 'instance' })
+ ...mapState({
+ instance: 'instance',
+ oauth: 'oauth'
+ })
},
methods: {
...mapMutations('authFlow', ['requireRecovery', 'abortMFA']),
...mapActions({ login: 'authFlow/login' }),
clearError () { this.error = false },
submit () {
+ const { clientId, clientSecret } = this.oauth
+
const data = {
- app: this.authApp,
+ clientId,
+ clientSecret,
instance: this.instance.server,
mfaToken: this.authSettings.mfa_token,
code: this.code
diff --git a/src/components/mobile_nav/mobile_nav.js b/src/components/mobile_nav/mobile_nav.js
index 5a90c31f43..c1166a0cd3 100644
--- a/src/components/mobile_nav/mobile_nav.js
+++ b/src/components/mobile_nav/mobile_nav.js
@@ -29,6 +29,7 @@ const MobileNav = {
unseenNotificationsCount () {
return this.unseenNotifications.length
},
+ hideSitename () { return this.$store.state.instance.hideSitename },
sitename () { return this.$store.state.instance.name }
},
methods: {
diff --git a/src/components/mobile_nav/mobile_nav.vue b/src/components/mobile_nav/mobile_nav.vue
index d1c24e56db..51f1d6362a 100644
--- a/src/components/mobile_nav/mobile_nav.vue
+++ b/src/components/mobile_nav/mobile_nav.vue
@@ -17,6 +17,7 @@
state.users.currentUser,
+ chat: state => state.chat.channel,
+ followRequestCount: state => state.api.followRequests.length,
+ privateMode: state => state.instance.private,
+ federating: state => state.instance.federating
+ })
}
export default NavPanel
diff --git a/src/components/nav_panel/nav_panel.vue b/src/components/nav_panel/nav_panel.vue
index 28589bb14a..034259d9c5 100644
--- a/src/components/nav_panel/nav_panel.vue
+++ b/src/components/nav_panel/nav_panel.vue
@@ -4,22 +4,22 @@
- {{ $t("nav.timeline") }}
+ {{ $t("nav.timeline") }}
- {{ $t("nav.interactions") }}
+ {{ $t("nav.interactions") }}
- {{ $t("nav.dms") }}
+ {{ $t("nav.dms") }}
- {{ $t("nav.friend_requests") }}
+ {{ $t("nav.friend_requests") }}
-
+
- {{ $t("nav.public_tl") }}
+ {{ $t("nav.public_tl") }}
-
+
- {{ $t("nav.twkn") }}
+ {{ $t("nav.twkn") }}
- {{ $t("nav.about") }}
+ {{ $t("nav.about") }}
@@ -113,4 +113,8 @@
}
}
}
+
+.nav-panel .button-icon:before {
+ width: 1.1em;
+}
diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
index af6299e496..74067fef6a 100644
--- a/src/components/post_status_form/post_status_form.js
+++ b/src/components/post_status_form/post_status_form.js
@@ -169,9 +169,7 @@ const PostStatusForm = {
if (this.submitDisabled) { return }
if (this.newStatus.status === '') {
- if (this.newStatus.files.length > 0) {
- this.newStatus.status = '\u200b' // hack
- } else {
+ if (this.newStatus.files.length === 0) {
this.error = 'Cannot post an empty status with no files'
return
}
diff --git a/src/components/registration/registration.vue b/src/components/registration/registration.vue
index 5bb06a4fed..222b67a87d 100644
--- a/src/components/registration/registration.vue
+++ b/src/components/registration/registration.vue
@@ -172,7 +172,7 @@
for="captcha-label"
>{{ $t('captcha') }}
-
+
- {{ sitename }}
+ {{ sitename }}
@@ -36,7 +36,7 @@
@click="toggleDrawer"
>
- {{ $t("login.login") }}
+ {{ $t("login.login") }}
- {{ $t("nav.dms") }}
+ {{ $t("nav.dms") }}
- {{ $t("nav.interactions") }}
+ {{ $t("nav.interactions") }}
@@ -62,7 +62,7 @@
@click="toggleDrawer"
>
- {{ $t("nav.timeline") }}
+ {{ $t("nav.timeline") }}
- {{ $t("nav.friend_requests") }}
+ {{ $t("nav.friend_requests") }}
-
+
- {{ $t("nav.public_tl") }}
+ {{ $t("nav.public_tl") }}
-
+
- {{ $t("nav.twkn") }}
+ {{ $t("nav.twkn") }}
- {{ $t("nav.chat") }}
+ {{ $t("nav.chat") }}
-
+
- {{ $t("nav.search") }}
+ {{ $t("nav.search") }}
- {{ $t("nav.who_to_follow") }}
+ {{ $t("nav.who_to_follow") }}
- {{ $t("settings.settings") }}
+ {{ $t("settings.settings") }}
- {{ $t("nav.about") }}
+ {{ $t("nav.about") }}
- {{ $t("nav.administration") }}
+ {{ $t("nav.administration") }}
- {{ $t("login.logout") }}
+ {{ $t("login.logout") }}
@@ -215,6 +224,10 @@
box-shadow: var(--panelShadow);
background-color: $fallback--bg;
background-color: var(--bg, $fallback--bg);
+
+ .button-icon:before {
+ width: 1.1em;
+ }
}
.side-drawer-logo-wrapper {
diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js
index 27a9a55ed4..9a53acd683 100644
--- a/src/components/timeline/timeline.js
+++ b/src/components/timeline/timeline.js
@@ -36,7 +36,12 @@ const Timeline = {
}
},
computed: {
- timelineError () { return this.$store.state.statuses.error },
+ timelineError () {
+ return this.$store.state.statuses.error
+ },
+ errorData () {
+ return this.$store.state.statuses.errorData
+ },
newStatusCount () {
return this.timeline.newStatusCount
},
diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue
index 93f6f5706b..9777bd0c38 100644
--- a/src/components/timeline/timeline.vue
+++ b/src/components/timeline/timeline.vue
@@ -11,15 +11,22 @@
>
{{ $t('timeline.error_fetching') }}
+
+ {{ errorData.statusText }}
+
{{ $t('timeline.show_new') }}{{ newStatusCountStr }}
@@ -67,12 +74,18 @@
{{ $t('timeline.no_more_statuses') }}
+
+
+