mirror of
https://akkoma.dev/lamp/akkoma-fe.git
synced 2025-11-04 04:32:10 -05:00
Compare commits
No commits in common. "589d8ea29fa86c875a1550244dc8a347c28abde7" and "4d91a7b2c36b3aff82d8988196ec1703709b93f8" have entirely different histories.
589d8ea29f
...
4d91a7b2c3
2
.eslintignore
Normal file
2
.eslintignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
build/*.js
|
||||||
|
config/*.js
|
||||||
30
.eslintrc.js
Normal file
30
.eslintrc.js
Normal 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
.node-version
Normal file
1
.node-version
Normal file
@ -0,0 +1 @@
|
|||||||
|
7.2.1
|
||||||
@ -1 +0,0 @@
|
|||||||
nodejs 20.12.2
|
|
||||||
@ -1,21 +1,20 @@
|
|||||||
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
|
||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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')
|
||||||
);
|
})
|
||||||
});
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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'
|
|
||||||
})
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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"'
|
||||||
})
|
})
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@ -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-->
|
||||||
|
|||||||
164
package.json
164
package.json
@ -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",
|
||||||
|
|||||||
@ -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 },
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -183,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'])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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';
|
||||||
|
|||||||
@ -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>
|
||||||
|
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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]
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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,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 () {
|
||||||
|
|||||||
@ -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">
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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';
|
||||||
|
|||||||
@ -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"
|
||||||
|
|||||||
@ -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';
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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"
|
||||||
|
|||||||
@ -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';
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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()
|
||||||
})
|
})
|
||||||
|
|||||||
@ -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';
|
||||||
|
|||||||
@ -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" />
|
||||||
|
|||||||
@ -69,4 +69,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script src="./recovery_form.js"></script>
|
<script src="./recovery_form.js" ></script>
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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)"
|
||||||
|
|||||||
@ -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';
|
||||||
|
|||||||
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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"
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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 })
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,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()
|
||||||
}
|
}
|
||||||
@ -343,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()
|
||||||
@ -518,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 })
|
||||||
@ -767,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,10 +190,8 @@
|
|||||||
<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"
|
||||||
:user-default="userDefaultScope"
|
:user-default="userDefaultScope"
|
||||||
:original-scope="copyMessageScope"
|
:original-scope="copyMessageScope"
|
||||||
@ -204,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>
|
||||||
@ -275,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" />
|
||||||
@ -285,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" />
|
||||||
@ -295,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" />
|
||||||
@ -470,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;
|
||||||
@ -484,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;
|
||||||
@ -590,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
|
||||||
@ -607,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">
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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>
|
||||||
|
|
||||||
<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>
|
||||||
|
|
||||||
<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"
|
||||||
@ -608,15 +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>
|
<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';
|
||||||
|
|||||||
@ -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';
|
||||||
|
|||||||
@ -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">
|
||||||
|
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -83,7 +83,7 @@
|
|||||||
:user="statusoid.user"
|
:user="statusoid.user"
|
||||||
/>
|
/>
|
||||||
<div class="right-side faint">
|
<div class="right-side faint">
|
||||||
<div
|
<span
|
||||||
class="status-username repeater-name"
|
class="status-username repeater-name"
|
||||||
:title="retweeter"
|
:title="retweeter"
|
||||||
>
|
>
|
||||||
@ -100,19 +100,14 @@
|
|||||||
v-else
|
v-else
|
||||||
:to="retweeterProfileLink"
|
:to="retweeterProfileLink"
|
||||||
>{{ retweeter }}</router-link>
|
>{{ retweeter }}</router-link>
|
||||||
</div>
|
</span>
|
||||||
{{ ' ' }}
|
{{ ' ' }}
|
||||||
|
<FAIcon
|
||||||
<div
|
icon="retweet"
|
||||||
class="repeat-tooltip"
|
class="repeat-icon"
|
||||||
>
|
:title="$t('tool_tip.repeat')"
|
||||||
<FAIcon
|
/>
|
||||||
icon="retweet"
|
{{ $t('timeline.repeated') }}
|
||||||
class="repeat-icon"
|
|
||||||
:title="$t('tool_tip.repeat')"
|
|
||||||
/>
|
|
||||||
{{ $t('timeline.repeated') }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -373,7 +368,7 @@
|
|||||||
:controlled-toggle-showing-long-subject="controlledToggleShowingLongSubject"
|
:controlled-toggle-showing-long-subject="controlledToggleShowingLongSubject"
|
||||||
@mediaplay="addMediaPlaying($event)"
|
@mediaplay="addMediaPlaying($event)"
|
||||||
@mediapause="removeMediaPlaying($event)"
|
@mediapause="removeMediaPlaying($event)"
|
||||||
@parse-ready="setHeadTailLinks"
|
@parseReady="setHeadTailLinks"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -481,8 +476,8 @@
|
|||||||
/>
|
/>
|
||||||
<extra-buttons
|
<extra-buttons
|
||||||
:status="status"
|
:status="status"
|
||||||
@on-error="showError"
|
@onError="showError"
|
||||||
@on-success="clearError"
|
@onSuccess="clearError"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -519,7 +514,6 @@
|
|||||||
:reply-to="status.id"
|
:reply-to="status.id"
|
||||||
:attentions="status.attentions"
|
:attentions="status.attentions"
|
||||||
:replied-user="status.user"
|
:replied-user="status.user"
|
||||||
:copy-message-language="status.language"
|
|
||||||
:copy-message-scope="status.visibility"
|
:copy-message-scope="status.visibility"
|
||||||
:subject="replySubject"
|
:subject="replySubject"
|
||||||
@posted="toggleReplying"
|
@posted="toggleReplying"
|
||||||
@ -534,7 +528,6 @@
|
|||||||
:quote-id="status.id"
|
:quote-id="status.id"
|
||||||
:attentions="[status.user]"
|
:attentions="[status.user]"
|
||||||
:replied-user="status.user"
|
:replied-user="status.user"
|
||||||
:copy-message-language="status.language"
|
|
||||||
:copy-message-scope="status.visibility"
|
:copy-message-scope="status.visibility"
|
||||||
:subject="replySubject"
|
:subject="replySubject"
|
||||||
@posted="toggleQuoting"
|
@posted="toggleQuoting"
|
||||||
|
|||||||
@ -41,8 +41,7 @@ const StatusContent = {
|
|||||||
postLength: this.status.text.length,
|
postLength: this.status.text.length,
|
||||||
parseReadyDone: false,
|
parseReadyDone: false,
|
||||||
renderMisskeyMarkdown,
|
renderMisskeyMarkdown,
|
||||||
translateFrom: null,
|
translateFrom: null
|
||||||
translating: false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -136,10 +135,7 @@ const StatusContent = {
|
|||||||
},
|
},
|
||||||
translateStatus () {
|
translateStatus () {
|
||||||
const translateTo = this.$store.getters.mergedConfig.translationLanguage || this.$store.state.instance.interfaceLanguage
|
const translateTo = this.$store.getters.mergedConfig.translationLanguage || this.$store.state.instance.interfaceLanguage
|
||||||
this.translating = true
|
this.$store.dispatch('translateStatus', { id: this.status.id, language: translateTo, from: this.translateFrom })
|
||||||
this.$store.dispatch(
|
|
||||||
'translateStatus', { id: this.status.id, language: translateTo, from: this.translateFrom }
|
|
||||||
).finally(() => { this.translating = false })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user