Merge remote-tracking branch 'origin/develop' into sss-objects
This commit is contained in:
commit
76616461e9
130 changed files with 1129 additions and 1205 deletions
|
|
@ -1 +1 @@
|
||||||
18.20.7
|
18.20.8
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
{
|
{
|
||||||
"extends": [
|
"extends": [
|
||||||
"stylelint-rscss/config",
|
|
||||||
"stylelint-config-standard",
|
"stylelint-config-standard",
|
||||||
"stylelint-config-recommended-scss",
|
"stylelint-config-recommended-scss",
|
||||||
"stylelint-config-html",
|
"stylelint-config-html",
|
||||||
|
|
@ -8,15 +7,6 @@
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"declaration-no-important": true,
|
"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,
|
"selector-class-pattern": null,
|
||||||
"import-notation": null,
|
"import-notation": null,
|
||||||
"custom-property-pattern": null,
|
"custom-property-pattern": null,
|
||||||
|
|
|
||||||
68
CHANGELOG.md
68
CHANGELOG.md
|
|
@ -2,6 +2,74 @@
|
||||||
All notable changes to this project will be documented in this file.
|
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/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
## 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 `<script type="module">`
|
||||||
|
- BREAKING: css source map does not work in production (see https://github.com/vitejs/vite/issues/2830 )
|
||||||
|
- Remove emoji annotations code for unused languages from final build
|
||||||
|
|
||||||
## 2.7.1
|
## 2.7.1
|
||||||
Bugfix release. Added small optimizations to emoji picker that should make it a bit more responsive, however it needs rather large change to make it more performant which might come in a major release.
|
Bugfix release. Added small optimizations to emoji picker that should make it a bit more responsive, however it needs rather large change to make it more performant which might come in a major release.
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Added option to always convert images to JPEG format instead of using WebP when compressing images.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Updated shadow editor, hopefully fixed long-standing bugs, added ability to specify shadow's name.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Support bookmark folders
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Speed up initial boot.
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
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.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Check for canvas extract permission when initializing favicon service
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
checkbox vertical alignment has been fixed
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Some new default color schemes
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix some of the color manipulation functions
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
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
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Added support for fetching /{resource}.custom.ext to allow adding instance-specific themes without altering sourcetree
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Post actions can be customized
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Support displaying time in absolute format
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Use /api/v1/accounts/:id/follow for account subscriptions instead of the deprecated routes
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix draft saving when auto-save is off
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add draft management system
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Switch from class hack to normalButton attr for emoji count popover
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Remove emoji annotations code for unused languages from final build
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
fixed occasional overflows in emoji picker and made header scrollable
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
fix emoji inconsistencies in notifications, fix some emoji not scaling with interface
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Make sure hover style is also applied to :focus-visible
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Added configurable image compression option in general settings, allowing users to control whether images are compressed before upload.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix few markup panel inconsistencies; better ToS and registration
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix small markup inconsistencies
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Enable mobile theme editing
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
modal layout for mobile has new layout to make it easy to use
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
fixed modals buttons overflow
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix whitespaces for multiple status mute reasons, display bot status reason
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Added missing EN translation key for status.muted_user
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
better display of mute reason on posts
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Create an OAuth app only when needed
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
BREAKING: drop support for browsers that do not support `<script type="module">`
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
BREAKING: css source map does not work in production (see https://github.com/vitejs/vite/issues/2830 )
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Inform users that Smithereen public polls are public
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Simplify the OAuth client_name to 'PleromaFE'
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Internal: Migrate OAuth store to pinia
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Fix CSS compatibility issues in style_setter.js for older browsers like Palemoon
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
proper sticky header for conversations on user page
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Partially migrated from vuex to pinia
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Add text label for more actions button in post status form
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
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)
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
reply-or-quote buttons now take less space
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Bookmarks visible again on mobile
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Splash screen + loading indicator to make process of identifying initialization issues and load performance
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Authenticate and subscribe to streaming after connection
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Remove focusability on hidden popover in subject input
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Tabs now have indentation for better visibility of which tab is currently active
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
UI for making v3 themes and palettes, support for bundling v3 themes
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Resize most kinds of images on upload.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Make UserLink wrappable
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Upgraded Vue to version 3.5
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Show only month and day instead of weird "day, hour" format. While at it, fixed typo "defualt" in a comment.
|
|
||||||
37
package.json
37
package.json
|
|
@ -17,7 +17,7 @@
|
||||||
"lint-fix": "eslint --fix src test/unit/specs test/e2e/specs"
|
"lint-fix": "eslint --fix src test/unit/specs test/e2e/specs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "7.26.10",
|
"@babel/runtime": "7.27.0",
|
||||||
"@chenfengyuan/vue-qrcode": "2.0.0",
|
"@chenfengyuan/vue-qrcode": "2.0.0",
|
||||||
"@fortawesome/fontawesome-svg-core": "6.7.2",
|
"@fortawesome/fontawesome-svg-core": "6.7.2",
|
||||||
"@fortawesome/free-regular-svg-icons": "6.7.2",
|
"@fortawesome/free-regular-svg-icons": "6.7.2",
|
||||||
|
|
@ -32,15 +32,15 @@
|
||||||
"body-scroll-lock": "3.1.5",
|
"body-scroll-lock": "3.1.5",
|
||||||
"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": "2.0.0",
|
||||||
"escape-html": "1.0.3",
|
"escape-html": "1.0.3",
|
||||||
"globals": "^16.0.0",
|
"globals": "^16.0.0",
|
||||||
"hash-sum": "^2.0.0",
|
"hash-sum": "^2.0.0",
|
||||||
"js-cookie": "3.0.5",
|
"js-cookie": "3.0.5",
|
||||||
"localforage": "1.10.0",
|
"localforage": "1.10.0",
|
||||||
"parse-link-header": "2.0.0",
|
"parse-link-header": "2.0.0",
|
||||||
"phoenix": "1.7.20",
|
"phoenix": "1.7.21",
|
||||||
"pinia": "^2.0.33",
|
"pinia": "^3.0.0",
|
||||||
"punycode.js": "2.3.1",
|
"punycode.js": "2.3.1",
|
||||||
"qrcode": "1.5.4",
|
"qrcode": "1.5.4",
|
||||||
"querystring-es3": "0.2.1",
|
"querystring-es3": "0.2.1",
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.26.10",
|
"@babel/core": "7.26.10",
|
||||||
"@babel/eslint-parser": "7.26.10",
|
"@babel/eslint-parser": "7.27.0",
|
||||||
"@babel/plugin-transform-runtime": "7.26.10",
|
"@babel/plugin-transform-runtime": "7.26.10",
|
||||||
"@babel/preset-env": "7.26.9",
|
"@babel/preset-env": "7.26.9",
|
||||||
"@babel/register": "7.25.9",
|
"@babel/register": "7.25.9",
|
||||||
|
|
@ -70,17 +70,17 @@
|
||||||
"@vue/test-utils": "2.4.6",
|
"@vue/test-utils": "2.4.6",
|
||||||
"autoprefixer": "10.4.21",
|
"autoprefixer": "10.4.21",
|
||||||
"babel-plugin-lodash": "3.3.4",
|
"babel-plugin-lodash": "3.3.4",
|
||||||
"chai": "4.5.0",
|
"chai": "5.2.0",
|
||||||
"chalk": "5.4.1",
|
"chalk": "5.4.1",
|
||||||
"chromedriver": "134.0.3",
|
"chromedriver": "134.0.5",
|
||||||
"connect-history-api-fallback": "2.0.0",
|
"connect-history-api-fallback": "2.0.0",
|
||||||
"cross-spawn": "7.0.6",
|
"cross-spawn": "7.0.6",
|
||||||
"custom-event-polyfill": "1.0.7",
|
"custom-event-polyfill": "1.0.7",
|
||||||
"eslint": "9.22.0",
|
"eslint": "9.23.0",
|
||||||
"eslint-config-standard": "17.1.0",
|
"eslint-config-standard": "17.1.0",
|
||||||
"eslint-formatter-friendly": "7.0.0",
|
"eslint-formatter-friendly": "7.0.0",
|
||||||
"eslint-plugin-import": "2.31.0",
|
"eslint-plugin-import": "2.31.0",
|
||||||
"eslint-plugin-n": "17.16.2",
|
"eslint-plugin-n": "17.17.0",
|
||||||
"eslint-plugin-promise": "7.2.1",
|
"eslint-plugin-promise": "7.2.1",
|
||||||
"eslint-plugin-vue": "9.33.0",
|
"eslint-plugin-vue": "9.33.0",
|
||||||
"eventsource-polyfill": "0.9.6",
|
"eventsource-polyfill": "0.9.6",
|
||||||
|
|
@ -91,24 +91,23 @@
|
||||||
"lodash": "4.17.21",
|
"lodash": "4.17.21",
|
||||||
"msw": "2.7.3",
|
"msw": "2.7.3",
|
||||||
"nightwatch": "3.12.1",
|
"nightwatch": "3.12.1",
|
||||||
"ora": "0.4.1",
|
|
||||||
"playwright": "1.49.1",
|
"playwright": "1.49.1",
|
||||||
"postcss": "8.5.3",
|
"postcss": "8.5.3",
|
||||||
"postcss-html": "^1.5.0",
|
"postcss-html": "^1.5.0",
|
||||||
"postcss-scss": "^4.0.6",
|
"postcss-scss": "^4.0.6",
|
||||||
"sass": "1.85.1",
|
"sass": "1.86.1",
|
||||||
"selenium-server": "3.141.59",
|
"selenium-server": "3.141.59",
|
||||||
"semver": "7.7.1",
|
"semver": "7.7.1",
|
||||||
"serve-static": "1.16.2",
|
"serve-static": "2.2.0",
|
||||||
"shelljs": "0.9.2",
|
"shelljs": "0.9.2",
|
||||||
"sinon": "15.2.0",
|
"sinon": "20.0.0",
|
||||||
"sinon-chai": "3.7.0",
|
"sinon-chai": "4.0.0",
|
||||||
"stylelint": "14.16.1",
|
"stylelint": "16.17.0",
|
||||||
"stylelint-config-html": "^1.1.0",
|
"stylelint-config-html": "^1.1.0",
|
||||||
"stylelint-config-recommended-scss": "^8.0.0",
|
"stylelint-config-recommended": "^14.0.0",
|
||||||
"stylelint-config-recommended-vue": "^1.4.0",
|
"stylelint-config-recommended-scss": "^14.0.0",
|
||||||
"stylelint-config-standard": "29.0.0",
|
"stylelint-config-recommended-vue": "^1.6.0",
|
||||||
"stylelint-rscss": "0.4.0",
|
"stylelint-config-standard": "37.0.0",
|
||||||
"vite": "^6.1.0",
|
"vite": "^6.1.0",
|
||||||
"vite-plugin-eslint2": "^5.0.3",
|
"vite-plugin-eslint2": "^5.0.3",
|
||||||
"vite-plugin-stylelint": "^6.0.0",
|
"vite-plugin-stylelint": "^6.0.0",
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
accent: #1CA4F3;
|
accent: #1CA4F3;
|
||||||
cBlue: #1CA4F3;
|
cBlue: #1CA4F3;
|
||||||
cRed: #f41a51;
|
cRed: #f41a51;
|
||||||
cGreen: #1af46e;
|
cGreen: #0b6a30;
|
||||||
cOrange: #f4af1a;
|
cOrange: #f4af1a;
|
||||||
border: #d8e6f9;
|
border: #d8e6f9;
|
||||||
link: #1CA4F3;
|
link: #1CA4F3;
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
accent: #1CA4F3;
|
accent: #1CA4F3;
|
||||||
cRed: #f41a51;
|
cRed: #f41a51;
|
||||||
cBlue: #1CA4F3;
|
cBlue: #1CA4F3;
|
||||||
cGreen: #1af46e;
|
cGreen: #0b6a30;
|
||||||
cOrange: #f4af1a;
|
cOrange: #f4af1a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,45 +47,46 @@ Root {
|
||||||
--badgeNotification: color | --cRed;
|
--badgeNotification: color | --cRed;
|
||||||
--buttonDefaultHoverGlow: shadow | inset 0 0 0 1 --accent / 1;
|
--buttonDefaultHoverGlow: shadow | inset 0 0 0 1 --accent / 1;
|
||||||
--buttonDefaultFocusGlow: shadow | inset 0 0 0 1 --accent / 1;
|
--buttonDefaultFocusGlow: shadow | inset 0 0 0 1 --accent / 1;
|
||||||
--buttonDefaultShadow: shadow | inset 0 0 0 1 --parent--text / 0.35, 0 5 5 -5 #000000 / 0.35;
|
--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;
|
--buttonDefaultBevel: shadow | inset 0 14 14 -14 #FFFFFF / 0.1;
|
||||||
--buttonPressedBevel: shadow | inset 0 -20 20 -20 #000000 / 0.05;
|
--buttonPressedBevel: shadow | inset 0 -20 20 -20 #000000 / 0.05;
|
||||||
--defaultInputBevel: shadow | inset 0 0 0 1 --parent--text / 0.35;
|
--defaultInputBevel: shadow | inset 0 0 0 1 --text / 0.35;
|
||||||
--defaultInputHoverGlow: shadow | 0 0 0 1 --accent / 1;
|
--defaultInputHoverGlow: shadow | 0 0 0 1 --accent / 1;
|
||||||
--defaultInputFocusGlow: shadow | 0 0 0 1 --link / 1;
|
--defaultInputFocusGlow: shadow | 0 0 0 1 --link / 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
background: --parent;
|
||||||
|
}
|
||||||
|
|
||||||
Button:disabled {
|
Button:disabled {
|
||||||
shadow: --buttonDefaultBevel, --buttonDefaultShadow
|
shadow: --buttonDefaultBevel, --buttonDefaultShadow
|
||||||
}
|
}
|
||||||
|
|
||||||
Button:hover {
|
Button:hover {
|
||||||
|
background: --inheritedBackground;
|
||||||
shadow: --buttonDefaultHoverGlow, --buttonDefaultBevel, --buttonDefaultShadow
|
shadow: --buttonDefaultHoverGlow, --buttonDefaultBevel, --buttonDefaultShadow
|
||||||
}
|
}
|
||||||
|
|
||||||
Button:toggled {
|
Button:toggled {
|
||||||
background: $blend(--bg 0.3 --accent)
|
background: $blend(--inheritedBackground 0.3 --accent)
|
||||||
}
|
}
|
||||||
|
|
||||||
Button:pressed {
|
Button:pressed {
|
||||||
background: $blend(--bg 0.8 --accent)
|
background: $blend(--inheritedBackground 0.8 --accent)
|
||||||
}
|
}
|
||||||
|
|
||||||
Button:pressed:toggled {
|
Button:pressed:toggled {
|
||||||
background: $blend(--bg 0.2 --accent)
|
background: $blend(--inheritedBackground 0.2 --accent)
|
||||||
}
|
}
|
||||||
|
|
||||||
Button:toggled:hover {
|
Button:toggled:hover {
|
||||||
background: $blend(--bg 0.3 --accent)
|
background: $blend(--inheritedBackground 0.3 --accent)
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
|
||||||
background: --parent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Input {
|
Input {
|
||||||
shadow: --defaultInputBevel;
|
shadow: --defaultInputBevel;
|
||||||
background: --parent;
|
background: $mod(--bg -10);
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelHeader {
|
PanelHeader {
|
||||||
|
|
@ -97,5 +98,5 @@ Tab:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
Tab {
|
Tab {
|
||||||
background: --parent;
|
background: --bg;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
src/App.scss
17
src/App.scss
|
|
@ -34,8 +34,7 @@ body {
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
overscroll-behavior-y: none;
|
overscroll-behavior-y: none;
|
||||||
overflow-x: clip;
|
overflow: clip scroll;
|
||||||
overflow-y: scroll;
|
|
||||||
|
|
||||||
&.hidden {
|
&.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
@ -224,9 +223,8 @@ nav {
|
||||||
grid-template-rows: 1fr;
|
grid-template-rows: 1fr;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
align-content: flex-start;
|
place-content: flex-start center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: center;
|
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
overflow-x: clip;
|
overflow-x: clip;
|
||||||
|
|
||||||
|
|
@ -262,8 +260,7 @@ nav {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: var(--navbar-height);
|
top: var(--navbar-height);
|
||||||
max-height: calc(100vh - var(--navbar-height));
|
max-height: calc(100vh - var(--navbar-height));
|
||||||
overflow-y: auto;
|
overflow: hidden auto;
|
||||||
overflow-x: hidden;
|
|
||||||
margin-left: calc(var(--___paddingIncrease) * -1);
|
margin-left: calc(var(--___paddingIncrease) * -1);
|
||||||
padding-left: calc(var(--___paddingIncrease) + var(--___columnMargin) / 2);
|
padding-left: calc(var(--___paddingIncrease) + var(--___columnMargin) / 2);
|
||||||
|
|
||||||
|
|
@ -388,6 +385,10 @@ nav {
|
||||||
&:disabled {
|
&:disabled {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: translate(1px, 1px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-item {
|
.menu-item {
|
||||||
|
|
@ -828,7 +829,7 @@ option {
|
||||||
.login-hint {
|
.login-hint {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
@media all and (min-width: 801px) {
|
@media all and (width >= 801px) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -850,7 +851,7 @@ option {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 800px) {
|
@media all and (width <= 800px) {
|
||||||
.mobile-hidden {
|
.mobile-hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@
|
||||||
.post-textarea {
|
.post-textarea {
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
height: 10em;
|
height: 10em;
|
||||||
overflow: none;
|
overflow: visible;
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,8 +107,7 @@
|
||||||
.outgoing {
|
.outgoing {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row wrap;
|
flex-flow: row wrap;
|
||||||
align-content: end;
|
place-content: end flex-end;
|
||||||
justify-content: flex-end;
|
|
||||||
|
|
||||||
.chat-message-inner {
|
.chat-message-inner {
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
|
|
|
||||||
|
|
@ -190,20 +190,15 @@ export default {
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
grid-area: header;
|
grid-area: header;
|
||||||
justify-self: center;
|
place-self: baseline center;
|
||||||
align-self: baseline;
|
|
||||||
line-height: 2;
|
line-height: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.invalid-container {
|
.invalid-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
inset: 0;
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
display: grid;
|
display: grid;
|
||||||
align-items: center;
|
place-items: center center;
|
||||||
justify-items: center;
|
|
||||||
background-color: rgba(100 0 0 / 50%);
|
background-color: rgba(100 0 0 / 50%);
|
||||||
|
|
||||||
.alert {
|
.alert {
|
||||||
|
|
@ -214,7 +209,7 @@ export default {
|
||||||
.assists {
|
.assists {
|
||||||
grid-area: assists;
|
grid-area: assists;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-auto-flow: rows;
|
grid-auto-flow: row;
|
||||||
grid-auto-rows: 2em;
|
grid-auto-rows: 2em;
|
||||||
grid-gap: 0.5em;
|
grid-gap: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -322,10 +322,7 @@
|
||||||
content: "";
|
content: "";
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: calc(var(--___margin) * -1);
|
inset: calc(var(--___margin) * -1);
|
||||||
bottom: calc(var(--___margin) * -1);
|
|
||||||
left: calc(var(--___margin) * -1);
|
|
||||||
right: calc(var(--___margin) * -1);
|
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
backdrop-filter: var(--__panel-backdrop-filter);
|
backdrop-filter: var(--__panel-backdrop-filter);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
transition-timing-function: ease-out;
|
transition-timing-function: ease-out;
|
||||||
transition-duration: 100ms;
|
transition-duration: 100ms;
|
||||||
|
|
||||||
@media all and (min-width: 800px) {
|
@media all and (width >= 800px) {
|
||||||
/* stylelint-disable-next-line declaration-no-important */
|
/* stylelint-disable-next-line declaration-no-important */
|
||||||
opacity: 1 !important;
|
opacity: 1 !important;
|
||||||
}
|
}
|
||||||
|
|
@ -70,10 +70,7 @@
|
||||||
mask-size: contain;
|
mask-size: contain;
|
||||||
background-color: var(--text);
|
background-color: var(--text);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
inset: 0;
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,11 @@
|
||||||
// TODO: unify with other modals.
|
// TODO: unify with other modals.
|
||||||
.dark-overlay {
|
.dark-overlay {
|
||||||
&::before {
|
&::before {
|
||||||
bottom: 0;
|
inset: 0;
|
||||||
content: " ";
|
content: " ";
|
||||||
display: block;
|
display: block;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
left: 0;
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
background: rgb(27 31 35 / 50%);
|
background: rgb(27 31 35 / 50%);
|
||||||
z-index: 2000;
|
z-index: 2000;
|
||||||
}
|
}
|
||||||
|
|
@ -45,13 +42,9 @@
|
||||||
.dialog-container {
|
.dialog-container {
|
||||||
display: grid;
|
display: grid;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
inset: 0;
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
place-items: center center;
|
||||||
justify-items: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-modal.panel {
|
.dialog-modal.panel {
|
||||||
|
|
@ -98,8 +91,7 @@
|
||||||
#modal.-mobile {
|
#modal.-mobile {
|
||||||
.dialog-container {
|
.dialog-container {
|
||||||
justify-content: stretch;
|
justify-content: stretch;
|
||||||
align-items: end;
|
place-items: end stretch;
|
||||||
justify-items: stretch;
|
|
||||||
|
|
||||||
&.-center-mobile {
|
&.-center-mobile {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
@ -114,7 +106,6 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
grid-auto-columns: none;
|
|
||||||
grid-auto-rows: auto;
|
grid-auto-rows: auto;
|
||||||
grid-auto-flow: row dense;
|
grid-auto-flow: row dense;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -135,8 +135,7 @@
|
||||||
.poll-indicator-container {
|
.poll-indicator-container {
|
||||||
border-radius: var(--roundness);
|
border-radius: var(--roundness);
|
||||||
display: grid;
|
display: grid;
|
||||||
justify-items: center;
|
place-items: center center;
|
||||||
align-items: center;
|
|
||||||
align-self: start;
|
align-self: start;
|
||||||
height: 0;
|
height: 0;
|
||||||
padding-bottom: 62.5%;
|
padding-bottom: 62.5%;
|
||||||
|
|
@ -147,13 +146,9 @@
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
inset: 0;
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
display: grid;
|
display: grid;
|
||||||
justify-items: center;
|
place-items: center center;
|
||||||
align-items: center;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -159,10 +159,7 @@
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
inset: 0;
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
left: 0;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
/* DEBUG STUFF */
|
/* DEBUG STUFF */
|
||||||
|
|
|
||||||
|
|
@ -64,8 +64,7 @@
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row nowrap;
|
flex-flow: row nowrap;
|
||||||
overflow-x: auto;
|
overflow: auto hidden;
|
||||||
overflow-y: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.additional-tabs {
|
.additional-tabs {
|
||||||
|
|
@ -153,7 +152,13 @@
|
||||||
transition: mask-size 150ms;
|
transition: mask-size 150ms;
|
||||||
mask-size: 100% 20px, 100% 20px, auto;
|
mask-size: 100% 20px, 100% 20px, auto;
|
||||||
// Autoprefixed seem to ignore this one, and also syntax is different
|
// Autoprefixed seem to ignore this one, and also syntax is different
|
||||||
|
/* stylelint-disable mask-composite */
|
||||||
|
/* stylelint-disable declaration-property-value-no-unknown */
|
||||||
|
|
||||||
|
/* TODO check if this is still needed */
|
||||||
mask-composite: xor;
|
mask-composite: xor;
|
||||||
|
/* stylelint-enable declaration-property-value-no-unknown */
|
||||||
|
/* stylelint-enable mask-composite */
|
||||||
mask-composite: exclude;
|
mask-composite: exclude;
|
||||||
|
|
||||||
&.scrolled {
|
&.scrolled {
|
||||||
|
|
@ -197,8 +202,7 @@
|
||||||
&-group {
|
&-group {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(var(--__amount), 1fr);
|
grid-template-columns: repeat(var(--__amount), 1fr);
|
||||||
align-items: center;
|
place-items: center center;
|
||||||
justify-items: center;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
grid-template-rows: repeat(1, auto);
|
grid-template-rows: repeat(1, auto);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@
|
||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
visibility: "hidden";
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -101,10 +101,7 @@
|
||||||
|
|
||||||
.gallery-row-inner {
|
.gallery-row-inner {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
inset: 0;
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row wrap;
|
flex-flow: row wrap;
|
||||||
align-content: stretch;
|
align-content: stretch;
|
||||||
|
|
@ -160,7 +157,13 @@
|
||||||
linear-gradient(to top, white, white);
|
linear-gradient(to top, white, white);
|
||||||
|
|
||||||
/* Autoprefixed seem to ignore this one, and also syntax is different */
|
/* Autoprefixed seem to ignore this one, and also syntax is different */
|
||||||
|
/* stylelint-disable mask-composite */
|
||||||
|
/* stylelint-disable declaration-property-value-no-unknown */
|
||||||
|
|
||||||
|
/* TODO check if this is still needed */
|
||||||
mask-composite: xor;
|
mask-composite: xor;
|
||||||
|
/* stylelint-enable declaration-property-value-no-unknown */
|
||||||
|
/* stylelint-enable mask-composite */
|
||||||
mask-composite: exclude;
|
mask-composite: exclude;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import Cropper from 'cropperjs'
|
import 'cropperjs' // This adds all of the cropperjs's components into DOM
|
||||||
import 'cropperjs/dist/cropper.css'
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
faCircleNotch
|
faCircleNotch
|
||||||
|
|
@ -19,19 +18,6 @@ const ImageCropper = {
|
||||||
type: Function,
|
type: Function,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
cropperOptions: {
|
|
||||||
type: Object,
|
|
||||||
default () {
|
|
||||||
return {
|
|
||||||
aspectRatio: 1,
|
|
||||||
autoCropArea: 1,
|
|
||||||
viewMode: 1,
|
|
||||||
movable: false,
|
|
||||||
zoomable: false,
|
|
||||||
guides: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mimes: {
|
mimes: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon'
|
default: 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon'
|
||||||
|
|
@ -48,7 +34,6 @@ const ImageCropper = {
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
cropper: undefined,
|
|
||||||
dataUrl: undefined,
|
dataUrl: undefined,
|
||||||
filename: undefined,
|
filename: undefined,
|
||||||
submitting: false
|
submitting: false
|
||||||
|
|
@ -67,27 +52,30 @@ const ImageCropper = {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
destroy () {
|
destroy () {
|
||||||
if (this.cropper) {
|
|
||||||
this.cropper.destroy()
|
|
||||||
}
|
|
||||||
this.$refs.input.value = ''
|
this.$refs.input.value = ''
|
||||||
this.dataUrl = undefined
|
this.dataUrl = undefined
|
||||||
this.$emit('close')
|
this.$emit('close')
|
||||||
},
|
},
|
||||||
submit (cropping = true) {
|
submit (cropping = true) {
|
||||||
this.submitting = true
|
this.submitting = true
|
||||||
this.submitHandler(cropping && this.cropper, this.file)
|
|
||||||
.then(() => this.destroy())
|
let cropperPromise
|
||||||
.finally(() => {
|
if (cropping) {
|
||||||
this.submitting = false
|
cropperPromise = this.$refs.cropperSelection.$toCanvas()
|
||||||
})
|
} else {
|
||||||
|
cropperPromise = Promise.resolve()
|
||||||
|
}
|
||||||
|
cropperPromise.then(canvas => {
|
||||||
|
this.submitHandler(canvas, this.file)
|
||||||
|
.then(() => this.destroy())
|
||||||
|
.finally(() => {
|
||||||
|
this.submitting = false
|
||||||
|
})
|
||||||
|
})
|
||||||
},
|
},
|
||||||
pickImage () {
|
pickImage () {
|
||||||
this.$refs.input.click()
|
this.$refs.input.click()
|
||||||
},
|
},
|
||||||
createCropper () {
|
|
||||||
this.cropper = new Cropper(this.$refs.img, this.cropperOptions)
|
|
||||||
},
|
|
||||||
getTriggerDOM () {
|
getTriggerDOM () {
|
||||||
return typeof this.trigger === 'object' ? this.trigger : document.querySelector(this.trigger)
|
return typeof this.trigger === 'object' ? this.trigger : document.querySelector(this.trigger)
|
||||||
},
|
},
|
||||||
|
|
@ -103,6 +91,29 @@ const ImageCropper = {
|
||||||
reader.readAsDataURL(this.file)
|
reader.readAsDataURL(this.file)
|
||||||
this.$emit('changed', this.file, reader)
|
this.$emit('changed', this.file, reader)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
inSelection(selection, maxSelection) {
|
||||||
|
return (
|
||||||
|
selection.x >= maxSelection.x
|
||||||
|
&& selection.y >= maxSelection.y
|
||||||
|
&& (selection.x + selection.width) <= (maxSelection.x + maxSelection.width)
|
||||||
|
&& (selection.y + selection.height) <= (maxSelection.y + maxSelection.height)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onCropperSelectionChange(event) {
|
||||||
|
const cropperCanvas = this.$refs.cropperCanvas
|
||||||
|
const cropperCanvasRect = cropperCanvas.getBoundingClientRect()
|
||||||
|
const selection = event.detail
|
||||||
|
const maxSelection = {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: cropperCanvasRect.width,
|
||||||
|
height: cropperCanvasRect.height,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.inSelection(selection, maxSelection)) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,43 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="image-cropper">
|
<div class="image-cropper">
|
||||||
<div v-if="dataUrl">
|
<div v-if="dataUrl">
|
||||||
<div class="image-cropper-image-container">
|
<cropper-canvas
|
||||||
<img
|
background
|
||||||
ref="img"
|
class="image-cropper-canvas"
|
||||||
|
ref="cropperCanvas"
|
||||||
|
height="25em"
|
||||||
|
>
|
||||||
|
<cropper-image
|
||||||
:src="dataUrl"
|
:src="dataUrl"
|
||||||
alt=""
|
alt="Picture"
|
||||||
@load.stop="createCropper"
|
ref="cropperImage"
|
||||||
|
class="image-cropper-image"
|
||||||
|
translatable
|
||||||
|
scalable
|
||||||
|
/>
|
||||||
|
<cropper-shade hidden />
|
||||||
|
<cropper-handle action="select" plain />
|
||||||
|
<cropper-selection
|
||||||
|
ref="cropperSelection"
|
||||||
|
initial-coverage="1"
|
||||||
|
aspect-ratio="1"
|
||||||
|
movable
|
||||||
|
resizable
|
||||||
|
@change="onCropperSelectionChange"
|
||||||
>
|
>
|
||||||
</div>
|
<cropper-grid role="grid" covered></cropper-grid>
|
||||||
|
<cropper-crosshair centered></cropper-crosshair>
|
||||||
|
<cropper-handle action="move" theme-color="rgba(255, 255, 255, 0.35)"></cropper-handle>
|
||||||
|
<cropper-handle action="n-resize"></cropper-handle>
|
||||||
|
<cropper-handle action="e-resize"></cropper-handle>
|
||||||
|
<cropper-handle action="s-resize"></cropper-handle>
|
||||||
|
<cropper-handle action="w-resize"></cropper-handle>
|
||||||
|
<cropper-handle action="ne-resize"></cropper-handle>
|
||||||
|
<cropper-handle action="nw-resize"></cropper-handle>
|
||||||
|
<cropper-handle action="se-resize"></cropper-handle>
|
||||||
|
<cropper-handle action="sw-resize"></cropper-handle>
|
||||||
|
</cropper-selection>
|
||||||
|
</cropper-canvas>
|
||||||
<div class="image-cropper-buttons-wrapper">
|
<div class="image-cropper-buttons-wrapper">
|
||||||
<button
|
<button
|
||||||
class="button-default btn"
|
class="button-default btn"
|
||||||
|
|
@ -55,20 +84,18 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-image-container {
|
&-canvas {
|
||||||
position: relative;
|
height: 25em;
|
||||||
|
width: 25em;
|
||||||
img {
|
|
||||||
display: block;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&-buttons-wrapper {
|
&-buttons-wrapper {
|
||||||
margin-top: 10px;
|
display: grid;
|
||||||
|
grid-gap: 0.5em;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
margin-top: 5px;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,10 +68,12 @@
|
||||||
margin: 0.5em 0 0;
|
margin: 0.5em 0 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
word-break: break-word;
|
word-break: break-all;
|
||||||
line-height: 1.2em;
|
line-height: 1.2em;
|
||||||
// cap description at 3 lines, the 1px is to clean up some stray pixels
|
|
||||||
// TODO: fancier fade-out at the bottom to show off that it's too long?
|
/* cap description at 3 lines, the 1px is to clean up some stray pixels
|
||||||
|
TODO: fancier fade-out at the bottom to show off that it's too long?
|
||||||
|
*/
|
||||||
max-height: calc(1.2em * 3 - 1px);
|
max-height: calc(1.2em * 3 - 1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import mfaApi from '../../services/new_api/mfa.js'
|
import mfaApi from '../../services/new_api/mfa.js'
|
||||||
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'
|
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'
|
||||||
|
import { mapStores } from 'pinia'
|
||||||
|
import { useOAuthStore } from 'src/stores/oauth.js'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
faTimes
|
faTimes
|
||||||
|
|
@ -18,17 +20,24 @@ export default {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
authSettings: 'authFlow/settings'
|
authSettings: 'authFlow/settings'
|
||||||
}),
|
}),
|
||||||
|
...mapStores(useOAuthStore),
|
||||||
...mapState({
|
...mapState({
|
||||||
instance: 'instance',
|
instance: 'instance',
|
||||||
oauth: 'oauth'
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapMutations('authFlow', ['requireTOTP', 'abortMFA']),
|
...mapMutations('authFlow', ['requireTOTP', 'abortMFA']),
|
||||||
...mapActions({ login: 'authFlow/login' }),
|
...mapActions({ login: 'authFlow/login' }),
|
||||||
clearError () { this.error = false },
|
clearError () { this.error = false },
|
||||||
|
|
||||||
|
focusOnCodeInput () {
|
||||||
|
const codeInput = this.$refs.codeInput
|
||||||
|
codeInput.focus()
|
||||||
|
codeInput.setSelectionRange(0, codeInput.value.length)
|
||||||
|
},
|
||||||
|
|
||||||
submit () {
|
submit () {
|
||||||
const { clientId, clientSecret } = this.oauth
|
const { clientId, clientSecret } = this.oauthStore
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
clientId,
|
clientId,
|
||||||
|
|
@ -42,6 +51,7 @@ export default {
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
this.error = result.error
|
this.error = result.error
|
||||||
this.code = null
|
this.code = null
|
||||||
|
this.focusOnCodeInput()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="login panel panel-default">
|
<div class="login-panel panel panel-default">
|
||||||
<!-- Default panel contents -->
|
<!-- Default panel contents -->
|
||||||
|
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
<label for="code">{{ $t('login.recovery_code') }}</label>
|
<label for="code">{{ $t('login.recovery_code') }}</label>
|
||||||
<input
|
<input
|
||||||
id="code"
|
id="code"
|
||||||
|
ref="codeInput"
|
||||||
v-model="code"
|
v-model="code"
|
||||||
class="input form-control"
|
class="input form-control"
|
||||||
>
|
>
|
||||||
|
|
@ -71,4 +72,5 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./recovery_form.js"></script>
|
<script src="./recovery_form.js"></script>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import mfaApi from '../../services/new_api/mfa.js'
|
import mfaApi from '../../services/new_api/mfa.js'
|
||||||
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'
|
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'
|
||||||
|
import { mapStores } from 'pinia'
|
||||||
|
import { useOAuthStore } from 'src/stores/oauth.js'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import {
|
import {
|
||||||
faTimes
|
faTimes
|
||||||
|
|
@ -18,17 +20,24 @@ export default {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
authSettings: 'authFlow/settings'
|
authSettings: 'authFlow/settings'
|
||||||
}),
|
}),
|
||||||
|
...mapStores(useOAuthStore),
|
||||||
...mapState({
|
...mapState({
|
||||||
instance: 'instance',
|
instance: 'instance',
|
||||||
oauth: 'oauth'
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapMutations('authFlow', ['requireRecovery', 'abortMFA']),
|
...mapMutations('authFlow', ['requireRecovery', 'abortMFA']),
|
||||||
...mapActions({ login: 'authFlow/login' }),
|
...mapActions({ login: 'authFlow/login' }),
|
||||||
clearError () { this.error = false },
|
clearError () { this.error = false },
|
||||||
|
|
||||||
|
focusOnCodeInput () {
|
||||||
|
const codeInput = this.$refs.codeInput
|
||||||
|
codeInput.focus()
|
||||||
|
codeInput.setSelectionRange(0, codeInput.value.length)
|
||||||
|
},
|
||||||
|
|
||||||
submit () {
|
submit () {
|
||||||
const { clientId, clientSecret } = this.oauth
|
const { clientId, clientSecret } = this.oauthStore
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
clientId,
|
clientId,
|
||||||
|
|
@ -42,6 +51,7 @@ export default {
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
this.error = result.error
|
this.error = result.error
|
||||||
this.code = null
|
this.code = null
|
||||||
|
this.focusOnCodeInput()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="login panel panel-default">
|
<div class="login-panel panel panel-default">
|
||||||
<!-- Default panel contents -->
|
<!-- Default panel contents -->
|
||||||
|
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="code"
|
id="code"
|
||||||
|
ref="codeInput"
|
||||||
v-model="code"
|
v-model="code"
|
||||||
class="input form-control"
|
class="input form-control"
|
||||||
>
|
>
|
||||||
|
|
@ -74,4 +75,5 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="./totp_form.js"></script>
|
<script src="./totp_form.js"></script>
|
||||||
|
|
|
||||||
|
|
@ -220,8 +220,7 @@
|
||||||
margin-top: 3.5em;
|
margin-top: 3.5em;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: calc(100vh - var(--navbar-height));
|
height: calc(100vh - var(--navbar-height));
|
||||||
overflow-x: hidden;
|
overflow: hidden scroll;
|
||||||
overflow-y: scroll;
|
|
||||||
|
|
||||||
.notifications {
|
.notifications {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (min-width: 801px) {
|
@media all and (width >= 801px) {
|
||||||
.new-status-button:not(.always-show) {
|
.new-status-button:not(.always-show) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,7 @@ export default {
|
||||||
.modal-view {
|
.modal-view {
|
||||||
z-index: var(--ZI_modals);
|
z-index: var(--ZI_modals);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
inset: 0;
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
border-bottom: 1px solid;
|
border-bottom: 1px solid;
|
||||||
border-color: var(--border);
|
border-color: var(--border);
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
word-break: break-word;
|
word-break: break-all;
|
||||||
|
|
||||||
&.Status {
|
&.Status {
|
||||||
/* stylelint-disable-next-line declaration-no-important */
|
/* stylelint-disable-next-line declaration-no-important */
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,7 @@
|
||||||
|
|
||||||
.notification-overlay {
|
.notification-overlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
inset: 0;
|
||||||
right: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue