diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..34af3774f --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +build/*.js +config/*.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..361cff5f2 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,27 @@ +module.exports = { + root: true, + parserOptions: { + parser: '@babel/eslint-parser', + sourceType: 'module' + }, + // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style + extends: [ + 'standard', + 'plugin:vue/recommended' + ], + // required to lint *.vue files + plugins: [ + 'vue' + ], + // 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/multi-word-component-names': 0 + } +} diff --git a/.gitattributes b/.gitattributes index 1bea4dc8f..c5b9ea10e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -/build/commit_hash.js export-subst +/build/webpack.prod.conf.js export-subst diff --git a/.gitignore b/.gitignore index 01ffda9a8..0d5befd28 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,5 @@ test/e2e/reports selenium-debug.log .idea/ config/local.json -src/assets/emoji.json +static/emoji.json logs/ -__screenshots__/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 99c85dd36..f4c5cf43a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,7 +1,7 @@ # This file is a template, and might need editing before it works on your project. # Official framework image. Look for the different tagged releases at: # https://hub.docker.com/r/library/node/tags/ -image: node:18 +image: node:16 stages: - check-changelog @@ -38,8 +38,8 @@ lint: stage: lint script: - yarn - - yarn lint - - yarn stylelint + - npm run lint + - npm run stylelint test: stage: test @@ -50,15 +50,10 @@ test: APT_CACHE_DIR: apt-cache script: - mkdir -pv $APT_CACHE_DIR && apt-get -qq update + - apt install firefox-esr -y --no-install-recommends + - firefox --version - yarn - - yarn playwright install firefox - - yarn playwright install-deps - - yarn unit-ci - artifacts: - # When the test fails, upload screenshots for better context on why it fails - paths: - - test/**/__screenshots__ - when: on_failure + - yarn unit build: stage: build @@ -67,7 +62,7 @@ build: - himem script: - yarn - - yarn build + - npm run build artifacts: paths: - dist/ diff --git a/.gitlab/merge_request_templates/Release.md b/.gitlab/merge_request_templates/Release.md deleted file mode 100644 index d02e14a73..000000000 --- a/.gitlab/merge_request_templates/Release.md +++ /dev/null @@ -1,8 +0,0 @@ -### Release checklist -* [ ] Bump version in `package.json` -* [ ] Compile a changelog with the `tools/collect-changelog` script -* [ ] Create an MR with an announcement to pleroma.social -#### post-merge -* [ ] Tag the release on the merge commit -* [ ] Make the tag into a Gitlab Release™ -* [ ] Merge `master` into `develop` (in case the fixes are already in develop, use `git merge -s ours --no-commit` and manually merge the changelogs) diff --git a/.node-version b/.node-version index 08b7109d0..5397c87fa 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -18.20.8 +16.18.1 diff --git a/.stylelintrc.json b/.stylelintrc.json index afdfd5f5b..d6689cc01 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -1,5 +1,6 @@ { "extends": [ + "stylelint-rscss/config", "stylelint-config-standard", "stylelint-config-recommended-scss", "stylelint-config-html", @@ -7,13 +8,20 @@ ], "rules": { "declaration-no-important": true, + "rscss/no-descendant-combinator": false, + "rscss/class-format": [ + false, + { + "component": "pascal-case", + "variant": "^-[a-z]\\w+", + "element": "^[a-z]\\w+" + } + ], "selector-class-pattern": null, "import-notation": null, "custom-property-pattern": null, "keyframes-name-pattern": null, "scss/operator-no-newline-after": null, - "declaration-property-value-no-unknown": true, - "scss/declaration-property-value-no-unknown": true, "declaration-block-no-redundant-longhand-properties": [ true, { diff --git a/CHANGELOG.md b/CHANGELOG.md index 20c9c2693..9844319e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,114 +3,6 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). -## 2.9.3 -### Fixed -- Being unable to update profile - -## 2.9.2 -### Changed -- BREAKING: due to some internal technical changes logging into AdminFE through PleromaFE is no longer possible -- User card/profile got an overhaul -- Profile editing overhaul -- Visually combined subject and content fields in post form -- Moved post form's emoji button into input field -- Minor visual changes and fixes -- Clicking on fav/rt/emoji notifications' contents expands/collapses it -- Reduced time taken processing theme by half -- Splash screen only appears if loading takes more than 2 seconds - -### Added -- Mutes received an update, adding support for regex, muting based on username and expiration time. -- Mutes are now synchronized across sessions -- Support for expiring mutes and blocks (if available) -- Clicking on emoji shows bigger version of it alongside with its shortcode - - Admins also are able to copy it into a local pack -- Added support for Akkoma and IceShrimp.NET backends -- Compatibility with stricter CSP (Akkoma backend) -- Added a way to upload new packs from a URL or ZIP file via the Admin Dashboard -- Unify show/hide content buttons -- Add support for detachable scrollTop button -- Option to left-align user bio -- Cache assets and emojis with service worker -- Indicate currently active V3 theme as a body element class -- Add arithmetic blend ISS function - -### Fixed -- Display counter for status action buttons when they are in the menu -- Fix bookmark button alignment in the extra actions menu -- Instance favicons are no longer stretched -- A lot more scalable UI fixes - - Emoji picker now should work fine when emoji size is increased - -## 2.8.0 -### Changed -- BREAKING: static/img/nsfw.2958239.png is now static/img/nsfw.DepQPhG0.png, which may affect people who specify exactly this path as the cover image -- BREAKING: static/emoji.json is replaced with a properly hashed path under static/js in the production build, meaning server admins cannot provide their own set of unicode emojis by overriding this file (custom (image-based) emojis not affected) -- Speed up initial boot. -- Updated our build system to support browsers: - Safari >= 15 - Firefox >= 115 - Android > 4 - no Opera Mini support - no IE support - no "dead" (unmaintained) browsers support - -This does not guarantee that browsers will or will not work. - -- Use /api/v1/accounts/:id/follow for account subscriptions instead of the deprecated routes -- Modal layout for mobile has new layout to make it easy to use -- Better display of mute reason on posts -- Simplify the OAuth client_name to 'PleromaFE' -- Partially migrated from vuex to pinia -- Authenticate and subscribe to streaming after connection -- Tabs now have indentation for better visibility of which tab is currently active -- Upgraded Vue to version 3.5 - -### Added -- Support bookmark folders -- Some new default color schemes -- Added support for fetching /{resource}.custom.ext to allow adding instance-specific themes without altering sourcetree -- Post actions customization -- Support displaying time in absolute format -- Add draft management system -- Compress most kinds of images on upload. -- Added option to always convert images to JPEG format instead of using WebP when compressing images. -- Added configurable image compression option in general settings, allowing users to control whether images are compressed before upload. -- Inform users that Smithereen public polls are public -- Splash screen + loading indicator to make process of identifying initialization issues and load performance -- UI for making v3 themes and palettes, support for bundling v3 themes -- Make UserLink wrappable - -### Fixed -- Fixed occasional overflows in emoji picker and made header scrollable -- Updated shadow editor, hopefully fixed long-standing bugs, added ability to specify shadow's name. -- Checkbox vertical alignment -- Check for canvas extract permission when initializing favicon service -- Fix some of the color manipulation functions -- Fix draft saving when auto-save is off -- Switch from class hack to normalButton attribute for emoji count popover -- Fix emoji inconsistencies in notifications, -- Fix some emoji not scaling with interface -- Make sure hover style is also applied to :focus-visible -- Improved ToS and registration -- Fix small markup inconsistencies -- Fixed modals buttons overflow -- Fix whitespaces for multiple status mute reasons, display bot status reason -- Create an OAuth app only when needed -- Fix CSS compatibility issues in style_setter.js for older browsers like Palemoon -- Proper sticky header for conversations on user page -- Add text label for more actions button in post status form -- Reply-or-quote buttons now take less space -- Allow repeats of own posts with private scopes -- Bookmarks visible again on mobile -- Remove focusability on hidden popover in subject input -- Show only month and day instead of weird "day, hour" format. - -### Removed -- BREAKING: drop support for browsers that do not support ` +
diff --git a/package.json b/package.json index 21d75f0fb..403a2b231 100644 --- a/package.json +++ b/package.json @@ -1,122 +1,137 @@ { "name": "pleroma_fe", - "version": "2.9.3", + "version": "2.7.1", "description": "Pleroma frontend, the default frontend of Pleroma social network server", "author": "Pleroma contributors ", "private": false, "scripts": { - "dev": "node build/update-emoji.js && vite dev", - "build": "node build/update-emoji.js && vite build", - "unit": "node build/update-emoji.js && vitest --run", - "unit-ci": "node build/update-emoji.js && vitest --run --browser.headless", - "unit:watch": "node build/update-emoji.js && vitest", + "dev": "node build/dev-server.js", + "build": "node build/build.js", + "unit": "karma start test/unit/karma.conf.js --single-run", + "unit:watch": "karma start test/unit/karma.conf.js --single-run=false", "e2e": "node test/e2e/runner.js", - "test": "yarn run unit && yarn run e2e", - "stylelint": "yarn exec stylelint '**/*.scss' '**/*.vue'", - "lint": "eslint src test/unit/specs test/e2e/specs", - "lint-fix": "eslint --fix src test/unit/specs test/e2e/specs" + "test": "npm run unit && npm run e2e", + "stylelint": "npx stylelint '**/*.scss' '**/*.vue'", + "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs", + "lint-fix": "eslint --fix --ext .js,.vue src test/unit/specs test/e2e/specs" }, "dependencies": { - "@babel/runtime": "7.28.4", + "@babel/runtime": "7.21.5", "@chenfengyuan/vue-qrcode": "2.0.0", - "@fortawesome/fontawesome-svg-core": "7.1.0", - "@fortawesome/free-regular-svg-icons": "7.1.0", - "@fortawesome/free-solid-svg-icons": "7.1.0", - "@fortawesome/vue-fontawesome": "3.1.2", - "@kazvmoe-infra/pinch-zoom-element": "1.3.0", + "@fortawesome/fontawesome-svg-core": "6.4.0", + "@fortawesome/free-regular-svg-icons": "6.4.0", + "@fortawesome/free-solid-svg-icons": "6.4.0", + "@fortawesome/vue-fontawesome": "3.0.3", + "@kazvmoe-infra/pinch-zoom-element": "1.2.0", "@kazvmoe-infra/unicode-emoji-json": "0.4.0", - "@ruffle-rs/ruffle": "0.1.0-nightly.2025.6.22", + "@ruffle-rs/ruffle": "0.1.0-nightly.2024.8.21", "@vuelidate/core": "2.0.3", "@vuelidate/validators": "2.0.4", - "@web3-storage/parse-link-header": "^3.1.0", "body-scroll-lock": "3.1.5", "chromatism": "3.0.0", "click-outside-vue3": "4.0.1", - "cropperjs": "2.0.1", + "cropperjs": "1.5.13", "escape-html": "1.0.3", - "globals": "^16.0.0", "hash-sum": "^2.0.0", "js-cookie": "3.0.5", "localforage": "1.10.0", "parse-link-header": "2.0.0", - "phoenix": "1.8.1", - "pinia": "^3.0.0", - "punycode.js": "2.3.1", - "qrcode": "1.5.4", + "phoenix": "1.7.7", + "punycode.js": "2.3.0", + "qrcode": "1.5.3", "querystring-es3": "0.2.1", - "url": "0.11.4", + "url": "0.11.0", "utf8": "3.0.0", - "uuid": "11.1.0", - "vue": "3.5.22", - "vue-i18n": "11", - "vue-router": "4.5.1", + "vue": "3.2.45", + "vue-i18n": "9.2.2", + "vue-router": "4.1.6", + "vue-template-compiler": "2.7.14", "vue-virtual-scroller": "^2.0.0-beta.7", "vuex": "4.1.0" }, "devDependencies": { - "@babel/core": "7.28.4", - "@babel/eslint-parser": "7.28.4", - "@babel/plugin-transform-runtime": "7.28.3", - "@babel/preset-env": "7.28.3", - "@babel/register": "7.28.3", + "@babel/core": "7.21.8", + "@babel/eslint-parser": "7.21.8", + "@babel/plugin-transform-runtime": "7.21.4", + "@babel/preset-env": "7.21.5", + "@babel/register": "7.21.0", + "@intlify/vue-i18n-loader": "5.0.1", "@ungap/event-target": "0.2.4", - "@vitejs/plugin-vue": "^5.2.1", - "@vitejs/plugin-vue-jsx": "^4.1.1", - "@vitest/browser": "^3.0.7", - "@vitest/ui": "^3.0.7", "@vue/babel-helper-vue-jsx-merge-props": "1.4.0", - "@vue/babel-plugin-jsx": "1.5.0", - "@vue/compiler-sfc": "3.5.22", - "@vue/test-utils": "2.4.6", - "autoprefixer": "10.4.21", + "@vue/babel-plugin-jsx": "1.2.2", + "@vue/compiler-sfc": "3.2.45", + "@vue/test-utils": "2.2.8", + "autoprefixer": "10.4.19", + "babel-loader": "9.1.3", "babel-plugin-lodash": "3.3.4", - "chai": "5.3.3", - "chalk": "5.6.2", - "chromedriver": "135.0.4", + "chai": "4.3.7", + "chalk": "1.1.3", + "chromedriver": "108.0.0", "connect-history-api-fallback": "2.0.0", - "cross-spawn": "7.0.6", + "copy-webpack-plugin": "11.0.0", + "cross-spawn": "7.0.3", + "css-loader": "6.10.0", + "css-minimizer-webpack-plugin": "4.2.2", "custom-event-polyfill": "1.0.7", - "eslint": "9.37.0", - "vue-eslint-parser": "10.2.0", - "eslint-config-standard": "17.1.0", + "eslint": "8.33.0", + "eslint-config-standard": "17.0.0", "eslint-formatter-friendly": "7.0.0", - "eslint-plugin-import": "2.32.0", - "eslint-plugin-n": "17.23.1", - "eslint-plugin-promise": "7.2.1", - "eslint-plugin-vue": "10.5.0", + "eslint-plugin-import": "2.27.5", + "eslint-plugin-n": "15.6.1", + "eslint-plugin-promise": "6.1.1", + "eslint-plugin-vue": "9.9.0", + "eslint-webpack-plugin": "3.2.0", "eventsource-polyfill": "0.9.6", - "express": "5.1.0", - "function-bind": "1.1.2", - "http-proxy-middleware": "3.0.5", - "iso-639-1": "3.1.5", + "express": "4.18.2", + "function-bind": "1.1.1", + "html-webpack-plugin": "5.5.1", + "http-proxy-middleware": "2.0.6", + "iso-639-1": "2.1.15", + "json-loader": "0.5.7", + "karma": "6.4.4", + "karma-coverage": "2.2.0", + "karma-firefox-launcher": "2.1.3", + "karma-mocha": "2.0.1", + "karma-mocha-reporter": "2.2.5", + "karma-sinon-chai": "2.0.2", + "karma-sourcemap-loader": "0.3.8", + "karma-spec-reporter": "0.0.36", + "karma-webpack": "5.0.0", "lodash": "4.17.21", - "msw": "2.10.5", - "nightwatch": "3.12.2", - "playwright": "1.55.0", - "postcss": "8.5.6", + "mini-css-extract-plugin": "2.7.6", + "mocha": "10.2.0", + "nightwatch": "2.6.25", + "opn": "5.5.0", + "ora": "0.4.1", + "postcss": "8.4.23", "postcss-html": "^1.5.0", + "postcss-loader": "7.0.2", "postcss-scss": "^4.0.6", - "sass": "1.93.2", - "selenium-server": "3.141.59", - "semver": "7.7.3", - "serve-static": "2.2.0", - "shelljs": "0.10.0", - "sinon": "20.0.0", - "sinon-chai": "4.0.1", - "stylelint": "16.25.0", + "sass": "1.60.0", + "sass-loader": "13.2.2", + "selenium-server": "2.53.1", + "semver": "7.3.8", + "serviceworker-webpack5-plugin": "2.0.0", + "shelljs": "0.8.5", + "sinon": "15.0.4", + "sinon-chai": "3.7.0", + "stylelint": "14.16.1", "stylelint-config-html": "^1.1.0", - "stylelint-config-recommended": "^16.0.0", - "stylelint-config-recommended-scss": "^14.0.0", - "stylelint-config-recommended-vue": "^1.6.0", - "stylelint-config-standard": "38.0.0", - "vite": "^6.1.0", - "vite-plugin-eslint2": "^5.0.3", - "vite-plugin-stylelint": "^6.0.0", - "vitest": "^3.0.7" + "stylelint-config-recommended-scss": "^8.0.0", + "stylelint-config-recommended-vue": "^1.4.0", + "stylelint-config-standard": "29.0.0", + "stylelint-rscss": "0.4.0", + "stylelint-webpack-plugin": "^3.3.0", + "vue-loader": "17.0.1", + "vue-style-loader": "4.1.3", + "webpack": "5.75.0", + "webpack-dev-middleware": "3.7.3", + "webpack-hot-middleware": "2.25.3", + "webpack-merge": "0.20.0" }, - "type": "module", "engines": { - "node": ">= 16.0.0" + "node": ">= 16.0.0", + "npm": ">= 3.0.0" }, "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } diff --git a/postcss.config.js b/postcss.config.js index 95ebbf2a6..88752c6cb 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,7 +1,5 @@ -import autoprefixer from 'autoprefixer' - -export default { +module.exports = { plugins: [ - autoprefixer + require('autoprefixer') ] } diff --git a/public/static/.gitignore b/public/static/.gitignore deleted file mode 100644 index 3332292a1..000000000 --- a/public/static/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.custom.* diff --git a/public/static/palettes/index.json b/public/static/palettes/index.json deleted file mode 100644 index 2cd110d1e..000000000 --- a/public/static/palettes/index.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "pleroma-dark": [ "Pleroma Dark", "#121a24", "#182230", "#b9b9ba", "#d8a070", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ], - "pleroma-light": [ "Pleroma Light", "#f2f4f6", "#dbe0e8", "#304055", "#f86f0f", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ], - "classic-dark": { - "name": "Classic Dark", - "bg": "#161c20", - "fg": "#282e32", - "text": "#b9b9b9", - "link": "#baaa9c", - "cRed": "#d31014", - "cGreen": "#0fa00f", - "cBlue": "#0095ff", - "cOrange": "#ffa500" - }, - "bird": [ "Bird", "#f8fafd", "#e6ecf0", "#14171a", "#0084b8", "#e0245e", "#17bf63", "#1b95e0", "#fab81e"], - "pleroma-amoled": [ "Pleroma Dark AMOLED", "#000000", "#111111", "#b0b0b1", "#d8a070", "#aa0000", "#0fa00f", "#0095ff", "#d59500"], - "tomorrow-night": { - "name": "Tomorrow Night", - "bg": "#1d1f21", - "fg": "#373b41", - "link": "#81a2be", - "text": "#c5c8c6", - "cRed": "#cc6666", - "cBlue": "#8abeb7", - "cGreen": "#b5bd68", - "cOrange": "#de935f" - }, - "dracula": { - "name": "Dracula", - "bg": "#282A36", - "fg": "#44475A", - "link": "#BC92F9", - "text": "#f8f8f2", - "cRed": "#FF5555", - "cBlue": "#8BE9FD", - "cGreen": "#50FA7B", - "cOrange": "#FFB86C" - }, - "ir-black": [ "Ir Black", "#000000", "#242422", "#b5b3aa", "#ff6c60", "#FF6C60", "#A8FF60", "#96CBFE", "#FFFFB6" ], - "monokai": [ "Monokai", "#272822", "#383830", "#f8f8f2", "#f92672", "#F92672", "#a6e22e", "#66d9ef", "#f4bf75" ], - "purple-stream": { - "name": "Purple stream", - "bg": "#17171A", - "fg": "#450F92", - "link": "#8769B4", - "text": "#C0C0C5", - "cRed": "#EB0300", - "cBlue": "#4656FF", - "cGreen": "#B0E020", - "cOrange": "#FF9046" - }, - "feud": { - "name": "Feud", - "bg": "#323337", - "fg": "#1D1E21", - "link": "#18A0E3", - "accent": "#6671E2", - "text": "#DBDDE0", - "cRed": "#E05053", - "cBlue": "#6671E2", - "cGreen": "#3A8D5D", - "cOrange": "#DCAA45" - }, - "constabulary": { - "name": "Constabulary", - "bg": "#FFFFFF", - "fg": "#3B5897", - "link": "#28487C", - "text": "#333333", - "cRed": "#FA3C4C", - "cBlue": "#0083FF", - "cGreen": "#44BDC6", - "cOrange": "#FFC200" - } -} diff --git a/public/static/pleromatan_apology_fox_small.webp b/public/static/pleromatan_apology_fox_small.webp deleted file mode 100644 index eacbf3cbf..000000000 Binary files a/public/static/pleromatan_apology_fox_small.webp and /dev/null differ diff --git a/public/static/pleromatan_apology_small.webp b/public/static/pleromatan_apology_small.webp deleted file mode 100644 index e27e06d06..000000000 Binary files a/public/static/pleromatan_apology_small.webp and /dev/null differ diff --git a/public/static/splash.css b/public/static/splash.css deleted file mode 100644 index f56f33d07..000000000 --- a/public/static/splash.css +++ /dev/null @@ -1,132 +0,0 @@ -body { - margin: 0; - padding: 0; -} - -#splash { - --scale: 1; - - width: 100vw; - height: 100vh; - display: grid; - grid-template-rows: auto; - grid-template-columns: auto; - align-content: center; - place-items: center; - flex-direction: column; - background: #0f161e; - font-family: sans-serif; - color: #b9b9ba; - position: absolute; - z-index: 9999; - font-size: calc(1vw + 1vh + 1vmin); - opacity: 1; - transition: opacity 500ms ease-out 2s; -} - -#splash.hidden, -#splash.initial-hidden { - opacity: 0; -} - -#splash-credit { - position: absolute; - font-size: 1em; - bottom: 1em; - right: 1em; -} - -#splash-container { - align-items: center; -} - -#mascot-container { - display: flex; - align-items: flex-end; - justify-content: center; - perspective: 60em; - perspective-origin: 0 -15em; - transform-style: preserve-3d; -} - -#mascot { - width: calc(10em * var(--scale)); - height: calc(10em * var(--scale)); - object-fit: contain; - object-position: bottom; - transform: translateZ(-2em); -} - -#throbber { - display: grid; - width: calc(5em * 0.5 * var(--scale)); - height: calc(8em * 0.5 * var(--scale)); - margin-left: 4.1em; - z-index: 2; - grid-template-rows: repeat(8, 1fr); - grid-template-columns: repeat(5, 1fr); - grid-template-areas: "P P . L L" - "P P . L L" - "P P . L L" - "P P . L L" - "P P . . ." - "P P . . ." - "P P . E E" - "P P . E E"; - - --logoChunkSize: calc(2em * 0.5 * var(--scale)) -} - -.chunk { - background-color: #e2b188; - box-shadow: 0.01em 0.01em 0.1em 0 #e2b188; -} - -#chunk-P { - grid-area: P; - border-top-left-radius: calc(var(--logoChunkSize) / 2); -} - -#chunk-L { - grid-area: L; - border-bottom-right-radius: calc(var(--logoChunkSize) / 2); -} - -#chunk-E { - grid-area: E; - border-bottom-right-radius: calc(var(--logoChunkSize) / 2); -} - -#status { - margin-top: 1em; - line-height: 2; - width: 100%; - text-align: center; -} - -#statusError { - display: none; - margin-top: 1em; - font-size: calc(1vw + 1vh + 1vmin); - line-height: 2; - width: 100%; - text-align: center; -} - -#statusStack { - display: none; - margin-top: 1em; - font-size: calc((1vw + 1vh + 1vmin) / 2.5); - width: calc(100vw - 5em); - padding: 1em; - text-overflow: ellipsis; - overflow-x: hidden; - text-align: left; - line-height: 2; -} - -@media (prefers-reduced-motion) { - #throbber { - animation: none !important; - } -} diff --git a/public/static/styles.json b/public/static/styles.json deleted file mode 100644 index 2f836a47a..000000000 --- a/public/static/styles.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "pleroma-dark": "/static/themes/pleroma-dark.json", - "pleroma-light": "/static/themes/pleroma-light.json", - "redmond-xx": "/static/themes/redmond-xx.json", - "redmond-xx-se": "/static/themes/redmond-xx-se.json", - "redmond-xxi": "/static/themes/redmond-xxi.json", - "breezy-dark": "/static/themes/breezy-dark.json", - "breezy-light": "/static/themes/breezy-light.json", - "mammal": "/static/themes/mammal.json", - "paper": "/static/themes/paper.json" -} diff --git a/public/static/styles/Breezy DX.iss b/public/static/styles/Breezy DX.iss deleted file mode 100644 index 69cc3befe..000000000 --- a/public/static/styles/Breezy DX.iss +++ /dev/null @@ -1,102 +0,0 @@ -@meta { - name: Breezy DX; - author: HJ; - license: WTFPL; - website: ebin.club; -} - -@palette.Dark { - bg: #292C32; - fg: #292C32; - text: #ffffff; - link: #1CA4F3; - accent: #1CA4F3; - cRed: #f41a51; - cBlue: #1CA4F3; - cGreen: #1af46e; - cOrange: #f4af1a; -} - -@palette.Light { - bg: #EFF0F2; - fg: #EFF0F2; - text: #1B1F22; - underlay: #5d6086; - accent: #1CA4F3; - cBlue: #1CA4F3; - cRed: #f41a51; - cGreen: #0b6a30; - cOrange: #f4af1a; - border: #d8e6f9; - link: #1CA4F3; -} - -@palette.Panda { - bg: #EFF0F2; - fg: #292C32; - text: #1B1F22; - link: #1CA4F3; - accent: #1CA4F3; - cRed: #f41a51; - cBlue: #1CA4F3; - cGreen: #0b6a30; - cOrange: #f4af1a; -} - -Root { - --badgeNotification: color | --cRed; - --buttonDefaultHoverGlow: shadow | inset 0 0 0 1 --accent / 1; - --buttonDefaultFocusGlow: shadow | inset 0 0 0 1 --accent / 1; - --buttonDefaultShadow: shadow | inset 0 0 0 1 --text / 0.35, 0 5 5 -5 #000000 / 0.35; - --buttonDefaultBevel: shadow | inset 0 14 14 -14 #FFFFFF / 0.1; - --buttonPressedBevel: shadow | inset 0 -20 20 -20 #000000 / 0.05; - --defaultInputBevel: shadow | inset 0 0 0 1 --text / 0.35; - --defaultInputHoverGlow: shadow | 0 0 0 1 --accent / 1; - --defaultInputFocusGlow: shadow | 0 0 0 1 --link / 1; -} - -Button { - background: --parent; -} - -Button:disabled { - shadow: --buttonDefaultBevel, --buttonDefaultShadow -} - -Button:hover { - background: --inheritedBackground; - shadow: --buttonDefaultHoverGlow, --buttonDefaultBevel, --buttonDefaultShadow -} - -Button:toggled { - background: $blend(--inheritedBackground 0.3 --accent) -} - -Button:pressed { - background: $blend(--inheritedBackground 0.8 --accent) -} - -Button:pressed:toggled { - background: $blend(--inheritedBackground 0.2 --accent) -} - -Button:toggled:hover { - background: $blend(--inheritedBackground 0.3 --accent) -} - -Input { - shadow: --defaultInputBevel; - background: $mod(--bg -10); -} - -PanelHeader { - shadow: inset 0 30 30 -30 #ffffff / 0.25 -} - -Tab:hover { - shadow: --buttonDefaultHoverGlow, --buttonDefaultBevel, --buttonDefaultShadow -} - -Tab { - background: --bg; -} diff --git a/public/static/styles/Redmond DX.iss b/public/static/styles/Redmond DX.iss deleted file mode 100644 index 919be056b..000000000 --- a/public/static/styles/Redmond DX.iss +++ /dev/null @@ -1,201 +0,0 @@ -@meta { - name: Redmond DX; - author: HJ; - license: WTFPL; - website: ebin.club; -} - -@palette.Modern { - bg: #D3CFC7; - fg: #092369; - text: #000000; - link: #0000FF; - accent: #A5C9F0; - cRed: #FF3000; - cBlue: #009EFF; - cGreen: #309E00; - cOrange: #FFCE00; -} - -@palette.Classic { - bg: #BFBFBF; - fg: #000180; - text: #000000; - link: #0000FF; - accent: #A5C9F0; - cRed: #FF0000; - cBlue: #2E2ECE; - cGreen: #007E00; - cOrange: #CE8F5F; -} - -@palette.Vapor { - bg: #F0ADCD; - fg: #bca4ee; - text: #602040; - link: #064745; - accent: #9DF7C8; - cRed: #86004a; - cBlue: #0e5663; - cGreen: #0a8b51; - cOrange: #787424; -} - -Root { - --gradientColor: color | --accent; - --inputColor: color | #FFFFFF; - --bevelLight: color | $brightness(--bg 50); - --bevelDark: color | $brightness(--bg -20); - --bevelExtraDark: color | #404040; - --buttonDefaultBevel: shadow | $borderSide(--bevelExtraDark bottom-right 1 1), $borderSide(--bevelLight top-left 1 1), $borderSide(--bevelDark bottom-right 1 2); - --buttonPressedFocusedBevel: shadow | inset 0 0 0 1 #000000 / 1 #Outer , inset 0 0 0 2 --bevelExtraDark / 1 #inner; - --buttonPressedBevel: shadow | $borderSide(--bevelDark top-left 1 1), $borderSide(--bevelLight bottom-right 1 1), $borderSide(--bevelExtraDark top-left 1 2); - --defaultInputBevel: shadow | $borderSide(--bevelDark top-left 1 1), $borderSide(--bevelLight bottom-right 1 1), $borderSide(--bevelExtraDark top-left 1 2), $borderSide(--bg bottom-right 1 2); -} - -Button:toggled { - background: --bg; - shadow: --buttonPressedBevel -} - -Button:focused { - shadow: --buttonDefaultBevel, 0 0 0 1 #000000 / 1 -} - -Button:pressed { - shadow: --buttonPressedBevel -} - -Button:hover { - shadow: --buttonDefaultBevel; - background: --bg -} - -Button { - shadow: --buttonDefaultBevel; - background: --bg; - roundness: 0 -} - -Button:pressed:hover { - shadow: --buttonPressedBevel -} - -Button:hover:pressed:focused { - shadow: --buttonPressedFocusedBevel -} - -Button:pressed:focused { - shadow: --buttonPressedFocusedBevel -} - -Button:toggled:pressed { - shadow: --buttonPressedFocusedBevel -} - -Input { - background: $boost(--bg 20); - shadow: --defaultInputBevel; - roundness: 0 -} - -Input:focused { - shadow: inset 0 0 0 1 #000000 / 1, --defaultInputBevel -} - -Input:focused:hover { - shadow: --defaultInputBevel -} - -Input:focused:hover:disabled { - shadow: --defaultInputBevel -} - -Input:hover { - shadow: --defaultInputBevel -} - -Input:disabled { - shadow: --defaultInputBevel -} - -Panel { - shadow: --buttonDefaultBevel; - roundness: 0 -} - -PanelHeader { - shadow: inset -1100 0 1000 -1000 --gradientColor / 1 #Gradient ; - background: --fg -} - -PanelHeader ButtonUnstyled Icon { - textColor: --text; - textAuto: 'no-preserve' -} - -PanelHeader Button Icon { - textColor: --text; - textAuto: 'no-preserve' -} - -PanelHeader Button Text { - textColor: --text; - textAuto: 'no-preserve' -} - -Tab:hover { - background: --bg; - shadow: --buttonDefaultBevel -} - -Tab:active { - background: --bg -} - -Tab:active:hover { - background: --bg; - shadow: --defaultButtonBevel -} - -Tab:active:hover:disabled { - background: --bg -} - -Tab:hover:disabled { - background: --bg -} - -Tab:disabled { - background: --bg -} - -Tab { - background: --bg; - shadow: --buttonDefaultBevel -} - -Tab:hover:active { - shadow: --buttonDefaultBevel -} - -TopBar Link { - textColor: #ffffff -} - -MenuItem:hover { - background: --fg -} - -MenuItem:active { - background: --fg -} - -MenuItem:active:hover { - background: --fg -} - -Popover { - shadow: --buttonDefaultBevel, 5 5 0 0 #000000 / 0.2; - roundness: 0 -} diff --git a/public/static/styles/index.json b/public/static/styles/index.json deleted file mode 100644 index 6c1dd1676..000000000 --- a/public/static/styles/index.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "RedmondDX": "/static/styles/Redmond DX.iss", - "BreezyDX": "/static/styles/Breezy DX.iss" -} diff --git a/src/App.js b/src/App.js index 0027d908a..e87108dd9 100644 --- a/src/App.js +++ b/src/App.js @@ -14,14 +14,9 @@ import EditStatusModal from './components/edit_status_modal/edit_status_modal.vu import PostStatusModal from './components/post_status_modal/post_status_modal.vue' import StatusHistoryModal from './components/status_history_modal/status_history_modal.vue' import GlobalNoticeList from './components/global_notice_list/global_notice_list.vue' -import { getOrCreateServiceWorker } from './services/sw/sw' import { windowWidth, windowHeight } from './services/window_utils/window_utils' import { mapGetters } from 'vuex' import { defineAsyncComponent } from 'vue' -import { useShoutStore } from './stores/shout' -import { useInterfaceStore } from './stores/interface' - -import { throttle } from 'lodash' export default { name: 'app', @@ -50,57 +45,27 @@ export default { mobileActivePanel: 'timeline' }), watch: { - themeApplied () { + themeApplied (value) { this.removeSplash() - }, - currentTheme () { - this.setThemeBodyClass() - }, - layoutType () { - document.getElementById('modal').classList = ['-' + this.layoutType] } }, created () { // Load the locale from the storage const val = this.$store.getters.mergedConfig.interfaceLanguage this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val }) - document.getElementById('modal').classList = ['-' + this.layoutType] - - // Create bound handlers - this.updateScrollState = throttle(this.scrollHandler, 200) - this.updateMobileState = throttle(this.resizeHandler, 200) + window.addEventListener('resize', this.updateMobileState) }, mounted () { - window.addEventListener('resize', this.updateMobileState) - this.scrollParent.addEventListener('scroll', this.updateScrollState) - - if (useInterfaceStore().themeApplied) { - this.setThemeBodyClass() + if (this.$store.state.interface.themeApplied) { this.removeSplash() } - getOrCreateServiceWorker() }, unmounted () { window.removeEventListener('resize', this.updateMobileState) - this.scrollParent.removeEventListener('scroll', this.updateScrollState) }, computed: { themeApplied () { - return useInterfaceStore().themeApplied - }, - currentTheme () { - if (useInterfaceStore().styleDataUsed) { - const styleMeta = useInterfaceStore().styleDataUsed.find(x => x.component === '@meta') - - if (styleMeta !== undefined) { - return styleMeta.directives.name.replaceAll(" ", "-").toLowerCase() - } - } - - return 'stock' - }, - layoutModalClass () { - return '-' + this.layoutType + return this.$store.state.interface.themeApplied }, classes () { return [ @@ -134,7 +99,7 @@ export default { } } }, - shout () { return useShoutStore().joined }, + shout () { return this.$store.state.shout.joined }, suggestionsEnabled () { return this.$store.state.instance.suggestionsEnabled }, showInstanceSpecificPanel () { return this.$store.state.instance.showInstanceSpecificPanel && @@ -160,7 +125,7 @@ export default { hideShoutbox () { return this.$store.getters.mergedConfig.hideShoutbox }, - layoutType () { return useInterfaceStore().layoutType }, + layoutType () { return this.$store.state.interface.layoutType }, privateMode () { return this.$store.state.instance.private }, reverseLayout () { const { thirdColumnMode, sidebarRight: reverseSetting } = this.$store.getters.mergedConfig @@ -172,41 +137,12 @@ export default { }, noSticky () { return this.$store.getters.mergedConfig.disableStickyHeaders }, showScrollbars () { return this.$store.getters.mergedConfig.showScrollbars }, - scrollParent () { return window; /* this.$refs.appContentRef */ }, ...mapGetters(['mergedConfig']) }, methods: { - resizeHandler () { - useInterfaceStore().setLayoutWidth(windowWidth()) - useInterfaceStore().setLayoutHeight(windowHeight()) - }, - scrollHandler () { - const scrollPosition = this.scrollParent === window ? window.scrollY : this.scrollParent.scrollTop - - if (scrollPosition != 0) { - this.$refs.appContentRef.classList.add(['-scrolled']) - } else { - this.$refs.appContentRef.classList.remove(['-scrolled']) - } - }, - setThemeBodyClass () { - const themeName = this.currentTheme - const classList = Array.from(document.body.classList) - const oldTheme = classList.filter(c => c.startsWith('theme-')) - - if (themeName !== null && themeName !== '') { - const newTheme = `theme-${themeName.toLowerCase()}` - - // remove old theme reference if there are any - if (oldTheme.length) { - document.body.classList.replace(oldTheme[0], newTheme) - } else { - document.body.classList.add(newTheme) - } - } else { - // remove theme reference if non-V3 theme is used - document.body.classList.remove(...oldTheme) - } + updateMobileState () { + this.$store.dispatch('setLayoutWidth', windowWidth()) + this.$store.dispatch('setLayoutHeight', windowHeight()) }, removeSplash () { document.querySelector('#status').textContent = this.$t('splash.fun_' + Math.ceil(Math.random() * 4)) @@ -214,9 +150,6 @@ export default { splashscreenRoot.addEventListener('transitionend', () => { splashscreenRoot.remove() }) - setTimeout(() => { - splashscreenRoot.remove() // forcibly remove it, should fix my plasma browser widget t. HJ - }, 600) splashscreenRoot.classList.add('hidden') document.querySelector('#app').classList.remove('hidden') } diff --git a/src/App.scss b/src/App.scss index 1eee63a7e..f52ba06b9 100644 --- a/src/App.scss +++ b/src/App.scss @@ -1,9 +1,6 @@ // stylelint-disable rscss/class-format /* stylelint-disable no-descending-specificity */ -@use "panel"; - -@import '@fortawesome/fontawesome-svg-core/styles.css'; -@import '@kazvmoe-infra/pinch-zoom-element/dist/pinch-zoom.css'; +@import "./panel"; :root { --status-margin: 0.75em; @@ -21,7 +18,7 @@ } html { - font-size: var(--textSize, 1rem); + font-size: var(--textSize, 14px); --navbar-height: var(--navbarSize, 3.5rem); --emoji-size: var(--emojiSize, 32px); @@ -33,12 +30,12 @@ body { font-family: sans-serif; font-family: var(--font); margin: 0; - padding: 0; color: var(--text); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; overscroll-behavior-y: none; - overflow: clip scroll; + overflow-x: clip; + overflow-y: scroll; &.hidden { display: none; @@ -227,8 +224,9 @@ nav { grid-template-rows: 1fr; box-sizing: border-box; margin: 0 auto; - place-content: flex-start center; + align-content: flex-start; flex-wrap: wrap; + justify-content: center; min-height: 100vh; overflow-x: clip; @@ -264,7 +262,8 @@ nav { position: sticky; top: var(--navbar-height); max-height: calc(100vh - var(--navbar-height)); - overflow: hidden auto; + overflow-y: auto; + overflow-x: hidden; margin-left: calc(var(--___paddingIncrease) * -1); padding-left: calc(var(--___paddingIncrease) + var(--___columnMargin) / 2); @@ -382,10 +381,6 @@ nav { font-family: sans-serif; font-family: var(--font); - &.-transparent { - backdrop-filter: blur(0.125em) contrast(60%); - } - &::-moz-focus-inner { border: none; } @@ -393,35 +388,39 @@ nav { &:disabled { cursor: not-allowed; } - - &:active { - transform: translate(1px, 1px); - } } -.menu-item { - line-height: var(--__line-height); +.menu-item, +.list-item { + display: block; + box-sizing: border-box; + border: none; + outline: none; + text-align: initial; + font-size: inherit; font-family: inherit; font-weight: 400; - font-size: 100%; cursor: pointer; - - a, - button:not(.button-default) { - color: var(--text); - font-size: 100%; - } - - &.disabled { - cursor: not-allowed; - } -} - -.list-item { + color: inherit; + clear: both; + position: relative; + white-space: nowrap; border-color: var(--border); border-style: solid; border-width: 0; border-top-width: 1px; + width: 100%; + line-height: var(--__line-height); + padding: var(--__vertical-gap) var(--__horizontal-gap); + background: transparent; + + --__line-height: 1.5em; + --__horizontal-gap: 0.75em; + --__vertical-gap: 0.5em; + + &.-non-interactive { + cursor: auto; + } &.-active, &:hover { @@ -443,6 +442,20 @@ nav { border-bottom-width: 1px; } + a, + button:not(.button-default) { + text-align: initial; + padding: 0; + background: none; + border: none; + outline: none; + display: inline; + font-size: 100%; + font-family: inherit; + line-height: unset; + color: var(--text); + } + &:first-child { border-top-right-radius: var(--roundness); border-top-left-radius: var(--roundness); @@ -456,42 +469,6 @@ nav { } } -.menu-item, -.list-item { - display: block; - box-sizing: border-box; - border: none; - outline: none; - text-align: initial; - color: inherit; - clear: both; - position: relative; - white-space: nowrap; - width: 100%; - padding: var(--__vertical-gap) var(--__horizontal-gap); - background: transparent; - - --__line-height: 1.5em; - --__horizontal-gap: 0.75em; - --__vertical-gap: 0.5em; - - &.-non-interactive { - cursor: auto; - } - - a, - button:not(.button-default) { - text-align: initial; - padding: 0; - background: none; - border: none; - outline: none; - display: inline; - font-family: inherit; - line-height: unset; - } -} - .button-unstyled { border: none; outline: none; @@ -513,12 +490,6 @@ nav { } } -label { - &.-disabled { - color: var(--textFaint); - } -} - input, textarea { border: none; @@ -535,10 +506,6 @@ textarea { height: unset; } - &::placeholder { - color: var(--textFaint) - } - --_padding: 0.5em; border: none; @@ -559,10 +526,6 @@ textarea { &[disabled="disabled"], &.disabled { cursor: not-allowed; - color: var(--textFaint); - - /* stylelint-disable-next-line declaration-no-important */ - background-color: transparent !important; } &[type="range"] { @@ -588,8 +551,6 @@ textarea { & + label::before { opacity: 0.5; } - - background-color: var(--background); } + label::before { @@ -689,8 +650,7 @@ option { list-style: none; display: grid; grid-auto-flow: row dense; - grid-template-columns: repeat(auto-fit, minmax(20em, 1fr)); - grid-gap: 0.5em; + grid-template-columns: 1fr 1fr; li { border: 1px solid var(--border); @@ -700,6 +660,11 @@ option { } } +.btn-block { + display: block; + width: 100%; +} + .btn-group { position: relative; display: inline-flex; @@ -711,6 +676,7 @@ option { --_roundness-right: 0; position: relative; + flex: 1 1 auto; } > *:first-child, @@ -757,15 +723,17 @@ option { } &.-dot { - min-height: 0.6em; - max-height: 0.6em; - min-width: 0.6em; - max-width: 0.6em; - left: calc(50% + 0.5em); - top: calc(50% - 1em); - line-height: 0; + min-height: 8px; + max-height: 8px; + min-width: 8px; + max-width: 8px; padding: 0; - margin: 0; + line-height: 0; + font-size: 0; + left: calc(50% - 4px); + top: calc(50% - 4px); + margin-left: 6px; + margin-top: -6px; } &.-counter { @@ -796,6 +764,12 @@ option { color: var(--text); } +.visibility-notice { + padding: 0.5em; + border: 1px solid var(--textFaint); + border-radius: var(--roundness); +} + .notice-dismissible { padding-right: 4rem; position: relative; @@ -840,7 +814,7 @@ option { .login-hint { text-align: center; - @media all and (width >= 801px) { + @media all and (min-width: 801px) { display: none; } @@ -862,7 +836,7 @@ option { flex: 1; } -@media all and (width <= 800px) { +@media all and (max-width: 800px) { .mobile-hidden { display: none; } @@ -943,7 +917,12 @@ option { #splash { pointer-events: none; - // transition: opacity 0.5s; + transition: opacity 2s; + opacity: 1; + + &.hidden { + opacity: 0; + } #status { &.css-ok { @@ -967,7 +946,7 @@ option { &.dead { animation-name: dead; - animation-duration: 0.5s; + animation-duration: 2s; animation-iteration-count: 1; transform: rotateX(90deg) rotateY(0) rotateZ(-45deg); } @@ -1082,7 +1061,7 @@ option { scale: 1.0063 0.9938; translate: 0 -10%; transform: rotateZ(var(--defaultZ)); - animation-timing-function: ease-in-out; + animation-timing-function: ease-in-ou; } 90% { @@ -1101,8 +1080,3 @@ option { } } } - -@property --shadow { - syntax: "*"; - inherits: false; -} diff --git a/src/App.vue b/src/App.vue index e5e088bc3..9d7ad9129 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,6 +1,6 @@