Compare commits

..

1 Commits

Author SHA1 Message Date
lamp 4d91a7b2c3 Fix public favorites
Show favorites tab to anyone when "Don't show list of my favorites" is unchecked.

Adapted from upstream changes by marcin mikołajczak <git@mkljczk.pl>:
https://git.pleroma.social/pleroma/pleroma-fe/-/commit/6f452d672fe740035cf1d29d03bcda0d39438753?merge_request_iid=1883
https://git.pleroma.social/pleroma/pleroma-fe/-/commit/1ceffb4e713b4b20d70121fba92d2b50f2d3cadf?merge_request_iid=1908
2024-05-06 17:55:10 -07:00
167 changed files with 6463 additions and 9738 deletions
+2
View File
@@ -0,0 +1,2 @@
build/*.js
config/*.js
+30
View File
@@ -0,0 +1,30 @@
module.exports = {
root: true,
parserOptions: {
parser: '@babel/eslint-parser',
sourceType: 'module'
},
// https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
extends: [
'plugin:vue/recommended'
],
// required to lint *.vue files
plugins: [
'vue',
'import'
],
// add your custom rules here
rules: {
// allow paren-less arrow functions
'arrow-parens': 0,
// allow async-await
'generator-star-spacing': 0,
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'vue/require-prop-types': 0,
'vue/no-unused-vars': 0,
'no-tabs': 0,
'vue/multi-word-component-names': 0,
'vue/no-reserved-component-names': 0
}
}
+1
View File
@@ -0,0 +1 @@
7.2.1
-1
View File
@@ -1 +0,0 @@
nodejs 20.12.2
+21 -27
View File
@@ -1,25 +1,24 @@
labels: platform: linux/amd64
platform: linux/amd64 pipeline:
steps:
lint: lint:
when: when:
event: event:
- pull_request - pull_request
image: node:20 image: node:18
commands: commands:
- yarn - yarn
- yarn lint - yarn lint
#- yarn stylelint
test: test:
when: when:
event: event:
- pull_request - pull_request
image: node:20 image: node:18
commands: commands:
- apt update - apt update
- apt install firefox-esr -y --no-install-recommends - apt install firefox-esr -y --no-install-recommends
- yarn - yarn
- yarn unit - yarn unit
build: build:
@@ -29,7 +28,7 @@ steps:
branch: branch:
- develop - develop
- stable - stable
image: node:20 image: node:18
commands: commands:
- yarn - yarn
- yarn build - yarn build
@@ -41,18 +40,15 @@ steps:
branch: branch:
- develop - develop
- stable - stable
image: node:20 image: node:18
environment: secrets:
SCW_ACCESS_KEY: - SCW_ACCESS_KEY
from_secret: SCW_ACCESS_KEY - SCW_SECRET_KEY
SCW_SECRET_KEY: - SCW_DEFAULT_ORGANIZATION_ID
from_secret: SCW_SECRET_KEY
SCW_DEFAULT_ORGANIZATION_ID:
from_secret: SCW_DEFAULT_ORGANIZATION_ID
commands: commands:
- apt-get update && apt-get install -y rclone wget zip - apt-get update && apt-get install -y rclone wget zip
- wget https://github.com/scaleway/scaleway-cli/releases/download/v2.30.0/scaleway-cli_2.30.0_linux_amd64 - wget https://github.com/scaleway/scaleway-cli/releases/download/v2.5.1/scaleway-cli_2.5.1_linux_amd64
- mv scaleway-cli_2.30.0_linux_amd64 scaleway-cli - mv scaleway-cli_2.5.1_linux_amd64 scaleway-cli
- chmod +x scaleway-cli - chmod +x scaleway-cli
- ./scaleway-cli object config install type=rclone - ./scaleway-cli object config install type=rclone
- zip akkoma-fe.zip -r dist - zip akkoma-fe.zip -r dist
@@ -67,17 +63,15 @@ steps:
- stable - stable
environment: environment:
CI: "true" CI: "true"
SCW_ACCESS_KEY:
from_secret: SCW_ACCESS_KEY
SCW_SECRET_KEY:
from_secret: SCW_SECRET_KEY
SCW_DEFAULT_ORGANIZATION_ID:
from_secret: SCW_DEFAULT_ORGANIZATION_ID
image: python:3.10-slim image: python:3.10-slim
secrets:
- SCW_ACCESS_KEY
- SCW_SECRET_KEY
- SCW_DEFAULT_ORGANIZATION_ID
commands: commands:
- apt-get update && apt-get install -y rclone wget git zip - apt-get update && apt-get install -y rclone wget git zip
- wget https://github.com/scaleway/scaleway-cli/releases/download/v2.30.0/scaleway-cli_2.30.0_linux_amd64 - wget https://github.com/scaleway/scaleway-cli/releases/download/v2.5.1/scaleway-cli_2.5.1_linux_amd64
- mv scaleway-cli_2.30.0_linux_amd64 scaleway-cli - mv scaleway-cli_2.5.1_linux_amd64 scaleway-cli
- chmod +x scaleway-cli - chmod +x scaleway-cli
- ./scaleway-cli object config install type=rclone - ./scaleway-cli object config install type=rclone
- cd docs - cd docs
@@ -85,4 +79,4 @@ steps:
- mkdocs build - mkdocs build
- zip -r docs.zip site/* - zip -r docs.zip site/*
- cd site - cd site
- rclone copy . scaleway:akkoma-docs/frontend/$CI_COMMIT_BRANCH/ - rclone copy . scaleway:akkoma-docs/frontend/$CI_COMMIT_BRANCH/
-2
View File
@@ -20,8 +20,6 @@ To use Akkoma-FE in Akkoma, use the [frontend](https://docs.akkoma.dev/stable/ad
## Build Setup ## Build Setup
Make sure you have [Node.js](https://nodejs.org/) installed. You can check `/.woodpecker.yml` for which node version the Akkoma CI currently uses.
``` bash ``` bash
# install dependencies # install dependencies
corepack enable corepack enable
+29 -29
View File
@@ -1,36 +1,36 @@
// https://github.com/shelljs/shelljs // https://github.com/shelljs/shelljs
require("./check-versions")(); require('./check-versions')()
require("shelljs/global"); require('shelljs/global')
env.NODE_ENV = "production"; env.NODE_ENV = 'production'
var path = require("path"); var path = require('path')
var config = require("../config"); var config = require('../config')
var webpack = require("webpack"); var ora = require('ora')
var webpackConfig = require("./webpack.prod.conf"); var webpack = require('webpack')
var webpackConfig = require('./webpack.prod.conf')
console.log( console.log(
" Tip:\n" + ' Tip:\n' +
" Built files are meant to be served over an HTTP server.\n" + ' Built files are meant to be served over an HTTP server.\n' +
" Opening index.html over file:// won't work.\n", ' Opening index.html over file:// won\'t work.\n'
); )
var assetsPath = path.join( var spinner = ora('building for production...')
config.build.assetsRoot, spinner.start()
config.build.assetsSubDirectory,
); var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory)
rm("-rf", assetsPath); rm('-rf', assetsPath)
mkdir("-p", assetsPath); mkdir('-p', assetsPath)
cp("-R", "static/*", assetsPath); cp('-R', 'static/*', assetsPath)
webpack(webpackConfig, function (err, stats) { webpack(webpackConfig, function (err, stats) {
if (err) throw err; spinner.stop()
process.stdout.write( if (err) throw err
stats.toString({ process.stdout.write(stats.toString({
colors: true, colors: true,
modules: false, modules: false,
children: false, children: false,
chunks: false, chunks: false,
chunkModules: false, chunkModules: false
}) + "\n", }) + '\n')
); })
});
+2 -8
View File
@@ -5,7 +5,7 @@ var path = require('path')
var express = require('express') var express = require('express')
var webpack = require('webpack') var webpack = require('webpack')
var opn = require('opn') var opn = require('opn')
const { createProxyMiddleware } = require('http-proxy-middleware'); var proxyMiddleware = require('http-proxy-middleware')
var webpackConfig = process.env.NODE_ENV === 'testing' var webpackConfig = process.env.NODE_ENV === 'testing'
? require('./webpack.prod.conf') ? require('./webpack.prod.conf')
: require('./webpack.dev.conf') : require('./webpack.dev.conf')
@@ -36,13 +36,7 @@ Object.keys(proxyTable).forEach(function (context) {
if (typeof options === 'string') { if (typeof options === 'string') {
options = { target: options } options = { target: options }
} }
const targetUrl = new URL(options.target); app.use(proxyMiddleware(context, options))
// add path
targetUrl.pathname = context;
options.target = targetUrl.toString();
console.log("Proxying", context, "to", options.target);
app.use(context, createProxyMiddleware(options))
}) })
// handle fallback for HTML5 history API // handle fallback for HTML5 history API
+15 -6
View File
@@ -3,7 +3,6 @@ var config = require('../config')
var utils = require('./utils') var utils = require('./utils')
var projectRoot = path.resolve(__dirname, '../') var projectRoot = path.resolve(__dirname, '../')
var { VueLoaderPlugin } = require('vue-loader') var { VueLoaderPlugin } = require('vue-loader')
const ESLintPlugin = require('eslint-webpack-plugin');
var env = process.env.NODE_ENV var env = process.env.NODE_ENV
// check env & config/index.js to decide weither to enable CSS Sourcemaps for the // check env & config/index.js to decide weither to enable CSS Sourcemaps for the
@@ -36,7 +35,6 @@ module.exports = {
], ],
fallback: { fallback: {
"url": require.resolve("url/"), "url": require.resolve("url/"),
querystring: require.resolve("querystring-es3")
}, },
alias: { alias: {
'static': path.resolve(__dirname, '../static'), 'static': path.resolve(__dirname, '../static'),
@@ -49,6 +47,20 @@ module.exports = {
module: { module: {
noParse: /node_modules\/localforage\/dist\/localforage.js/, noParse: /node_modules\/localforage\/dist\/localforage.js/,
rules: [ rules: [
{
enforce: 'pre',
test: /\.(js|vue)$/,
include: projectRoot,
exclude: /node_modules/,
use: {
loader: 'eslint-loader',
options: {
formatter: require('eslint-friendly-formatter'),
sourceMap: config.build.productionSourceMap,
extract: true
}
}
},
{ {
enforce: 'post', enforce: 'post',
test: /\.(json5?|ya?ml)$/, // target json, json5, yaml and yml files test: /\.(json5?|ya?ml)$/, // target json, json5, yaml and yml files
@@ -106,9 +118,6 @@ module.exports = {
] ]
}, },
plugins: [ plugins: [
new VueLoaderPlugin(), new VueLoaderPlugin()
new ESLintPlugin({
configType: 'flat'
})
] ]
} }
+1
View File
@@ -2,4 +2,5 @@ var { merge } = require('webpack-merge')
var devEnv = require('./dev.env') var devEnv = require('./dev.env')
module.exports = merge(devEnv, { module.exports = merge(devEnv, {
NODE_ENV: '"testing"'
}) })
-3
View File
@@ -70,9 +70,6 @@ Default post formatting option (markdown/bbcode/plaintext/etc...)
### `redirectRootNoLogin`, `redirectRootLogin` ### `redirectRootNoLogin`, `redirectRootLogin`
These two settings should point to where FE should redirect visitor when they login/open up website root These two settings should point to where FE should redirect visitor when they login/open up website root
### `scopeCopy`
Copy post scope (visibility) when replying to a post. Instance-default.
### `sidebarRight` ### `sidebarRight`
Change alignment of sidebar and panels to the right. Defaults to `false`. Change alignment of sidebar and panels to the right. Defaults to `false`.
+2 -3
View File
@@ -15,13 +15,12 @@ put a file that looks like this
```json ```json
{ {
"myPack": "/static/stickers/myPack/" "myPack": "/static/stickers/myPack"
} }
``` ```
This file is a mapping from name to pack directory location. It says "we have a pack called myPack, look for This file is a mapping from name to pack directory location. It says "we have a pack called myPack, look for
it inside `/static/stickers/myPack`". You can add as many packs as you like in this manner. it at `/static/stickers/myPack`". You can add as many packs as you like in this manner.
Note that a single leading and a trailing slash are **required** to work correctly!
## Creating the pack ## Creating the pack
-31
View File
@@ -1,31 +0,0 @@
const pluginVue = require('eslint-plugin-vue')
const pluginImport = require('eslint-plugin-import')
module.exports = [
...pluginVue.configs['flat/recommended'],
{
languageOptions: {
parserOptions: {
parser: '@babel/eslint-parser',
sourceType: 'module'
}
},
rules: {
// allow paren-less arrow functions
'arrow-parens': 0,
// allow async-await
'generator-star-spacing': 0,
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'vue/require-prop-types': 0,
'vue/no-unused-vars': 0,
'no-tabs': 0,
'vue/multi-word-component-names': 0,
'vue/no-reserved-component-names': 0
},
ignores: [
'build/*.js',
'config/*.js'
]
}
]
+1
View File
@@ -6,6 +6,7 @@
<title>Akkoma</title> <title>Akkoma</title>
<link rel="stylesheet" href="/static/font/tiresias.css"> <link rel="stylesheet" href="/static/font/tiresias.css">
<link rel="stylesheet" href="/static/font/css/lato.css"> <link rel="stylesheet" href="/static/font/css/lato.css">
<link rel="stylesheet" href="/static/mfm.css">
<link rel="stylesheet" href="/static/custom.css"> <link rel="stylesheet" href="/static/custom.css">
<link rel="stylesheet" href="/static/theme-holder.css" id="theme-holder"> <link rel="stylesheet" href="/static/theme-holder.css" id="theme-holder">
<!--server-generated-meta--> <!--server-generated-meta-->
+83 -81
View File
@@ -1,6 +1,6 @@
{ {
"name": "pleroma_fe", "name": "pleroma_fe",
"version": "3.12.0", "version": "3.10.0",
"description": "A frontend for Akkoma instances", "description": "A frontend for Akkoma instances",
"author": "Roger Braun <roger@rogerbraun.net>", "author": "Roger Braun <roger@rogerbraun.net>",
"private": true, "private": true,
@@ -12,118 +12,120 @@
"e2e": "node test/e2e/runner.js", "e2e": "node test/e2e/runner.js",
"test": "npm run unit && npm run e2e", "test": "npm run unit && npm run e2e",
"stylelint": "stylelint src/**/*.scss", "stylelint": "stylelint src/**/*.scss",
"lint": "eslint src test/unit/specs test/e2e/specs", "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs",
"lint-fix": "eslint --fix src test/unit/specs test/e2e/specs" "lint-fix": "eslint --fix --ext .js,.vue src test/unit/specs test/e2e/specs"
}, },
"dependencies": { "dependencies": {
"@babel/runtime": "7.17.8", "@babel/runtime": "7.17.8",
"@chenfengyuan/vue-qrcode": "^2.0.0", "@chenfengyuan/vue-qrcode": "2.0.0",
"@floatingghost/pinch-zoom-element": "^1.3.1", "@floatingghost/pinch-zoom-element": "^1.3.1",
"@fortawesome/fontawesome-svg-core": "^6.5.2", "@fortawesome/fontawesome-svg-core": "1.3.0",
"@fortawesome/free-regular-svg-icons": "^6.5.2", "@fortawesome/free-regular-svg-icons": "^6.1.2",
"@fortawesome/free-solid-svg-icons": "^6.5.2", "@fortawesome/free-solid-svg-icons": "^6.2.0",
"@fortawesome/vue-fontawesome": "^3.0.8", "@fortawesome/vue-fontawesome": "3.0.1",
"@vuelidate/core": "^2.0.3", "@vuelidate/core": "^2.0.0",
"@vuelidate/validators": "^2.0.4", "@vuelidate/validators": "^2.0.0",
"blurhash": "^2.0.5", "blurhash": "^2.0.4",
"body-scroll-lock": "^3.1.5", "body-scroll-lock": "2.7.1",
"chromatism": "^3.0.0", "chromatism": "3.0.0",
"click-outside-vue3": "^4.0.1", "click-outside-vue3": "4.0.1",
"cropperjs": "^1.6.2", "cropperjs": "1.5.12",
"diff": "^5.2.0", "diff": "3.5.0",
"escape-html": "^1.0.3", "escape-html": "1.0.3",
"iso-639-1": "^2.1.15", "iso-639-1": "^2.1.15",
"js-cookie": "^3.0.1", "js-cookie": "^3.0.1",
"localforage": "^1.10.0", "localforage": "1.10.0",
"parse-link-header": "^2.0.0", "parse-link-header": "^2.0.0",
"phoenix": "^1.7.12", "phoenix": "1.6.2",
"punycode.js": "^2.3.1", "punycode.js": "2.1.0",
"qrcode": "^1.5.3", "qrcode": "1",
"querystring-es3": "^0.2.1", "url": "^0.11.0",
"url": "^0.11.3", "vue": "^3.2.31",
"vue": "^3.4.38", "vue-i18n": "^9.2.2",
"vue-i18n": "^9.14.0", "vue-router": "4.0.14",
"vue-router": "^4.4.3", "vue-template-compiler": "2.6.11",
"vue-template-compiler": "^2.7.16", "vuex": "4.0.2"
"vuex": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.24.6", "@babel/core": "7.17.8",
"@babel/eslint-parser": "^7.19.1", "@babel/eslint-parser": "^7.19.1",
"@babel/plugin-transform-runtime": "^7.24.6", "@babel/plugin-transform-runtime": "7.17.0",
"@babel/preset-env": "^7.24.6", "@babel/preset-env": "7.16.11",
"@babel/register": "^7.24.6", "@babel/register": "7.17.7",
"@intlify/vue-i18n-loader": "^5.0.0", "@intlify/vue-i18n-loader": "^5.0.0",
"@ungap/event-target": "^0.2.4", "@ungap/event-target": "0.2.3",
"@vue/babel-helper-vue-jsx-merge-props": "^1.4.0", "@vue/babel-helper-vue-jsx-merge-props": "1.2.1",
"@vue/babel-plugin-jsx": "^1.2.2", "@vue/babel-plugin-jsx": "1.1.1",
"@vue/compiler-sfc": "^3.1.0", "@vue/compiler-sfc": "^3.1.0",
"@vue/test-utils": "^2.0.2", "@vue/test-utils": "^2.0.2",
"autoprefixer": "^10.4.19", "autoprefixer": "6.7.7",
"babel-loader": "^9.1.0", "babel-loader": "^9.1.0",
"babel-plugin-lodash": "^3.3.4", "babel-plugin-lodash": "3.3.4",
"chai": "^4.3.7", "chai": "^4.3.7",
"chalk": "^1.1.3", "chalk": "1.1.3",
"chromedriver": "^119.0.1", "chromedriver": "^107.0.3",
"connect-history-api-fallback": "^2.0.0", "connect-history-api-fallback": "^2.0.0",
"cross-spawn": "^7.0.3", "cross-spawn": "^7.0.3",
"css-loader": "^7.1.2", "css-loader": "^6.7.2",
"custom-event-polyfill": "^1.0.7", "custom-event-polyfill": "^1.0.7",
"eslint": "^9.3.0", "eslint": "^7.32.0",
"eslint-config-standard": "^17.1.0", "eslint-config-standard": "^17.0.0",
"eslint-friendly-formatter": "^4.0.1", "eslint-friendly-formatter": "^4.0.1",
"eslint-plugin-import": "^2.29.1", "eslint-loader": "^4.0.2",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-node": "^11.1.0", "eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.2.0", "eslint-plugin-promise": "^6.1.1",
"eslint-plugin-standard": "^5.0.0", "eslint-plugin-standard": "^5.0.0",
"eslint-plugin-vue": "^9.26.0", "eslint-plugin-vue": "^9.7.0",
"eslint-webpack-plugin": "^4.2.0", "eventsource-polyfill": "0.9.6",
"eventsource-polyfill": "^0.9.6", "express": "4.17.3",
"express": "^4.19.2",
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"function-bind": "^1.1.2", "function-bind": "1.1.1",
"html-webpack-plugin": "^5.5.0", "html-webpack-plugin": "^5.5.0",
"http-proxy-middleware": "^3.0.0", "http-proxy-middleware": "0.21.0",
"json-loader": "^0.5.7", "inject-loader": "2.0.1",
"karma": "^6.4.3", "isparta-loader": "2.0.0",
"karma-coverage": "^2.2.1", "json-loader": "0.5.7",
"karma-firefox-launcher": "^2.1.3", "karma": "6.3.17",
"karma-mocha": "^2.0.1", "karma-coverage": "1.1.2",
"karma-mocha-reporter": "^2.2.5", "karma-firefox-launcher": "1.3.0",
"karma-sinon-chai": "^2.0.2", "karma-mocha": "2.0.1",
"karma-sourcemap-loader": "^0.4.0", "karma-mocha-reporter": "2.2.5",
"karma-spec-reporter": "^0.0.36", "karma-sinon-chai": "2.0.2",
"karma-sourcemap-loader": "0.3.8",
"karma-spec-reporter": "0.0.33",
"karma-webpack": "^5.0.0", "karma-webpack": "^5.0.0",
"lodash": "^4.17.21", "lodash": "4.17.21",
"lolex": "^6.0.0", "lolex": "1.6.0",
"mini-css-extract-plugin": "^2.9.0", "mini-css-extract-plugin": "0.12.0",
"mocha": "^10.4.0", "mocha": "3.5.3",
"nightwatch": "^3.6.3", "nightwatch": "0.9.21",
"opn": "^6.0.0", "opn": "4.0.2",
"ora": "0.4.1",
"postcss-html": "^1.5.0", "postcss-html": "^1.5.0",
"postcss-loader": "^8.1.1", "postcss-loader": "3.0.0",
"postcss-sass": "^0.5.0", "postcss-sass": "^0.5.0",
"raw-loader": "^4.0.2", "raw-loader": "0.5.1",
"sass": "^1.77.2", "sass": "^1.56.0",
"sass-loader": "^14.2.1", "sass-loader": "^13.2.0",
"selenium-server": "^3.141.59", "selenium-server": "2.53.1",
"semver": "^7.6.2", "semver": "5.7.1",
"shelljs": "^0.8.5", "shelljs": "0.8.5",
"sinon": "^18.0.0", "sinon": "2.4.1",
"sinon-chai": "^3.7.0", "sinon-chai": "2.14.0",
"stylelint": "^14.15.0", "stylelint": "^14.15.0",
"stylelint-config-recommended-vue": "^1.4.0", "stylelint-config-recommended-vue": "^1.4.0",
"stylelint-config-standard": "^29.0.0", "stylelint-config-standard": "^29.0.0",
"stylelint-config-standard-scss": "^6.1.0", "stylelint-config-standard-scss": "^6.1.0",
"stylelint-rscss": "^0.4.0", "stylelint-rscss": "^0.4.0",
"url-loader": "^4.1.1", "url-loader": "^4.1.1",
"vue-loader": "^17.4.2", "vue-loader": "^17.0.0",
"vue-style-loader": "^4.1.3", "vue-style-loader": "^4.1.2",
"webpack": "^5.91.0", "webpack": "^5.75.0",
"webpack-dev-middleware": "^7.2.1", "webpack-dev-middleware": "^5.3.3",
"webpack-hot-middleware": "^2.26.1", "webpack-hot-middleware": "^2.25.1",
"webpack-merge": "^5.10.0", "webpack-merge": "^5.8.0",
"workbox-webpack-plugin": "^7.1.0" "workbox-webpack-plugin": "^6.5.4"
}, },
"engines": { "engines": {
"node": ">= 16.0.0", "node": ">= 16.0.0",
+1 -5
View File
@@ -59,8 +59,7 @@ export default {
{ {
'-reverse': this.reverseLayout, '-reverse': this.reverseLayout,
'-no-sticky-headers': this.noSticky, '-no-sticky-headers': this.noSticky,
'-has-new-post-button': this.newPostButtonShown, '-has-new-post-button': this.newPostButtonShown
'-wide-timeline': this.widenTimeline
}, },
'-' + this.layoutType '-' + this.layoutType
] ]
@@ -94,9 +93,6 @@ export default {
newPostButtonShown () { newPostButtonShown () {
return this.$store.getters.mergedConfig.alwaysShowNewPostButton || this.layoutType === 'mobile' return this.$store.getters.mergedConfig.alwaysShowNewPostButton || this.layoutType === 'mobile'
}, },
widenTimeline () {
return this.$store.getters.mergedConfig.widenTimeline
},
showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel }, showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel },
editingAvailable () { return this.$store.state.instance.editingAvailable }, editingAvailable () { return this.$store.state.instance.editingAvailable },
layoutType () { return this.$store.state.interface.layoutType }, layoutType () { return this.$store.state.interface.layoutType },
-9
View File
@@ -172,10 +172,6 @@ nav {
background-color: rgba(0, 0, 0, 0.15); background-color: rgba(0, 0, 0, 0.15);
background-color: var(--underlay, rgba(0, 0, 0, 0.15)); background-color: var(--underlay, rgba(0, 0, 0, 0.15));
z-index: -1000; z-index: -1000;
.-wide-timeline & {
margin:0 calc(var(--columnGap) / -2);
}
} }
.app-layout { .app-layout {
@@ -191,17 +187,12 @@ nav {
grid-template-rows: 1fr; grid-template-rows: 1fr;
box-sizing: border-box; box-sizing: border-box;
margin: 0 auto; margin: 0 auto;
padding: 0 calc(var(--columnGap) / 2);
align-content: flex-start; align-content: flex-start;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: center; justify-content: center;
min-height: 100vh; min-height: 100vh;
overflow-x: clip; overflow-x: clip;
&.-wide-timeline {
--maxiColumn: minmax(var(--miniColumn), 1fr);
}
.column { .column {
--___columnMargin: var(--columnGap); --___columnMargin: var(--columnGap);
-8
View File
@@ -173,10 +173,8 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
copyInstanceOption('redirectRootNoLogin') copyInstanceOption('redirectRootNoLogin')
copyInstanceOption('redirectRootLogin') copyInstanceOption('redirectRootLogin')
copyInstanceOption('showInstanceSpecificPanel') copyInstanceOption('showInstanceSpecificPanel')
copyInstanceOption('minimalScopesMode')
copyInstanceOption('hideMutedPosts') copyInstanceOption('hideMutedPosts')
copyInstanceOption('collapseMessageWithSubject') copyInstanceOption('collapseMessageWithSubject')
copyInstanceOption('scopeCopy')
copyInstanceOption('subjectLineBehavior') copyInstanceOption('subjectLineBehavior')
copyInstanceOption('postContentType') copyInstanceOption('postContentType')
copyInstanceOption('alwaysShowSubjectInput') copyInstanceOption('alwaysShowSubjectInput')
@@ -185,12 +183,6 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
copyInstanceOption('renderMisskeyMarkdown') copyInstanceOption('renderMisskeyMarkdown')
copyInstanceOption('sidebarRight') copyInstanceOption('sidebarRight')
if (config.backendCommitUrl)
copyInstanceOption('backendCommitUrl')
if (config.frontendCommitUrl)
copyInstanceOption('frontendCommitUrl')
return store.dispatch('setTheme', config['theme']) return store.dispatch('setTheme', config['theme'])
} }
+1 -1
View File
@@ -9,7 +9,7 @@
</div> </div>
</template> </template>
<script src="./about.js"></script> <script src="./about.js" ></script>
<style lang="scss"> <style lang="scss">
</style> </style>
@@ -6,7 +6,7 @@
:bound-to="{ x: 'container' }" :bound-to="{ x: 'container' }"
remove-padding remove-padding
> >
<template #content> <template v-slot:content>
<div class="dropdown-menu"> <div class="dropdown-menu">
<template v-if="relationship.following"> <template v-if="relationship.following">
<button <button
@@ -71,7 +71,7 @@
</button> </button>
</div> </div>
</template> </template>
<template #trigger> <template v-slot:trigger>
<button class="button-unstyled ellipsis-button"> <button class="button-unstyled ellipsis-button">
<FAIcon <FAIcon
class="icon" class="icon"
@@ -93,7 +93,7 @@
keypath="user_card.block_confirm" keypath="user_card.block_confirm"
tag="span" tag="span"
> >
<template #user> <template v-slot:user>
<span <span
v-text="user.screen_name_ui" v-text="user.screen_name_ui"
/> />
+1 -22
View File
@@ -16,14 +16,9 @@
.attachment-wrapper { .attachment-wrapper {
flex: 1 1 auto; flex: 1 1 auto;
min-height: 200px; height: 200px;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
align-content: center;
.status-popover & {
height: 200px;
}
} }
.description-container { .description-container {
@@ -120,22 +115,6 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding-top: 0.5em; padding-top: 0.5em;
p {
line-height: 1.5;
padding: 0 0.5em;
white-space: pre-line;
text-align: center;
max-height: 200px;
overflow-y: auto;
scrollbar-color: var(--border) #0000;
.status-popover & {
text-overflow: ellipsis;
overflow: hidden;
height: 1lh;
}
}
} }
+2 -2
View File
@@ -246,8 +246,8 @@
ref="flash" ref="flash"
class="flash" class="flash"
:src="attachment.large_thumb_url || attachment.url" :src="attachment.large_thumb_url || attachment.url"
@player-opened="setFlashLoaded(true)" @playerOpened="setFlashLoaded(true)"
@player-closed="setFlashLoaded(false)" @playerClosed="setFlashLoaded(false)"
/> />
</span> </span>
</div> </div>
+1 -1
View File
@@ -14,7 +14,7 @@
</div> </div>
</template> </template>
<script src="./avatar_list.js"></script> <script src="./avatar_list.js" ></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import '../../_variables.scss';
+2 -2
View File
@@ -22,12 +22,12 @@
<script> <script>
export default { export default {
emits: ['update:modelValue'],
props: [ props: [
'modelValue', 'modelValue',
'indeterminate', 'indeterminate',
'disabled' 'disabled'
], ]
emits: ['update:modelValue']
} }
</script> </script>
+2 -2
View File
@@ -14,7 +14,7 @@
:model-value="present" :model-value="present"
:disabled="disabled" :disabled="disabled"
class="opt" class="opt"
@update:model-value="$emit('update:modelValue', typeof modelValue === 'undefined' ? fallback : undefined)" @update:modelValue="$emit('update:modelValue', typeof modelValue === 'undefined' ? fallback : undefined)"
/> />
<div class="input color-input-field"> <div class="input color-input-field">
<input <input
@@ -46,6 +46,7 @@
</div> </div>
</div> </div>
</template> </template>
<style lang="scss" src="./color_input.scss"></style>
<script> <script>
import Checkbox from '../checkbox/checkbox.vue' import Checkbox from '../checkbox/checkbox.vue'
import { hex2rgb } from '../../services/color_convert/color_convert.js' import { hex2rgb } from '../../services/color_convert/color_convert.js'
@@ -107,7 +108,6 @@ export default {
} }
} }
</script> </script>
<style lang="scss" src="./color_input.scss"></style>
<style lang="scss"> <style lang="scss">
.color-control { .color-control {
@@ -25,8 +25,6 @@
</dialog-modal> </dialog-modal>
</template> </template>
<script src="./confirm_modal.js"></script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '../../_variables'; @import '../../_variables';
@@ -37,3 +35,5 @@
} }
} }
</style> </style>
<script src="./confirm_modal.js"></script>
+3 -11
View File
@@ -267,11 +267,11 @@ const conversation = {
}, },
replies () { replies () {
let i = 1 let i = 1
// eslint-disable-next-line camelcase
return reduce(this.conversation, (result, { id, in_reply_to_status_id }) => { return reduce(this.conversation, (result, { id, in_reply_to_status_id }) => {
/* eslint-disable camelcase */
const irid = in_reply_to_status_id const irid = in_reply_to_status_id
/* eslint-enable camelcase */
if (irid) { if (irid) {
result[irid] = result[irid] || [] result[irid] = result[irid] || []
result[irid].push({ result[irid].push({
@@ -414,14 +414,6 @@ const conversation = {
}, },
toggleExpanded () { toggleExpanded () {
this.expanded = !this.expanded this.expanded = !this.expanded
const navHeight = document.getElementById("nav").offsetHeight
const headingHeight = document.getElementsByClassName("timeline-heading")[0].offsetHeight
document.documentElement.style.setProperty("--timeline-scroll-margin-top", `${navHeight + headingHeight}px`)
this.$nextTick(() => {
if (!this.expanded) {
this.$el.scrollIntoView({ block: 'nearest' })
}
})
}, },
getConversationId (statusId) { getConversationId (statusId) {
const status = this.$store.state.statuses.allStatusesObject[statusId] const status = this.$store.state.statuses.allStatusesObject[statusId]
+2 -4
View File
@@ -91,7 +91,7 @@
:controlled-set-media-playing="(newVal) => toggleStatusContentProperty(status.id, 'mediaPlaying', newVal)" :controlled-set-media-playing="(newVal) => toggleStatusContentProperty(status.id, 'mediaPlaying', newVal)"
@goto="setHighlight" @goto="setHighlight"
@toggle-expanded="toggleExpanded" @toggleExpanded="toggleExpanded"
/> />
<div <div
v-if="showOtherRepliesButtonBelowStatus && getReplies(status.id).length > 1" v-if="showOtherRepliesButtonBelowStatus && getReplies(status.id).length > 1"
@@ -184,7 +184,7 @@
:toggle-status-content-property="toggleStatusContentProperty" :toggle-status-content-property="toggleStatusContentProperty"
@goto="setHighlight" @goto="setHighlight"
@toggle-expanded="toggleExpanded" @toggleExpanded="toggleExpanded"
/> />
</div> </div>
</div> </div>
@@ -278,7 +278,5 @@
&.-expanded.status-fadein { &.-expanded.status-fadein {
margin: calc(var(--status-margin, $status-margin) / 2); margin: calc(var(--status-margin, $status-margin) / 2);
} }
scroll-margin-block-start: var(--timeline-scroll-margin-top);
} }
</style> </style>
+2 -2
View File
@@ -44,9 +44,9 @@
/> />
</router-link> </router-link>
<router-link <router-link
v-if="publicTimelineVisible"
:to="{ name: 'public-timeline' }" :to="{ name: 'public-timeline' }"
class="nav-icon" class="nav-icon"
v-if="publicTimelineVisible"
> >
<FAIcon <FAIcon
fixed-width fixed-width
@@ -68,9 +68,9 @@
/> />
</router-link> </router-link>
<router-link <router-link
v-if="federatedTimelineVisible"
:to="{ name: 'public-external-timeline' }" :to="{ name: 'public-external-timeline' }"
class="nav-icon" class="nav-icon"
v-if="federatedTimelineVisible"
> >
<FAIcon <FAIcon
fixed-width fixed-width
@@ -9,7 +9,7 @@
class="btn button-default" class="btn button-default"
> >
{{ $t('domain_mute_card.unmute') }} {{ $t('domain_mute_card.unmute') }}
<template #progress> <template v-slot:progress>
{{ $t('domain_mute_card.unmute_progress') }} {{ $t('domain_mute_card.unmute_progress') }}
</template> </template>
</ProgressButton> </ProgressButton>
@@ -19,7 +19,7 @@
class="btn button-default" class="btn button-default"
> >
{{ $t('domain_mute_card.mute') }} {{ $t('domain_mute_card.mute') }}
<template #progress> <template v-slot:progress>
{{ $t('domain_mute_card.mute_progress') }} {{ $t('domain_mute_card.mute_progress') }}
</template> </template>
</ProgressButton> </ProgressButton>
@@ -2,7 +2,7 @@
<Modal <Modal
v-if="isFormVisible" v-if="isFormVisible"
class="edit-form-modal-view" class="edit-form-modal-view"
@backdrop-clicked="closeModal" @backdropClicked="closeModal"
> >
<div class="edit-form-modal-panel panel"> <div class="edit-form-modal-panel panel">
<div class="panel-heading"> <div class="panel-heading">
@@ -11,10 +11,10 @@
<PostStatusForm <PostStatusForm
class="panel-body" class="panel-body"
v-bind="params" v-bind="params"
:disable-polls="true"
:disable-visibility-selector="true"
:post-handler="doEditStatus"
@posted="closeModal" @posted="closeModal"
:disablePolls="true"
:disableVisibilitySelector="true"
:post-handler="doEditStatus"
/> />
</div> </div>
</Modal> </Modal>
-5
View File
@@ -1,5 +1,3 @@
import StillImage from '../still-image/still-image.vue'
const EMOJI_SIZE = 32 + 8 const EMOJI_SIZE = 32 + 8
const GROUP_TITLE_HEIGHT = 24 const GROUP_TITLE_HEIGHT = 24
const BUFFER_SIZE = 3 * EMOJI_SIZE const BUFFER_SIZE = 3 * EMOJI_SIZE
@@ -19,9 +17,6 @@ const EmojiGrid = {
resizeObserver: null resizeObserver: null
} }
}, },
components: {
StillImage
},
mounted () { mounted () {
const rect = this.$refs.container.getBoundingClientRect() const rect = this.$refs.container.getBoundingClientRect()
this.containerWidth = rect.width this.containerWidth = rect.width
+2 -3
View File
@@ -34,11 +34,10 @@
@click.stop.prevent="onEmoji(item.emoji)" @click.stop.prevent="onEmoji(item.emoji)"
> >
<span v-if="!item.emoji.imageUrl">{{ item.emoji.replacement }}</span> <span v-if="!item.emoji.imageUrl">{{ item.emoji.replacement }}</span>
<StillImage <img
v-else v-else
:src="item.emoji.imageUrl" :src="item.emoji.imageUrl"
noStopGifs="true" >
/>
</span> </span>
</template> </template>
</div> </div>
+1 -3
View File
@@ -1,6 +1,5 @@
import Completion from '../../services/completion/completion.js' import Completion from '../../services/completion/completion.js'
import EmojiPicker from '../emoji_picker/emoji_picker.vue' import EmojiPicker from '../emoji_picker/emoji_picker.vue'
import StillImage from '../still-image/still-image.vue'
import { take } from 'lodash' import { take } from 'lodash'
import { findOffset } from '../../services/offset_finder/offset_finder.service.js' import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
@@ -121,8 +120,7 @@ const EmojiInput = {
} }
}, },
components: { components: {
EmojiPicker, EmojiPicker
StillImage
}, },
computed: { computed: {
padEmoji () { padEmoji () {
+3 -8
View File
@@ -20,7 +20,6 @@
ref="picker" ref="picker"
show-keep-open show-keep-open
:class="{ hide: !showPicker }" :class="{ hide: !showPicker }"
:visible="showPicker"
:enable-sticker-picker="enableStickerPicker" :enable-sticker-picker="enableStickerPicker"
class="emoji-picker-panel" class="emoji-picker-panel"
@emoji="insert" @emoji="insert"
@@ -44,15 +43,11 @@
:class="{ highlighted: index === highlighted }" :class="{ highlighted: index === highlighted }"
@click.stop.prevent="onClick($event, suggestion)" @click.stop.prevent="onClick($event, suggestion)"
> >
<span <span v-if="!suggestion.mfm" class="image">
v-if="!suggestion.mfm" <img
class="image"
>
<StillImage
v-if="suggestion.img" v-if="suggestion.img"
:src="suggestion.img" :src="suggestion.img"
noStopGifs="true" >
/>
<span v-else>{{ suggestion.replacement }}</span> <span v-else>{{ suggestion.replacement }}</span>
</span> </span>
<div class="label"> <div class="label">
+3 -3
View File
@@ -1,4 +1,4 @@
const MFM_TAGS = ['bg', 'blur', 'bounce', 'center', 'fg', 'flip', 'font', 'jelly', 'jump', 'position', 'rainbow', 'rotate', 'scale', 'shake', 'sparkle', 'spin', 'tada', 'twitch', 'x2', 'x3', 'x4'] const MFM_TAGS = ['blur', 'bounce', 'flip', 'font', 'jelly', 'jump', 'rainbow', 'rotate', 'shake', 'sparkle', 'spin', 'tada', 'twitch', 'x2', 'x3', 'x4']
.map(tag => ({ displayText: tag, detailText: '$[' + tag + ' ]', replacement: '$[' + tag + ' ]', mfm: true })) .map(tag => ({ displayText: tag, detailText: '$[' + tag + ' ]', replacement: '$[' + tag + ' ]', mfm: true }))
/** /**
@@ -122,14 +122,14 @@ export const suggestUsers = ({ dispatch, state }) => {
const screenNameAlphabetically = a.screen_name > b.screen_name ? 1 : -1 const screenNameAlphabetically = a.screen_name > b.screen_name ? 1 : -1
return diff + nameAlphabetically + screenNameAlphabetically return diff + nameAlphabetically + screenNameAlphabetically
/* eslint-disable camelcase */
}).map(({ screen_name, screen_name_ui, name, profile_image_url_original }) => ({ }).map(({ screen_name, screen_name_ui, name, profile_image_url_original }) => ({
displayText: screen_name_ui, displayText: screen_name_ui,
detailText: name, detailText: name,
imageUrl: profile_image_url_original, imageUrl: profile_image_url_original,
replacement: '@' + screen_name + ' ' replacement: '@' + screen_name + ' '
})) }))
/* eslint-enable camelcase */
suggestions = newSuggestions || [] suggestions = newSuggestions || []
return suggestions return suggestions
+2 -21
View File
@@ -1,7 +1,6 @@
import { defineAsyncComponent } from 'vue' import { defineAsyncComponent } from 'vue'
import Checkbox from '../checkbox/checkbox.vue' import Checkbox from '../checkbox/checkbox.vue'
import EmojiGrid from '../emoji_grid/emoji_grid.vue' import EmojiGrid from '../emoji_grid/emoji_grid.vue'
import StillImage from '../still-image/still-image.vue'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
faBoxOpen, faBoxOpen,
@@ -27,17 +26,12 @@ const EmojiPicker = {
required: false, required: false,
type: Boolean, type: Boolean,
default: false default: false
},
visible: {
required: false,
type: Boolean,
default: true
} }
}, },
data () { data () {
return { return {
keyword: '', keyword: '',
activeGroup: this.getDefaultGroup(), activeGroup: 'standard',
showingStickers: false, showingStickers: false,
keepOpen: false keepOpen: false
} }
@@ -45,8 +39,7 @@ const EmojiPicker = {
components: { components: {
StickerPicker: defineAsyncComponent(() => import('../sticker_picker/sticker_picker.vue')), StickerPicker: defineAsyncComponent(() => import('../sticker_picker/sticker_picker.vue')),
Checkbox, Checkbox,
EmojiGrid, EmojiGrid
StillImage
}, },
methods: { methods: {
debouncedSearch: debounce(function (e) { debouncedSearch: debounce(function (e) {
@@ -89,11 +82,6 @@ const EmojiPicker = {
return list.filter(emoji => { return list.filter(emoji => {
return (regex.test(emoji.displayText) || (!emoji.imageUrl && emoji.replacement === this.keyword)) return (regex.test(emoji.displayText) || (!emoji.imageUrl && emoji.replacement === this.keyword))
}) })
},
getDefaultGroup () {
if (!this.visible) return null
const recentEmojis = this.$store.getters.recentEmojis
return recentEmojis.length === 0 ? 'standard' : 'recent'
} }
}, },
computed: { computed: {
@@ -160,13 +148,6 @@ const EmojiPicker = {
stickerPickerEnabled () { stickerPickerEnabled () {
return (this.$store.state.instance.stickers || []).length !== 0 && this.enableStickerPicker return (this.$store.state.instance.stickers || []).length !== 0 && this.enableStickerPicker
} }
},
watch: {
visible (val, oldVal) {
if (val && this.activeGroup === null) {
this.activeGroup = this.getDefaultGroup()
}
}
} }
} }
+2 -3
View File
@@ -18,11 +18,10 @@
@click.prevent="highlight(group.id)" @click.prevent="highlight(group.id)"
> >
<span v-if="!group.first.imageUrl">{{ group.first.replacement }}</span> <span v-if="!group.first.imageUrl">{{ group.first.replacement }}</span>
<StillImage <img
v-else v-else
:src="group.first.imageUrl" :src="group.first.imageUrl"
noStopGifs="true" >
/>
</span> </span>
<span <span
v-if="stickerPickerEnabled" v-if="stickerPickerEnabled"
@@ -11,7 +11,7 @@
@click="emojiOnClick(reaction.name, $event)" @click="emojiOnClick(reaction.name, $event)"
@mouseenter="fetchEmojiReactionsByIfMissing()" @mouseenter="fetchEmojiReactionsByIfMissing()"
> >
<template <span
v-if="reaction.url !== null" v-if="reaction.url !== null"
> >
<StillImage <StillImage
@@ -19,15 +19,16 @@
:title="reaction.name" :title="reaction.name"
:alt="reaction.name" :alt="reaction.name"
class="reaction-emoji" class="reaction-emoji"
height="2.55em"
/> />
{{ reaction.count }} {{ reaction.count }}
</template> </span>
<template v-else> <span v-else>
<span class="reaction-emoji unicode-emoji"> <span class="reaction-emoji unicode-emoji">
{{ reaction.name }} {{ reaction.name }}
</span> </span>
<span>{{ reaction.count }}</span> <span>{{ reaction.count }}</span>
</template> </span>
</button> </button>
</UserListPopover> </UserListPopover>
<a <a
@@ -41,7 +42,7 @@
</div> </div>
</template> </template>
<script src="./emoji_reactions.js"></script> <script src="./emoji_reactions.js" ></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import '../../_variables.scss';
@@ -52,26 +53,23 @@
container-type: inline-size; container-type: inline-size;
} }
.unicode-emoji {
font-size: 210%;
}
.emoji-reaction { .emoji-reaction {
padding: 2px 0.5em; padding: 0 0.5em;
margin-right: 0.5em; margin-right: 0.5em;
margin-top: 0.5em; margin-top: 0.5em;
display: flex; display: flex;
align-items: end; align-items: center;
justify-content: center;
box-sizing: border-box;
.reaction-emoji { .reaction-emoji {
width: auto; width: auto;
max-width: 96cqw; max-width: 96cqw;
height: 2.55em !important;
margin-right: 0.25em; margin-right: 0.25em;
&.still-image {
height: 2.55em;
}
&.unicode-emoji {
display: inline-block;
font-size: 2.125em; // assuming default line height of 1.2rem and emojis that don't exceed line height
line-height: 2.55rem;
}
} }
&:focus { &:focus {
outline: none; outline: none;
@@ -99,9 +97,9 @@
} }
.button-default.picked-reaction { .button-default.picked-reaction {
&, &:hover { border: 1px solid var(--accent, $fallback--link);
box-shadow: inset 0 0 0 1px var(--accent, $fallback--link); margin-left: -1px; // offset the border, can't use inset shadows either
} margin-right: calc(0.5em - 1px);
} }
</style> </style>
@@ -7,7 +7,7 @@
:bound-to="{ x: 'container' }" :bound-to="{ x: 'container' }"
remove-padding remove-padding
> >
<template #content="{close}"> <template v-slot:content="{close}">
<div class="dropdown-menu"> <div class="dropdown-menu">
<button <button
v-if="canMute && !status.thread_muted" v-if="canMute && !status.thread_muted"
@@ -172,7 +172,7 @@
</button> </button>
</div> </div>
</template> </template>
<template #trigger> <template v-slot:trigger>
<button class="button-unstyled popover-trigger"> <button class="button-unstyled popover-trigger">
<FAIcon <FAIcon
class="fa-scale-110 fa-old-padding" class="fa-scale-110 fa-old-padding"
@@ -205,7 +205,7 @@
</Popover> </Popover>
</template> </template>
<script src="./extra_buttons.js"></script> <script src="./extra_buttons.js" ></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import '../../_variables.scss';
@@ -35,7 +35,7 @@
</div> </div>
</template> </template>
<script src="./favorite_button.js"></script> <script src="./favorite_button.js" ></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import '../../_variables.scss';
@@ -4,7 +4,6 @@ const FeaturesPanel = {
computed: { computed: {
whoToFollow: function () { return this.$store.state.instance.suggestionsEnabled }, whoToFollow: function () { return this.$store.state.instance.suggestionsEnabled },
mediaProxy: function () { return this.$store.state.instance.mediaProxyAvailable }, mediaProxy: function () { return this.$store.state.instance.mediaProxyAvailable },
minimalScopesMode: function () { return this.$store.state.instance.minimalScopesMode },
textlimit: function () { return this.$store.state.instance.textlimit }, textlimit: function () { return this.$store.state.instance.textlimit },
uploadlimit: function () { return fileSizeFormatService.fileSizeFormat(this.$store.state.instance.uploadlimit) } uploadlimit: function () { return fileSizeFormatService.fileSizeFormat(this.$store.state.instance.uploadlimit) }
} }
@@ -23,7 +23,7 @@
</div> </div>
</template> </template>
<script src="./features_panel.js"></script> <script src="./features_panel.js" ></script>
<style lang="scss"> <style lang="scss">
.features-panel li { .features-panel li {
@@ -1,8 +1,5 @@
<template> <template>
<basic-user-card <basic-user-card :user="user" v-if="show">
v-if="show"
:user="user"
>
<div class="follow-request-card-content-container"> <div class="follow-request-card-content-container">
<button <button
class="btn button-default" class="btn button-default"
+1 -1
View File
@@ -47,7 +47,7 @@
</div> </div>
</template> </template>
<script src="./font_control.js"></script> <script src="./font_control.js" ></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import '../../_variables.scss';
+4 -2
View File
@@ -88,8 +88,10 @@ const Gallery = {
set(this.sizes, id, { width, height }) set(this.sizes, id, { width, height })
}, },
rowStyle (row) { rowStyle (row) {
if (!row.audio && !row.minimal && !row.grid) { if (row.audio) {
return { 'aspect-ratio': `1/${(1 / (row.items.length + 0.6))}` } return { 'padding-bottom': '25%' } // fixed reduced height for audio
} else if (!row.minimal && !row.grid) {
return { 'padding-bottom': `${(100 / (row.items.length + 0.6))}%` }
} }
}, },
itemStyle (id, row) { itemStyle (id, row) {
+3 -9
View File
@@ -31,8 +31,8 @@
:description="descriptions && descriptions[attachment.id]" :description="descriptions && descriptions[attachment.id]"
:hide-description="size === 'small' || tooManyAttachments && hidingLong" :hide-description="size === 'small' || tooManyAttachments && hidingLong"
:style="itemStyle(attachment.id, row.items)" :style="itemStyle(attachment.id, row.items)"
@set-media="onMedia" @setMedia="onMedia"
@natural-size-load="onNaturalSizeLoad" @naturalSizeLoad="onNaturalSizeLoad"
/> />
</div> </div>
</div> </div>
@@ -96,15 +96,9 @@
.gallery-row { .gallery-row {
position: relative; position: relative;
height: 0;
width: 100%; width: 100%;
flex-grow: 1; flex-grow: 1;
.Status & {
max-height: 30em;
}
&.-audio {
aspect-ratio: 4/1; // this is terrible, but it's how it was before so I'm not changing it >:(
}
&:not(:first-child) { &:not(:first-child) {
margin-top: 0.5em; margin-top: 0.5em;
+2 -2
View File
@@ -14,6 +14,6 @@
</span> </span>
</template> </template>
<script src="./hashtag_link.js" /> <script src="./hashtag_link.js"/>
<style lang="scss" src="./hashtag_link.scss" /> <style lang="scss" src="./hashtag_link.scss"/>
@@ -10,4 +10,4 @@
</div> </div>
</template> </template>
<script src="./instance_specific_panel.js"></script> <script src="./instance_specific_panel.js" ></script>
-1
View File
@@ -42,7 +42,6 @@ export default {
@import '../../_variables.scss'; @import '../../_variables.scss';
.list { .list {
min-height: 1em;
&-item:not(:last-child) { &-item:not(:last-child) {
border-bottom: 1px solid; border-bottom: 1px solid;
border-bottom-color: $fallback--border; border-bottom-color: $fallback--border;
@@ -10,7 +10,7 @@
</div> </div>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<p>{{ $t("about.bubble_instances_description") }}:</p> <p>{{ $t("about.bubble_instances_description")}}:</p>
<ul> <ul>
<li <li
v-for="instance in bubbleInstances" v-for="instance in bubbleInstances"
+1 -1
View File
@@ -90,7 +90,7 @@
</div> </div>
</template> </template>
<script src="./login_form.js"></script> <script src="./login_form.js" ></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import '../../_variables.scss';
+3 -4
View File
@@ -2,7 +2,7 @@
<Modal <Modal
v-if="showing" v-if="showing"
class="media-modal-view" class="media-modal-view"
@backdrop-clicked="hideIfNotSwiped" @backdropClicked="hideIfNotSwiped"
> >
<SwipeClick <SwipeClick
v-if="type === 'image'" v-if="type === 'image'"
@@ -24,15 +24,14 @@
:min-scale="pinchZoomMinScale" :min-scale="pinchZoomMinScale"
:reset-to-min-scale-limit="pinchZoomScaleResetLimit" :reset-to-min-scale-limit="pinchZoomScaleResetLimit"
> >
<StillImage <img
:class="{ loading }" :class="{ loading }"
class="modal-image" class="modal-image"
:src="currentMedia.url" :src="currentMedia.url"
:alt="currentMedia.description" :alt="currentMedia.description"
:title="currentMedia.description" :title="currentMedia.description"
@load="onImageLoaded" @load="onImageLoaded"
noStopGifs="true" >
/>
</PinchZoom> </PinchZoom>
</SwipeClick> </SwipeClick>
<VideoAttachment <VideoAttachment
+1 -1
View File
@@ -42,7 +42,7 @@ const mediaUpload = {
.then((fileData) => { .then((fileData) => {
self.$emit('uploaded', fileData) self.$emit('uploaded', fileData)
self.decreaseUploadCount() self.decreaseUploadCount()
}, (error) => { }, (error) => { // eslint-disable-line handle-callback-err
self.$emit('upload-failed', 'default') self.$emit('upload-failed', 'default')
self.decreaseUploadCount() self.decreaseUploadCount()
}) })
+1 -1
View File
@@ -26,7 +26,7 @@
</label> </label>
</template> </template>
<script src="./media_upload.js"></script> <script src="./media_upload.js" ></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import '../../_variables.scss';
+2 -2
View File
@@ -66,6 +66,6 @@
</span> </span>
</template> </template>
<script src="./mention_link.js" /> <script src="./mention_link.js"/>
<style lang="scss" src="./mention_link.scss" /> <style lang="scss" src="./mention_link.scss"/>
@@ -37,5 +37,5 @@
</span> </span>
</span> </span>
</template> </template>
<script src="./mentions_line.js"></script> <script src="./mentions_line.js" ></script>
<style lang="scss" src="./mentions_line.scss" /> <style lang="scss" src="./mentions_line.scss" />
+1 -1
View File
@@ -69,4 +69,4 @@
</div> </div>
</div> </div>
</template> </template>
<script src="./recovery_form.js"></script> <script src="./recovery_form.js" ></script>
-1
View File
@@ -18,7 +18,6 @@
<input <input
id="code" id="code"
v-model="code" v-model="code"
autocomplete="one-time-code"
class="form-control" class="form-control"
> >
</div> </div>
@@ -4,7 +4,7 @@
class="panel-heading" class="panel-heading"
@click="toggleHidden" @click="toggleHidden"
> >
<h4>{{ $t('moderation.reports.report') + ' ' + account.screen_name }}</h4> <h4>{{ $t('moderation.reports.report') + ' ' + this.account.screen_name }}</h4>
<button <button
v-if="isOpen" v-if="isOpen"
class="button-default" class="button-default"
@@ -24,7 +24,7 @@
class="button-default" class="button-default"
@click.stop="updateReportState('open')" @click.stop="updateReportState('open')"
> >
{{ $t('moderation.reports.reopen') }} {{ $t('moderation.reports.reopen') }}
</button> </button>
</div> </div>
<div <div
@@ -35,10 +35,7 @@
<div v-if="content"> <div v-if="content">
{{ decode(content) }} {{ decode(content) }}
</div> </div>
<i <i v-else class="faint">
v-else
class="faint"
>
{{ $t('moderation.reports.no_content') }} {{ $t('moderation.reports.no_content') }}
</i> </i>
<div class="report-author"> <div class="report-author">
@@ -46,12 +43,12 @@
class="small-avatar" class="small-avatar"
:user="actor" :user="actor"
/> />
{{ actor.screen_name }} {{ this.actor.screen_name }}
</div> </div>
</div> </div>
<div <div
v-if="!hidden && statuses.length > 0"
class="dropdown" class="dropdown"
v-if="!hidden && this.statuses.length > 0"
> >
<button <button
class="button button-unstyled dropdown-header" class="button button-unstyled dropdown-header"
@@ -77,8 +74,8 @@
</div> </div>
</div> </div>
<div <div
v-if="!hidden && notes.length > 0"
class="dropdown" class="dropdown"
v-if="!hidden && this.notes.length > 0"
> >
<button <button
class="button button-unstyled dropdown-header" class="button button-unstyled dropdown-header"
@@ -102,9 +99,9 @@
</div> </div>
<div class="report-add-note"> <div class="report-add-note">
<textarea <textarea
v-model.trim="note"
rows="1" rows="1"
cols="1" cols="1"
v-model.trim="note"
:placeholder="$t('moderation.reports.note_placeholder')" :placeholder="$t('moderation.reports.note_placeholder')"
/> />
<button <button
@@ -137,7 +134,7 @@
:offset="{ y: 5 }" :offset="{ y: 5 }"
remove-padding remove-padding
> >
<template #trigger> <template v-slot:trigger>
<button <button
class="btn button-default" class="btn button-default"
:disabled="!tagPolicyEnabled" :disabled="!tagPolicyEnabled"
@@ -150,7 +147,7 @@
/> />
</button> </button>
</template> </template>
<template #content="{close}"> <template v-slot:content="{close}">
<div <div
class="dropdown-menu" class="dropdown-menu"
:disabled="!tagPolicyEnabled" :disabled="!tagPolicyEnabled"
@@ -6,7 +6,7 @@
class="small-avatar" class="small-avatar"
:user="user" :user="user"
/> />
{{ user.screen_name }} {{ this.user.screen_name }}
</div> </div>
<div class="header-right"> <div class="header-right">
<Timeago <Timeago
-3
View File
@@ -22,9 +22,6 @@ export default {
default: false default: false
} }
}, },
emits: [
'backdropClicked',
],
computed: { computed: {
classes () { classes () {
return { return {
@@ -8,7 +8,7 @@
@show="setToggled(true)" @show="setToggled(true)"
@close="setToggled(false)" @close="setToggled(false)"
> >
<template #content> <template v-slot:content>
<div class="dropdown-menu"> <div class="dropdown-menu">
<span v-if="user.is_local"> <span v-if="user.is_local">
<button <button
@@ -122,7 +122,7 @@
</span> </span>
</div> </div>
</template> </template>
<template #trigger> <template v-slot:trigger>
<button <button
class="btn button-default btn-block moderation-tools-button" class="btn button-default btn-block moderation-tools-button"
:class="{ toggled }" :class="{ toggled }"
@@ -137,11 +137,11 @@
v-if="showDeleteUserDialog" v-if="showDeleteUserDialog"
:on-cancel="deleteUserDialog.bind(this, false)" :on-cancel="deleteUserDialog.bind(this, false)"
> >
<template #header> <template v-slot:header>
{{ $t('user_card.admin_menu.delete_user') }} {{ $t('user_card.admin_menu.delete_user') }}
</template> </template>
<p>{{ $t('user_card.admin_menu.delete_user_confirmation') }}</p> <p>{{ $t('user_card.admin_menu.delete_user_confirmation') }}</p>
<template #footer> <template v-slot:footer>
<button <button
class="btn button-default" class="btn button-default"
@click="deleteUserDialog(false)" @click="deleteUserDialog(false)"
+1 -1
View File
@@ -102,7 +102,7 @@
</div> </div>
</template> </template>
<script src="./nav_panel.js"></script> <script src="./nav_panel.js" ></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import '../../_variables.scss';
+1 -3
View File
@@ -6,7 +6,6 @@ import UserCard from '../user_card/user_card.vue'
import Timeago from '../timeago/timeago.vue' import Timeago from '../timeago/timeago.vue'
import RichContent from 'src/components/rich_content/rich_content.jsx' import RichContent from 'src/components/rich_content/rich_content.jsx'
import ConfirmModal from '../confirm_modal/confirm_modal.vue' import ConfirmModal from '../confirm_modal/confirm_modal.vue'
import StillImage from '../still-image/still-image.vue'
import { isStatusNotification } from '../../services/notification_utils/notification_utils.js' import { isStatusNotification } from '../../services/notification_utils/notification_utils.js'
import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js' import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
@@ -51,8 +50,7 @@ const Notification = {
Timeago, Timeago,
Status, Status,
RichContent, RichContent,
ConfirmModal, ConfirmModal
StillImage
}, },
methods: { methods: {
toggleUserExpanded () { toggleUserExpanded () {
@@ -101,8 +101,4 @@
color: $fallback--cBlue; color: $fallback--cBlue;
color: var(--cBlue, $fallback--cBlue); color: var(--cBlue, $fallback--cBlue);
} }
.attachment-wrapper {
min-height: unset;
}
} }
+3 -4
View File
@@ -116,13 +116,12 @@
scope="global" scope="global"
keypath="notifications.reacted_with" keypath="notifications.reacted_with"
> >
<still-image <img
v-if="notification.emoji_url !== null" v-if="notification.emoji_url !== null"
class="notification-reaction-emoji" class="notification-reaction-emoji"
:src="notification.emoji_url" :src="notification.emoji_url"
:title="notification.emoji" :name="notification.emoji"
:alt="notification.emoji" >
/>
<span <span
v-else v-else
class="emoji-reaction-emoji" class="emoji-reaction-emoji"
@@ -5,7 +5,7 @@
placement="bottom" placement="bottom"
:bound-to="{ x: 'container' }" :bound-to="{ x: 'container' }"
> >
<template #content> <template v-slot:content>
<div class="dropdown-menu"> <div class="dropdown-menu">
<button <button
class="button-default dropdown-item" class="button-default dropdown-item"
@@ -72,7 +72,7 @@
</button> </button>
</div> </div>
</template> </template>
<template #trigger> <template v-slot:trigger>
<button class="filter-trigger-button button-unstyled"> <button class="filter-trigger-button button-unstyled">
<FAIcon icon="filter" /> <FAIcon icon="filter" />
</button> </button>
@@ -14,7 +14,7 @@
:model-value="present" :model-value="present"
:disabled="disabled" :disabled="disabled"
class="opt" class="opt"
@update:model-value="$emit('update:modelValue', !present ? fallback : undefined)" @update:modelValue="$emit('update:modelValue', !present ? fallback : undefined)"
/> />
<input <input
:id="name" :id="name"
+1
View File
@@ -2,6 +2,7 @@
<pinch-zoom <pinch-zoom
class="pinch-zoom-parent" class="pinch-zoom-parent"
v-bind="$attrs" v-bind="$attrs"
v-on="$listeners"
> >
<slot /> <slot />
</pinch-zoom> </pinch-zoom>
+2 -10
View File
@@ -50,13 +50,6 @@ export default {
totalVotesCount () { totalVotesCount () {
return this.poll.votes_count return this.poll.votes_count
}, },
totalFractionBase () {
// Due to a backend bug, we might not have any voter count info for remote polls
// in this case, fall back to count of votes even for multiple cjoice polls
// to be able to at least display _something_
const total_base = this.poll.multiple ? this.poll.voters_count : this.poll.votes_count
return total_base > 0 ? total_base : this.poll.votes_count
},
containerClass () { containerClass () {
return { return {
loading: this.loading loading: this.loading
@@ -77,11 +70,10 @@ export default {
}, },
methods: { methods: {
percentageForOption (count) { percentageForOption (count) {
const total = this.totalFractionBase return this.totalVotesCount === 0 ? 0 : Math.round(count / this.totalVotesCount * 100)
return total === 0 ? 0 : Math.round(count / total * 100)
}, },
resultTitle (option) { resultTitle (option) {
return `${option.votes_count}/${this.totalFractionBase} ${this.$t('polls.votes')}` return `${option.votes_count}/${this.totalVotesCount} ${this.$t('polls.votes')}`
}, },
fetchPoll () { fetchPoll () {
this.$store.dispatch('refreshPoll', { id: this.statusId, pollId: this.poll.id }) this.$store.dispatch('refreshPoll', { id: this.statusId, pollId: this.poll.id })
-2
View File
@@ -24,7 +24,6 @@
<button <button
v-if="options.length > 2" v-if="options.length > 2"
class="delete-option button-unstyled -hover-highlight" class="delete-option button-unstyled -hover-highlight"
type="button"
@click="deleteOption(index)" @click="deleteOption(index)"
> >
<FAIcon icon="times" /> <FAIcon icon="times" />
@@ -33,7 +32,6 @@
<button <button
v-if="options.length < maxOptions" v-if="options.length < maxOptions"
class="add-option faint button-unstyled -hover-highlight" class="add-option faint button-unstyled -hover-highlight"
type="button"
@click="addOption" @click="addOption"
> >
<FAIcon <FAIcon
@@ -9,13 +9,11 @@ import StatusContent from '../status_content/status_content.vue'
import fileTypeService from '../../services/file_type/file_type.service.js' import fileTypeService from '../../services/file_type/file_type.service.js'
import { findOffset } from '../../services/offset_finder/offset_finder.service.js' import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
import { reject, map, uniqBy, debounce } from 'lodash' import { reject, map, uniqBy, debounce } from 'lodash'
import { usePostLanguageOptions } from 'src/lib/post_language'
import scopeUtils from 'src/lib/scope_utils.js'
import suggestor from '../emoji_input/suggestor.js' import suggestor from '../emoji_input/suggestor.js'
import { mapGetters, mapState } from 'vuex' import { mapGetters, mapState } from 'vuex'
import Checkbox from '../checkbox/checkbox.vue' import Checkbox from '../checkbox/checkbox.vue'
import Select from '../select/select.vue' import Select from '../select/select.vue'
import iso6391 from 'iso-639-1'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
@@ -64,13 +62,6 @@ const deleteDraft = (draftKey) => {
localStorage.setItem('drafts', JSON.stringify(draftData)); localStorage.setItem('drafts', JSON.stringify(draftData));
} }
const interfaceToISOLanguage = (ilang) => {
const sep = ilang.indexOf("_");
return sep < 0 ?
ilang :
ilang.substr(0, sep);
}
const PostStatusForm = { const PostStatusForm = {
props: [ props: [
'statusId', 'statusId',
@@ -86,7 +77,6 @@ const PostStatusForm = {
'quoteId', 'quoteId',
'repliedUser', 'repliedUser',
'attentions', 'attentions',
'copyMessageLanguage',
'copyMessageScope', 'copyMessageScope',
'subject', 'subject',
'disableSubject', 'disableSubject',
@@ -139,13 +129,6 @@ const PostStatusForm = {
this.$refs.textarea.focus() this.$refs.textarea.focus()
} }
}, },
setup() {
const {postLanguageOptions} = usePostLanguageOptions()
return {
postLanguageOptions,
}
},
data () { data () {
const preset = this.$route.query.message const preset = this.$route.query.message
let statusText = preset || '' let statusText = preset || ''
@@ -155,7 +138,7 @@ const PostStatusForm = {
statusText = buildMentionsString({ user: this.repliedUser, attentions: this.attentions }, currentUser) statusText = buildMentionsString({ user: this.repliedUser, attentions: this.attentions }, currentUser)
} }
const { postContentType: contentType, sensitiveByDefault, sensitiveIfSubject, alwaysShowSubjectInput } = this.$store.getters.mergedConfig const { postContentType: contentType, sensitiveByDefault, sensitiveIfSubject, interfaceLanguage, alwaysShowSubjectInput } = this.$store.getters.mergedConfig
let statusParams = { let statusParams = {
spoilerText: this.subject || '', spoilerText: this.subject || '',
@@ -166,7 +149,7 @@ const PostStatusForm = {
poll: {}, poll: {},
mediaDescriptions: {}, mediaDescriptions: {},
visibility: this.suggestedVisibility(), visibility: this.suggestedVisibility(),
language: this.suggestedLanguage(), language: interfaceLanguage,
contentType contentType
} }
@@ -181,7 +164,7 @@ const PostStatusForm = {
poll: this.statusPoll || {}, poll: this.statusPoll || {},
mediaDescriptions: this.statusMediaDescriptions || {}, mediaDescriptions: this.statusMediaDescriptions || {},
visibility: this.statusScope || this.suggestedVisibility(), visibility: this.statusScope || this.suggestedVisibility(),
language: this.statusLanguage || this.suggestedLanguage(), language: this.statusLanguage || interfaceLanguage,
contentType: statusContentType contentType: statusContentType
} }
} }
@@ -247,9 +230,6 @@ const PostStatusForm = {
userDefaultScope () { userDefaultScope () {
return this.$store.state.users.currentUser.default_scope return this.$store.state.users.currentUser.default_scope
}, },
showAllScopes () {
return !this.mergedConfig.minimalScopesMode
},
emojiUserSuggestor () { emojiUserSuggestor () {
return suggestor({ return suggestor({
emoji: [ emoji: [
@@ -291,9 +271,6 @@ const PostStatusForm = {
isOverLengthLimit () { isOverLengthLimit () {
return this.hasStatusLengthLimit && (this.charactersLeft < 0) return this.hasStatusLengthLimit && (this.charactersLeft < 0)
}, },
minimalScopesMode () {
return this.$store.state.instance.minimalScopesMode
},
alwaysShowSubject () { alwaysShowSubject () {
return this.mergedConfig.alwaysShowSubjectInput return this.mergedConfig.alwaysShowSubjectInput
}, },
@@ -332,11 +309,13 @@ const PostStatusForm = {
...mapState({ ...mapState({
mobileLayout: state => state.interface.mobileLayout mobileLayout: state => state.interface.mobileLayout
}), }),
isoLanguages () {
return iso6391.getAllCodes();
}
}, },
watch: { watch: {
'newStatus': { 'newStatus': {
deep: true, deep: true,
flush: 'sync',
handler () { handler () {
this.statusChanged() this.statusChanged()
} }
@@ -349,22 +328,17 @@ const PostStatusForm = {
this.saveDraft() this.saveDraft()
}, },
clearStatus () { clearStatus () {
const config = this.$store.getters.mergedConfig const newStatus = this.newStatus
this.newStatus = { this.newStatus = {
status: '', status: '',
spoilerText: '', spoilerText: '',
files: [], files: [],
nsfw: !!config.sensitiveByDefault, visibility: newStatus.visibility,
visibility: this.suggestedVisibility(), contentType: newStatus.contentType,
contentType: config.postContentType, language: newStatus.language,
language: this.suggestedLanguage(),
poll: {}, poll: {},
mediaDescriptions: {} mediaDescriptions: {}
} }
const scopeselector = this.$refs.scopeselector
if (scopeselector) {
scopeselector.currentScope = this.newStatus.visibility
}
this.pollFormVisible = false this.pollFormVisible = false
this.$refs.mediaUpload && this.$refs.mediaUpload.clearFile() this.$refs.mediaUpload && this.$refs.mediaUpload.clearFile()
this.clearPollForm() this.clearPollForm()
@@ -524,7 +498,7 @@ const PostStatusForm = {
addMediaFile (fileInfo) { addMediaFile (fileInfo) {
this.newStatus.files.push(fileInfo) this.newStatus.files.push(fileInfo)
if (this.$store.getters.mergedConfig.sensitiveIfSubject && this.newStatus.spoilerText !== '' || !!this.$store.getters.mergedConfig.sensitiveByDefault) { if (this.$store.getters.mergedConfig.sensitiveIfSubject && this.newStatus.spoilerText !== '') {
this.newStatus.nsfw = true this.newStatus.nsfw = true
} }
this.$emit('resize', { delayed: true }) this.$emit('resize', { delayed: true })
@@ -773,19 +747,16 @@ const PostStatusForm = {
openProfileTab () { openProfileTab () {
this.$store.dispatch('openSettingsModalTab', 'profile') this.$store.dispatch('openSettingsModalTab', 'profile')
}, },
suggestedLanguage () {
// Make sure the inherited language is actually valid
if (this.postLanguageOptions.find(o => o.value === this.copyMessageLanguage)) {
return this.copyMessageLanguage
}
const { postLanguage: defaultPostLanguage, interfaceLanguage } = this.$store.getters.mergedConfig
const postLanguage = defaultPostLanguage || interfaceToISOLanguage(interfaceLanguage)
return postLanguage
},
suggestedVisibility () { suggestedVisibility () {
const maxScope = this.copyMessageScope if (this.copyMessageScope) {
const defaultScope = this.$store.state.users.currentUser.default_scope if (this.copyMessageScope === 'direct') {
return scopeUtils.negotiate(defaultScope, maxScope) return this.copyMessageScope
}
if (this.copyMessageScope !== 'public' && this.$store.state.users.currentUser.default_scope !== 'private') {
return this.copyMessageScope
}
}
return this.$store.state.users.currentUser.default_scope
} }
} }
} }
@@ -18,7 +18,6 @@
> >
<button <button
class="button-unstyled -link" class="button-unstyled -link"
type="button"
@click="openProfileTab" @click="openProfileTab"
> >
{{ $t('post_status.account_not_locked_warning_link') }} {{ $t('post_status.account_not_locked_warning_link') }}
@@ -119,8 +118,8 @@
/> />
</div> </div>
<EmojiInput <EmojiInput
v-if="subjectVisible"
ref="subject-emoji-input" ref="subject-emoji-input"
v-if="subjectVisible"
v-model="newStatus.spoilerText" v-model="newStatus.spoilerText"
enable-emoji-picker enable-emoji-picker
hide-emoji-button hide-emoji-button
@@ -137,7 +136,6 @@
class="form-post-subject" class="form-post-subject"
@input="onSubjectInput" @input="onSubjectInput"
@focus="focusSubjectInput()" @focus="focusSubjectInput()"
@keydown.exact.enter.prevent
> >
</EmojiInput> </EmojiInput>
<i18n-t <i18n-t
@@ -172,7 +170,7 @@
cols="1" cols="1"
:disabled="posting && !optimisticPosting" :disabled="posting && !optimisticPosting"
class="form-post-body" class="form-post-body"
:class="{ 'scrollable-form': !!maxHeight, '-has-subject': subjectVisible }" :class="{ 'scrollable-form': !!maxHeight }"
@keydown.exact.enter="submitOnEnter && postStatus($event, newStatus)" @keydown.exact.enter="submitOnEnter && postStatus($event, newStatus)"
@keydown.meta.enter="postStatus($event, newStatus)" @keydown.meta.enter="postStatus($event, newStatus)"
@keydown.ctrl.enter="!submitOnEnter && postStatus($event, newStatus)" @keydown.ctrl.enter="!submitOnEnter && postStatus($event, newStatus)"
@@ -192,12 +190,9 @@
<div <div
v-if="!disableScopeSelector" v-if="!disableScopeSelector"
class="visibility-tray" class="visibility-tray"
:class="{ 'visibility-tray-edit': isEdit }"
> >
<scope-selector <scope-selector
ref="scopeselector"
v-if="!disableVisibilitySelector" v-if="!disableVisibilitySelector"
:show-all="showAllScopes"
:user-default="userDefaultScope" :user-default="userDefaultScope"
:original-scope="copyMessageScope" :original-scope="copyMessageScope"
:initial-scope="newStatus.visibility" :initial-scope="newStatus.visibility"
@@ -205,50 +200,47 @@
/> />
<div <div
class="format-selector-container"> class="language-selector"
<div
class="format-selector"
>
<Select
id="post-language"
v-model="newStatus.language"
class="form-control"
>
<option
v-for="language in postLanguageOptions"
:key="language.key"
:value="language.value"
>
{{ language.label }}
</option>
</Select>
</div>
<div
v-if="postFormats.length > 1"
class="text-format format-selector"
> >
<Select <Select
id="post-content-type" id="post-language"
v-model="newStatus.contentType" v-model="newStatus.language"
class="form-control" class="form-control"
>
<option
v-for="postFormat in postFormats"
:key="postFormat"
:value="postFormat"
>
{{ $t(`post_status.content_type["${postFormat}"]`) }}
</option>
</Select>
</div>
<div
v-if="postFormats.length === 1 && postFormats[0] !== 'text/plain'"
class="text-format format-selector"
> >
<span class="only-format"> <option
{{ $t(`post_status.content_type["${postFormats[0]}"]`) }} v-for="language in isoLanguages"
</span> :key="language"
</div> :value="language"
>
{{ language }}
</option>
</Select>
</div>
<div
v-if="postFormats.length > 1"
class="text-format"
>
<Select
id="post-content-type"
v-model="newStatus.contentType"
class="form-control"
>
<option
v-for="postFormat in postFormats"
:key="postFormat"
:value="postFormat"
>
{{ $t(`post_status.content_type["${postFormat}"]`) }}
</option>
</Select>
</div>
<div
v-if="postFormats.length === 1 && postFormats[0] !== 'text/plain'"
class="text-format"
>
<span class="only-format">
{{ $t(`post_status.content_type["${postFormats[0]}"]`) }}
</span>
</div> </div>
</div> </div>
</div> </div>
@@ -276,7 +268,6 @@
<button <button
class="emoji-icon button-unstyled" class="emoji-icon button-unstyled"
:title="$t('emoji.add_emoji')" :title="$t('emoji.add_emoji')"
type="button"
@click="showEmojiPicker" @click="showEmojiPicker"
> >
<FAIcon icon="smile-beam" /> <FAIcon icon="smile-beam" />
@@ -286,7 +277,6 @@
class="poll-icon button-unstyled" class="poll-icon button-unstyled"
:class="{ selected: pollFormVisible }" :class="{ selected: pollFormVisible }"
:title="$t('polls.add_poll')" :title="$t('polls.add_poll')"
type="button"
@click="togglePollForm" @click="togglePollForm"
> >
<FAIcon icon="poll-h" /> <FAIcon icon="poll-h" />
@@ -296,7 +286,6 @@
class="spoiler-icon button-unstyled" class="spoiler-icon button-unstyled"
:class="{ selected: subjectVisible }" :class="{ selected: subjectVisible }"
:title="$t('post_status.toggle_content_warning')" :title="$t('post_status.toggle_content_warning')"
type="button"
@click="toggleSubjectVisible" @click="toggleSubjectVisible"
> >
<FAIcon icon="eye-slash" /> <FAIcon icon="eye-slash" />
@@ -471,10 +460,6 @@
align-items: baseline; align-items: baseline;
} }
.visibility-tray-edit {
justify-content: right;
}
.visibility-notice.edit-warning { .visibility-notice.edit-warning {
> :first-child { > :first-child {
margin-top: 0; margin-top: 0;
@@ -485,12 +470,6 @@
} }
} }
.format-selector-container {
.format-selector {
display: inline-block;
}
}
.media-upload-icon, .poll-icon, .emoji-icon, .spoiler-icon { .media-upload-icon, .poll-icon, .emoji-icon, .spoiler-icon {
font-size: 1.85em; font-size: 1.85em;
line-height: 1.1; line-height: 1.1;
@@ -591,11 +570,6 @@
line-height: 1.85; line-height: 1.85;
} }
.form-post-subject {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.form-post-body { .form-post-body {
// TODO: make a resizable textarea component? // TODO: make a resizable textarea component?
box-sizing: content-box; // needed for easier computation of dynamic size box-sizing: content-box; // needed for easier computation of dynamic size
@@ -608,11 +582,6 @@
min-height: calc(var(--post-line-height) * 1em); min-height: calc(var(--post-line-height) * 1em);
resize: none; resize: none;
&.-has-subject {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
&.scrollable-form { &.scrollable-form {
overflow-y: auto; overflow-y: auto;
} }
@@ -3,7 +3,7 @@
v-if="isLoggedIn && !resettingForm" v-if="isLoggedIn && !resettingForm"
:is-open="modalActivated" :is-open="modalActivated"
class="post-form-modal-view" class="post-form-modal-view"
@backdrop-clicked="closeModal" @backdropClicked="closeModal"
> >
<div class="post-form-modal-panel panel"> <div class="post-form-modal-panel panel">
<div class="panel-heading"> <div class="panel-heading">
+3 -3
View File
@@ -8,13 +8,13 @@
remove-padding remove-padding
@show="focusInput" @show="focusInput"
> >
<template #content="{close}"> <template v-slot:content="{close}">
<EmojiPicker <EmojiPicker
:enable-sticker-picker="false" :enable-sticker-picker="false"
@emoji="addReaction($event, close)" @emoji="addReaction($event, close)"
/> />
</template> </template>
<template #trigger> <template v-slot:trigger>
<button <button
class="button-unstyled popover-trigger" class="button-unstyled popover-trigger"
:title="$t('tool_tip.add_reaction')" :title="$t('tool_tip.add_reaction')"
@@ -28,7 +28,7 @@
</Popover> </Popover>
</template> </template>
<script src="./react_button.js"></script> <script src="./react_button.js" ></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import '../../_variables.scss';
@@ -2,7 +2,7 @@ export default {
props: [ 'user' ], props: [ 'user' ],
computed: { computed: {
subscribeUrl () { subscribeUrl () {
// eslint-disable-next-line no-undef
const serverUrl = new URL(this.user.statusnet_profile_url) const serverUrl = new URL(this.user.statusnet_profile_url)
return `${serverUrl.protocol}//${serverUrl.host}/main/ostatus` return `${serverUrl.protocol}//${serverUrl.host}/main/ostatus`
} }
@@ -1,6 +1,4 @@
import ConfirmModal from '../confirm_modal/confirm_modal.vue' import ConfirmModal from '../confirm_modal/confirm_modal.vue'
import ScopeSelector from '../scope_selector/scope_selector.vue'
import scopeUtils from 'src/lib/scope_utils.js'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { faRetweet } from '@fortawesome/free-solid-svg-icons' import { faRetweet } from '@fortawesome/free-solid-svg-icons'
@@ -9,14 +7,12 @@ library.add(faRetweet)
const RetweetButton = { const RetweetButton = {
props: ['status', 'loggedIn', 'visibility'], props: ['status', 'loggedIn', 'visibility'],
components: { components: {
ConfirmModal, ConfirmModal
ScopeSelector
}, },
data () { data () {
return { return {
animated: false, animated: false,
showingConfirmDialog: false, showingConfirmDialog: false
retweetVisibility: this.$store.state.users.currentUser.default_scope
} }
}, },
methods: { methods: {
@@ -29,7 +25,7 @@ const RetweetButton = {
}, },
doRetweet () { doRetweet () {
if (!this.status.repeated) { if (!this.status.repeated) {
this.$store.dispatch('retweet', { id: this.status.id, visibility: this.retweetVisibility }) this.$store.dispatch('retweet', { id: this.status.id })
} else { } else {
this.$store.dispatch('unretweet', { id: this.status.id }) this.$store.dispatch('unretweet', { id: this.status.id })
} }
@@ -44,9 +40,6 @@ const RetweetButton = {
}, },
hideConfirmDialog () { hideConfirmDialog () {
this.showingConfirmDialog = false this.showingConfirmDialog = false
},
changeVis (visibility) {
this.retweetVisibility = visibility
} }
}, },
computed: { computed: {
@@ -61,15 +54,6 @@ const RetweetButton = {
}, },
remoteInteractionLink () { remoteInteractionLink () {
return this.$store.getters.remoteInteractionLink({ statusId: this.status.id }) return this.$store.getters.remoteInteractionLink({ statusId: this.status.id })
},
userDefaultScope () {
return this.$store.state.users.currentUser.default_scope
},
statusScope () {
return this.status.visibility
},
initialScope () {
return scopeUtils.negotiate(this.userDefaultScope, this.status.visibility)
} }
} }
} }
@@ -49,18 +49,12 @@
@cancelled="hideConfirmDialog" @cancelled="hideConfirmDialog"
> >
{{ $t('status.repeat_confirm') }} {{ $t('status.repeat_confirm') }}
<scope-selector
:user-default="userDefaultScope"
:original-scope="statusScope"
:initial-scope="initialScope"
:on-scope-change="changeVis"
/>
</confirm-modal> </confirm-modal>
</teleport> </teleport>
</div> </div>
</template> </template>
<script src="./retweet_button.js"></script> <script src="./retweet_button.js" ></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import '../../_variables.scss';
@@ -121,19 +121,6 @@ export default {
} }
} }
const mfmStyleFromDataAttributes = (attributes) => {
// CSS selectors can check if a data-* attribute is true, but can't use other values, so we want to add them to the style attribute
// Here we turn e.g. `{'data-mfm-some': '1deg', 'data-mfm-thing': '5s'}` to "--mfm-some: 1deg;--mfm-thing: 5s;"
// Note that we only add the value to `style` when they contain only letters, numbers, dot, or minus signs
// At the moment of writing, this should be enough for legitimate purposes and reduces the chance of injection by using special characters
// There is a special case for the `color` value, who is provided without `#`, but requires this in the `style` attribute
return Object.keys(attributes).filter(
(key) => key.startsWith('data-mfm-') && attributes[key] !== true && /^[a-zA-Z0-9.\-]*$/.test(attributes[key])
).map(
(key) => '--mfm-' + key.substr(9) + (key === 'data-mfm-color' ? ': #' : ': ') + attributes[key] + ';'
).reduce((a,v) => a+v, '')
}
// Processor to use with html_tree_converter // Processor to use with html_tree_converter
const processItem = (item, index, array, what) => { const processItem = (item, index, array, what) => {
// Handle text nodes - just add emoji // Handle text nodes - just add emoji
@@ -204,15 +191,6 @@ export default {
if (this.handleLinks && attrs?.['class']?.includes?.('h-card')) { if (this.handleLinks && attrs?.['class']?.includes?.('h-card')) {
return ['', children.map(processItem), ''] return ['', children.map(processItem), '']
} }
let mfm_style = mfmStyleFromDataAttributes(attrs)
if (mfm_style !== '') {
return [
opener.slice(0,-1) + ' style="' + mfm_style + '">',
children.map(processItem),
closer
]
}
} }
if (children !== undefined) { if (children !== undefined) {
+20 -10
View File
@@ -6,8 +6,6 @@ import {
faGlobe faGlobe
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
import scopeUtils from 'src/lib/scope_utils.js'
library.add( library.add(
faEnvelope, faEnvelope,
faGlobe, faGlobe,
@@ -15,11 +13,18 @@ library.add(
faLockOpen faLockOpen
) )
const SCOPE_LEVELS = {
'direct': 0,
'private': 1,
'local': 2,
'unlisted': 2,
'public': 3
}
const ScopeSelector = { const ScopeSelector = {
props: [ props: [
'showAll', 'showAll',
'userDefault', 'userDefault',
// scope of parent object
'originalScope', 'originalScope',
'initialScope', 'initialScope',
'onScopeChange' 'onScopeChange'
@@ -34,16 +39,16 @@ const ScopeSelector = {
return !this.showPublic && !this.showUnlisted && !this.showPrivate && !this.showDirect return !this.showPublic && !this.showUnlisted && !this.showPrivate && !this.showDirect
}, },
showPublic () { showPublic () {
return this.shouldShow('public') return this.originalScope !== 'direct' && this.shouldShow('public')
}, },
showLocal () { showLocal () {
return this.shouldShow('local') return this.originalScope !== 'direct' && this.shouldShow('local')
}, },
showUnlisted () { showUnlisted () {
return this.shouldShow('unlisted') return this.originalScope !== 'direct' && this.shouldShow('unlisted')
}, },
showPrivate () { showPrivate () {
return this.shouldShow('private') return this.originalScope !== 'direct' && this.shouldShow('private')
}, },
showDirect () { showDirect () {
return this.shouldShow('direct') return this.shouldShow('direct')
@@ -60,10 +65,15 @@ const ScopeSelector = {
}, },
methods: { methods: {
shouldShow (scope) { shouldShow (scope) {
if (!this.originalScope) if (!this.originalScope) {
return true return true
else }
return scopeUtils.compare(scope, this.originalScope) <= 0
if (this.originalScope === 'local') {
return scope === 'direct' || scope === 'local'
}
return SCOPE_LEVELS[scope] <= SCOPE_LEVELS[this.originalScope]
}, },
changeVis (scope) { changeVis (scope) {
this.currentScope = scope this.currentScope = scope
@@ -24,7 +24,7 @@
:items="items" :items="items"
:get-key="getKey" :get-key="getKey"
> >
<template #item="{item}"> <template v-slot:item="{item}">
<div <div
class="selectable-list-item-inner" class="selectable-list-item-inner"
:class="{ 'selectable-list-item-selected-inner': isSelected(item) }" :class="{ 'selectable-list-item-selected-inner': isSelected(item) }"
@@ -41,7 +41,7 @@
/> />
</div> </div>
</template> </template>
<template #empty> <template v-slot:empty>
<slot name="empty" /> <slot name="empty" />
</template> </template>
</List> </List>
@@ -6,7 +6,7 @@
<Checkbox <Checkbox
:model-value="state" :model-value="state"
:disabled="disabled" :disabled="disabled"
@update:model-value="update" @update:modelValue="update"
> >
<span <span
v-if="!!$slots.default" v-if="!!$slots.default"
@@ -8,7 +8,7 @@
<Select <Select
:model-value="state" :model-value="state"
:disabled="disabled" :disabled="disabled"
@update:model-value="update" @update:modelValue="update"
> >
<option <option
v-for="option in options" v-for="option in options"
@@ -6,14 +6,14 @@
<Popover <Popover
trigger="hover" trigger="hover"
> >
<template #trigger> <template v-slot:trigger>
&nbsp; &nbsp;
<FAIcon <FAIcon
icon="wrench" icon="wrench"
:aria-label="$t('settings.setting_changed')" :aria-label="$t('settings.setting_changed')"
/> />
</template> </template>
<template #content> <template v-slot:content>
<div class="modified-tooltip"> <div class="modified-tooltip">
{{ $t('settings.setting_changed') }} {{ $t('settings.setting_changed') }}
</div> </div>
@@ -6,14 +6,14 @@
<Popover <Popover
trigger="hover" trigger="hover"
> >
<template #trigger> <template v-slot:trigger>
&nbsp; &nbsp;
<FAIcon <FAIcon
icon="server" icon="server"
:aria-label="$t('settings.setting_server_side')" :aria-label="$t('settings.setting_server_side')"
/> />
</template> </template>
<template #content> <template v-slot:content>
<div class="serverside-tooltip"> <div class="serverside-tooltip">
{{ $t('settings.setting_server_side') }} {{ $t('settings.setting_server_side') }}
</div> </div>
@@ -69,7 +69,7 @@ const SettingsModal = {
this.$store.dispatch('closeSettingsModal') this.$store.dispatch('closeSettingsModal')
}, },
logout () { logout () {
this.$router.replace(this.$store.state.instance.redirectRootNoLogin || '/main/all') this.$router.replace('/main/public')
this.$store.dispatch('closeSettingsModal') this.$store.dispatch('closeSettingsModal')
this.$store.dispatch('logout') this.$store.dispatch('logout')
}, },
@@ -108,7 +108,7 @@
<Checkbox <Checkbox
:model-value="!!expertLevel" :model-value="!!expertLevel"
class="expertMode" class="expertMode"
@update:model-value="expertLevel = Number($event)" @update:modelValue="expertLevel = Number($event)"
> >
{{ $t("settings.expert_mode") }} {{ $t("settings.expert_mode") }}
</Checkbox> </Checkbox>
@@ -72,7 +72,7 @@ const DataImportExportTab = {
// check is it's a local user // check is it's a local user
if (user && user.is_local) { if (user && user.is_local) {
// append the instance address // append the instance address
// eslint-disable-next-line no-undef
return user.screen_name + '@' + location.hostname return user.screen_name + '@' + location.hostname
} }
return user.screen_name return user.screen_name
@@ -4,7 +4,6 @@ import ScopeSelector from 'src/components/scope_selector/scope_selector.vue'
import IntegerSetting from '../helpers/integer_setting.vue' import IntegerSetting from '../helpers/integer_setting.vue'
import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue' import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
import { usePostLanguageOptions } from 'src/lib/post_language'
import SharedComputedObject from '../helpers/shared_computed_object.js' import SharedComputedObject from '../helpers/shared_computed_object.js'
import ServerSideIndicator from '../helpers/server_side_indicator.vue' import ServerSideIndicator from '../helpers/server_side_indicator.vue'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
@@ -18,11 +17,6 @@ library.add(
) )
const GeneralTab = { const GeneralTab = {
setup() {
const {postLanguageOptions} = usePostLanguageOptions()
return {postLanguageOptions}
},
data () { data () {
return { return {
subjectLineOptions: ['email', 'noop', 'masto'].map(mode => ({ subjectLineOptions: ['email', 'noop', 'masto'].map(mode => ({
@@ -124,12 +118,6 @@ const GeneralTab = {
this.$store.dispatch('setOption', { name: 'translationLanguage', value: val }) this.$store.dispatch('setOption', { name: 'translationLanguage', value: val })
} }
}, },
postLanguage: {
get: function () { return this.$store.getters.mergedConfig.postLanguage },
set: function (val) {
this.$store.dispatch('setOption', { name: 'postLanguage', value: val })
}
},
...SharedComputedObject() ...SharedComputedObject()
}, },
methods: { methods: {
@@ -44,6 +44,7 @@
<template <template
v-if="profilesExpanded" v-if="profilesExpanded"
> >
<div <div
v-for="profile in settingsProfiles" v-for="profile in settingsProfiles"
:key="profile.id" :key="profile.id"
@@ -72,24 +73,15 @@
</button> </button>
</template> </template>
</div> </div>
<button <button class="btn button-default" @click="refreshProfiles()">
class="btn button-default"
@click="refreshProfiles()"
>
{{ $t('settings.settings_profiles_refresh') }} {{ $t('settings.settings_profiles_refresh') }}
<FAIcon <FAIcon icon="sync" @click="refreshProfiles()" />
icon="sync"
@click="refreshProfiles()"
/>
</button> </button>
<h3>{{ $t('settings.settings_profile_creation') }}</h3> <h3>{{ $t('settings.settings_profile_creation') }}</h3>
<label for="settings-profile-new-name"> <label for="settings-profile-new-name">
{{ $t('settings.settings_profile_creation_new_name_label') }} {{ $t('settings.settings_profile_creation_new_name_label') }}
</label> </label>
<input <input v-model="newProfileName" id="settings-profile-new-name">
id="settings-profile-new-name"
v-model="newProfileName"
>
<button <button
class="btn button-default" class="btn button-default"
@click="createSettingsProfile" @click="createSettingsProfile"
@@ -159,16 +151,6 @@
{{ $t('settings.show_page_backgrounds') }} {{ $t('settings.show_page_backgrounds') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
<li>
<BooleanSetting path="centerAlignBio">
{{ $t('settings.center_align_bio') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="compactUserInfo">
{{ $t('settings.compact_user_info') }}
</BooleanSetting>
</li>
<li> <li>
<BooleanSetting path="stopGifs"> <BooleanSetting path="stopGifs">
{{ $t('settings.stop_gifs') }} {{ $t('settings.stop_gifs') }}
@@ -279,11 +261,6 @@
{{ $t('settings.right_sidebar') }} {{ $t('settings.right_sidebar') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
<li>
<BooleanSetting path="widenTimeline">
{{ $t('settings.widen_timeline') }}
</BooleanSetting>
</li>
<li> <li>
<ChoiceSetting <ChoiceSetting
v-if="user" v-if="user"
@@ -565,18 +542,12 @@
{{ $t('settings.default_vis') }} <ServerSideIndicator :server-side="true" /> {{ $t('settings.default_vis') }} <ServerSideIndicator :server-side="true" />
<ScopeSelector <ScopeSelector
class="scope-selector" class="scope-selector"
:show-all="true"
:user-default="serverSide_defaultScope" :user-default="serverSide_defaultScope"
:initial-scope="serverSide_defaultScope" :initial-scope="serverSide_defaultScope"
:on-scope-change="changeDefaultScope" :on-scope-change="changeDefaultScope"
/> />
</label> </label>
</li> </li>
<li>
<BooleanSetting path="minimalScopesMode">
{{ $t('settings.minimal_scopes_mode') }}
</BooleanSetting>
</li>
<li> <li>
<BooleanSetting path="sensitiveByDefault"> <BooleanSetting path="sensitiveByDefault">
{{ $t('settings.sensitive_by_default') }} {{ $t('settings.sensitive_by_default') }}
@@ -587,14 +558,6 @@
{{ $t('settings.sensitive_if_subject') }} {{ $t('settings.sensitive_if_subject') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
<li>
<BooleanSetting
path="scopeCopy"
expert="1"
>
{{ $t('settings.scope_copy') }}
</BooleanSetting>
</li>
<li> <li>
<BooleanSetting <BooleanSetting
path="alwaysShowSubjectInput" path="alwaysShowSubjectInput"
@@ -622,23 +585,6 @@
{{ $t('settings.post_status_content_type') }} {{ $t('settings.post_status_content_type') }}
</ChoiceSetting> </ChoiceSetting>
</li> </li>
<li>
<ChoiceSetting
id="postLanguage"
path="postLanguage"
:options="postLanguageOptions"
>
{{ $t('settings.post_language') }}
</ChoiceSetting>
</li>
<li>
<BooleanSetting
path="minimalScopesMode"
expert="1"
>
{{ $t('settings.minimal_scopes_mode') }}
</BooleanSetting>
</li>
<li> <li>
<BooleanSetting <BooleanSetting
path="alwaysShowNewPostButton" path="alwaysShowNewPostButton"
@@ -85,7 +85,7 @@ const MutesAndBlocks = {
// check is it's a local user // check is it's a local user
if (user && user.is_local) { if (user && user.is_local) {
// append the instance address // append the instance address
// eslint-disable-next-line no-undef
return user.screen_name + '@' + location.hostname return user.screen_name + '@' + location.hostname
} }
return user.screen_name return user.screen_name
@@ -10,7 +10,7 @@
:query="queryUserIds" :query="queryUserIds"
:placeholder="$t('settings.search_user_to_block')" :placeholder="$t('settings.search_user_to_block')"
> >
<template #default="row"> <template v-slot="row">
<BlockCard <BlockCard
:user-id="row.item" :user-id="row.item"
/> />
@@ -21,7 +21,7 @@
:refresh="true" :refresh="true"
:get-key="i => i" :get-key="i => i"
> >
<template #header="{selected}"> <template v-slot:header="{selected}">
<div class="bulk-actions"> <div class="bulk-actions">
<ProgressButton <ProgressButton
v-if="selected.length > 0" v-if="selected.length > 0"
@@ -29,7 +29,7 @@
:click="() => blockUsers(selected)" :click="() => blockUsers(selected)"
> >
{{ $t('user_card.block') }} {{ $t('user_card.block') }}
<template #progress> <template v-slot:progress>
{{ $t('user_card.block_progress') }} {{ $t('user_card.block_progress') }}
</template> </template>
</ProgressButton> </ProgressButton>
@@ -39,16 +39,16 @@
:click="() => unblockUsers(selected)" :click="() => unblockUsers(selected)"
> >
{{ $t('user_card.unblock') }} {{ $t('user_card.unblock') }}
<template #progress> <template v-slot:progress>
{{ $t('user_card.unblock_progress') }} {{ $t('user_card.unblock_progress') }}
</template> </template>
</ProgressButton> </ProgressButton>
</div> </div>
</template> </template>
<template #item="{item}"> <template v-slot:item="{item}">
<BlockCard :user-id="item" /> <BlockCard :user-id="item" />
</template> </template>
<template #empty> <template v-slot:empty>
{{ $t('settings.no_blocks') }} {{ $t('settings.no_blocks') }}
</template> </template>
</BlockList> </BlockList>
@@ -63,7 +63,7 @@
:query="queryUserIds" :query="queryUserIds"
:placeholder="$t('settings.search_user_to_mute')" :placeholder="$t('settings.search_user_to_mute')"
> >
<template #default="row"> <template v-slot="row">
<MuteCard <MuteCard
:user-id="row.item" :user-id="row.item"
/> />
@@ -74,7 +74,7 @@
:refresh="true" :refresh="true"
:get-key="i => i" :get-key="i => i"
> >
<template #header="{selected}"> <template v-slot:header="{selected}">
<div class="bulk-actions"> <div class="bulk-actions">
<ProgressButton <ProgressButton
v-if="selected.length > 0" v-if="selected.length > 0"
@@ -82,7 +82,7 @@
:click="() => muteUsers(selected)" :click="() => muteUsers(selected)"
> >
{{ $t('user_card.mute') }} {{ $t('user_card.mute') }}
<template #progress> <template v-slot:progress>
{{ $t('user_card.mute_progress') }} {{ $t('user_card.mute_progress') }}
</template> </template>
</ProgressButton> </ProgressButton>
@@ -92,16 +92,16 @@
:click="() => unmuteUsers(selected)" :click="() => unmuteUsers(selected)"
> >
{{ $t('user_card.unmute') }} {{ $t('user_card.unmute') }}
<template #progress> <template v-slot:progress>
{{ $t('user_card.unmute_progress') }} {{ $t('user_card.unmute_progress') }}
</template> </template>
</ProgressButton> </ProgressButton>
</div> </div>
</template> </template>
<template #item="{item}"> <template v-slot:item="{item}">
<MuteCard :user-id="item" /> <MuteCard :user-id="item" />
</template> </template>
<template #empty> <template v-slot:empty>
{{ $t('settings.no_mutes') }} {{ $t('settings.no_mutes') }}
</template> </template>
</MuteList> </MuteList>
@@ -114,7 +114,7 @@
:query="queryKnownDomains" :query="queryKnownDomains"
:placeholder="$t('settings.type_domains_to_mute')" :placeholder="$t('settings.type_domains_to_mute')"
> >
<template #default="row"> <template v-slot="row">
<DomainMuteCard <DomainMuteCard
:domain="row.item" :domain="row.item"
/> />
@@ -125,7 +125,7 @@
:refresh="true" :refresh="true"
:get-key="i => i" :get-key="i => i"
> >
<template #header="{selected}"> <template v-slot:header="{selected}">
<div class="bulk-actions"> <div class="bulk-actions">
<ProgressButton <ProgressButton
v-if="selected.length > 0" v-if="selected.length > 0"
@@ -133,16 +133,16 @@
:click="() => unmuteDomains(selected)" :click="() => unmuteDomains(selected)"
> >
{{ $t('domain_mute_card.unmute') }} {{ $t('domain_mute_card.unmute') }}
<template #progress> <template v-slot:progress>
{{ $t('domain_mute_card.unmute_progress') }} {{ $t('domain_mute_card.unmute_progress') }}
</template> </template>
</ProgressButton> </ProgressButton>
</div> </div>
</template> </template>
<template #item="{item}"> <template v-slot:item="{item}">
<DomainMuteCard :domain="item" /> <DomainMuteCard :domain="item" />
</template> </template>
<template #empty> <template v-slot:empty>
{{ $t('settings.no_mutes') }} {{ $t('settings.no_mutes') }}
</template> </template>
</DomainMuteList> </DomainMuteList>
@@ -130,7 +130,7 @@ const ProfileTab = {
note: this.newBio, note: this.newBio,
locked: this.newLocked, locked: this.newLocked,
// Backend notation. // Backend notation.
/* eslint-disable camelcase */
display_name: this.newName, display_name: this.newName,
fields_attributes: this.newFields.filter(el => el != null), fields_attributes: this.newFields.filter(el => el != null),
bot: this.bot, bot: this.bot,
@@ -138,7 +138,7 @@ const ProfileTab = {
status_ttl_days: this.expirePosts ? this.newPostTTLDays : -1, status_ttl_days: this.expirePosts ? this.newPostTTLDays : -1,
permit_followback: this.permit_followback, permit_followback: this.permit_followback,
accepts_direct_messages_from: this.userAcceptsDirectMessagesFrom accepts_direct_messages_from: this.userAcceptsDirectMessagesFrom
/* eslint-enable camelcase */
} }
if (this.emailLanguage) { if (this.emailLanguage) {
@@ -187,7 +187,7 @@ const ProfileTab = {
}) })
return return
} }
// eslint-disable-next-line no-undef
const reader = new FileReader() const reader = new FileReader()
reader.onload = ({ target }) => { reader.onload = ({ target }) => {
const img = target.result const img = target.result
@@ -110,9 +110,11 @@
max="730" max="730"
class="expire-posts-days" class="expire-posts-days"
:placeholder="$t('settings.expire_posts_input_placeholder')" :placeholder="$t('settings.expire_posts_input_placeholder')"
> />
</p>
<p>
</p> </p>
<p />
<p> <p>
<interface-language-switcher <interface-language-switcher
:prompt-text="$t('settings.email_language')" :prompt-text="$t('settings.email_language')"
@@ -1,25 +1,22 @@
import { extractCommit } from 'src/services/version/version.service' import { extractCommit } from 'src/services/version/version.service'
function joinURL(base, subpath) { const pleromaFeCommitUrl = 'https://akkoma.dev/AkkomaGang/pleroma-fe/commit/'
return URL.parse(subpath, base)?.href || "invalid base URL" const pleromaBeCommitUrl = 'https://akkoma.dev/AkkomaGang/akkoma/commit/'
}
const VersionTab = { const VersionTab = {
data () { data () {
const instance = this.$store.state.instance const instance = this.$store.state.instance
return { return {
backendCommitUrl: instance.backendCommitUrl,
backendVersion: instance.backendVersion, backendVersion: instance.backendVersion,
frontendCommitUrl: instance.frontendCommitUrl,
frontendVersion: instance.frontendVersion frontendVersion: instance.frontendVersion
} }
}, },
computed: { computed: {
frontendVersionLink () { frontendVersionLink () {
return joinURL(this.frontendCommitUrl, this.frontendVersion) return pleromaFeCommitUrl + this.frontendVersion
}, },
backendVersionLink () { backendVersionLink () {
return joinURL(this.backendCommitUrl, extractCommit(this.backendVersion)) return pleromaBeCommitUrl + extractCommit(this.backendVersion)
} }
} }
} }
@@ -215,7 +215,7 @@
</div> </div>
</template> </template>
<script src="./shadow_control.js"></script> <script src="./shadow_control.js" ></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import '../../_variables.scss';
+1 -1
View File
@@ -218,7 +218,7 @@
</div> </div>
</template> </template>
<script src="./side_drawer.js"></script> <script src="./side_drawer.js" ></script>
<style lang="scss"> <style lang="scss">
@import '../../_variables.scss'; @import '../../_variables.scss';
+1 -1
View File
@@ -24,7 +24,7 @@
</div> </div>
</template> </template>
<script src="./staff_panel.js"></script> <script src="./staff_panel.js" ></script>
<style lang="scss"> <style lang="scss">
-10
View File
@@ -266,16 +266,6 @@
color: $fallback--cGreen; color: $fallback--cGreen;
color: var(--cGreen, $fallback--cGreen); color: var(--cGreen, $fallback--cGreen);
} }
.right-side {
display: flex;
align-items: center;
gap: 0.3em;
}
.repeat-tooltip {
flex-shrink: 0;
}
} }
.repeater-avatar { .repeater-avatar {

Some files were not shown because too many files have changed in this diff Show More