diff --git a/.babelrc b/.babelrc
index bc2b0e31a..3c732dd1b 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/docs/CONFIGURATION.md b/docs/CONFIGURATION.md
index 353635372..0a9bbd7ab 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/package.json b/package.json
index 3c9598eb2..38936b237 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",
diff --git a/src/App.js b/src/App.js
index 04a40e304..61b5eec1c 100644
--- a/src/App.js
+++ b/src/App.js
@@ -90,6 +90,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 &&
@@ -97,7 +98,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 925913f2d..754ca62e6 100644
--- a/src/App.scss
+++ b/src/App.scss
@@ -870,3 +870,16 @@ nav {
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 dbe842ec4..1b1c2648c 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 0b574a048..0d8f1da65 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 7a3cc22d5..b25c65dd3 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 778bf8dce..b774f2d0c 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 5a90c31f4..c1166a0cd 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 d1c24e56d..51f1d6362 100644
--- a/src/components/mobile_nav/mobile_nav.vue
+++ b/src/components/mobile_nav/mobile_nav.vue
@@ -17,6 +17,7 @@
{
- if (!response.ok) { return }
- store.commit('updateActivationStatus', { user: this.user, status: status })
- })
+ this.$store.dispatch('toggleActivationStatus', { user: this.user })
},
deleteUserDialog (show) {
this.showDeleteUserDialog = show
diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js
index 7f783acba..d92685858 100644
--- a/src/components/nav_panel/nav_panel.js
+++ b/src/components/nav_panel/nav_panel.js
@@ -1,20 +1,18 @@
+import { mapState } from 'vuex'
+
const NavPanel = {
created () {
if (this.currentUser && this.currentUser.locked) {
this.$store.dispatch('startFetchingFollowRequest')
}
},
- computed: {
- currentUser () {
- return this.$store.state.users.currentUser
- },
- chat () {
- return this.$store.state.chat.channel
- },
- followRequestCount () {
- return this.$store.state.api.followRequests.length
- }
- }
+ computed: mapState({
+ currentUser: state => 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 28589bb14..034259d9c 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/registration/registration.vue b/src/components/registration/registration.vue
index 5bb06a4fe..222b67a87 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/sticker_picker/sticker_picker.vue b/src/components/sticker_picker/sticker_picker.vue
index 323855b96..3863908ab 100644
--- a/src/components/sticker_picker/sticker_picker.vue
+++ b/src/components/sticker_picker/sticker_picker.vue
@@ -36,23 +36,23 @@
.sticker-picker {
width: 100%;
- position: relative;
- .tab-switcher {
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
- }
- .sticker-picker-content {
- .sticker {
- display: inline-block;
- width: 20%;
- height: 20%;
- img {
- width: 100%;
- &:hover {
- filter: drop-shadow(0 0 5px var(--link, $fallback--link));
+ .contents {
+ min-height: 250px;
+ .sticker-picker-content {
+ display: flex;
+ flex-wrap: wrap;
+ padding: 0 4px;
+ .sticker {
+ display: flex;
+ flex: 1 1 auto;
+ margin: 4px;
+ width: 56px;
+ height: 56px;
+ img {
+ height: 100%;
+ &:hover {
+ filter: drop-shadow(0 0 5px var(--link, $fallback--link));
+ }
}
}
}
diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js
index 27a9a55ed..9a53acd68 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 93f6f5706..9777bd0c3 100644
--- a/src/components/timeline/timeline.vue
+++ b/src/components/timeline/timeline.vue
@@ -11,15 +11,22 @@
>
{{ $t('timeline.error_fetching') }}
+
+ {{ errorData.statusText }}
+
@@ -67,12 +74,18 @@
{{ $t('timeline.no_more_statuses') }}
+
+
+