Merge branch 'fixes-roundup4' into 'develop'

Fixes roundup 4

See merge request pleroma/pleroma-fe!2040
This commit is contained in:
HJ 2025-02-20 10:16:20 +00:00
commit b0af90a629
49 changed files with 341 additions and 299 deletions

View file

@ -53,7 +53,8 @@ Object.keys(proxyTable).forEach(function (context) {
if (typeof options === 'string') { if (typeof options === 'string') {
options = { target: options } options = { target: options }
} }
app.use(proxyMiddleware.createProxyMiddleware(context, options)) options.pathFilter = context
app.use(proxyMiddleware.createProxyMiddleware(options))
}) })
// handle fallback for HTML5 history API // handle fallback for HTML5 history API

View file

View file

@ -36,7 +36,6 @@
"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",
"pako": "^2.1.0",
"parse-link-header": "2.0.0", "parse-link-header": "2.0.0",
"phoenix": "1.7.19", "phoenix": "1.7.19",
"pinia": "^2.0.33", "pinia": "^2.0.33",

View file

@ -1,6 +1,6 @@
// stylelint-disable rscss/class-format // stylelint-disable rscss/class-format
/* stylelint-disable no-descending-specificity */ /* stylelint-disable no-descending-specificity */
@import "./panel"; @use "panel";
:root { :root {
--status-margin: 0.75em; --status-margin: 0.75em;
@ -762,12 +762,6 @@ option {
margin-left: 0.7em; margin-left: 0.7em;
margin-top: -1em; margin-top: -1em;
} }
&.-neutral {
background-color: var(--badgeNeutral);
color: white;
color: var(--badgeNeutralText, white);
}
} }
.alert { .alert {
@ -1100,3 +1094,8 @@ option {
} }
} }
} }
@property --shadow {
syntax: "*";
inherits: false;
}

View file

@ -4,7 +4,7 @@ export default {
notEditable: true, notEditable: true,
validInnerComponents: [ validInnerComponents: [
'Border', 'Border',
'ButtonUnstyled', 'Button',
'Input' 'Input'
], ],
defaultRules: [ defaultRules: [
@ -14,7 +14,7 @@ export default {
} }
}, },
{ {
component: 'ButtonUnstyled', component: 'Button',
parent: { component: 'Attachment' }, parent: { component: 'Attachment' },
directives: { directives: {
background: '#FFFFFF', background: '#FFFFFF',

View file

@ -1,7 +1,7 @@
<template> <template>
<button <button
v-if="usePlaceholder" v-if="usePlaceholder"
class="Attachment -placeholder button-unstyled" class="Attachment -placeholder button-default"
:class="classNames" :class="classNames"
@click="openModal" @click="openModal"
> >
@ -23,7 +23,7 @@
> >
<button <button
v-if="remove" v-if="remove"
class="button-unstyled attachment-button" class="button-default attachment-button"
@click.prevent="onRemove" @click.prevent="onRemove"
> >
<FAIcon icon="trash-alt" /> <FAIcon icon="trash-alt" />
@ -81,7 +81,7 @@
> >
<button <button
v-if="type === 'flash' && flashLoaded" v-if="type === 'flash' && flashLoaded"
class="button-unstyled attachment-button" class="button-default attachment-button"
:title="$t('status.attachment_stop_flash')" :title="$t('status.attachment_stop_flash')"
@click.prevent="stopFlash" @click.prevent="stopFlash"
> >
@ -89,7 +89,7 @@
</button> </button>
<button <button
v-if="attachment.description && size !== 'small' && !edit && type !== 'unknown'" v-if="attachment.description && size !== 'small' && !edit && type !== 'unknown'"
class="button-unstyled attachment-button" class="button-default attachment-button"
:title="$t('status.show_attachment_description')" :title="$t('status.show_attachment_description')"
@click.prevent="toggleDescription" @click.prevent="toggleDescription"
> >
@ -97,7 +97,7 @@
</button> </button>
<button <button
v-if="!useModal && type !== 'unknown'" v-if="!useModal && type !== 'unknown'"
class="button-unstyled attachment-button" class="button-default attachment-button"
:title="$t('status.show_attachment_in_modal')" :title="$t('status.show_attachment_in_modal')"
@click.prevent="openModalForce" @click.prevent="openModalForce"
> >
@ -105,7 +105,7 @@
</button> </button>
<button <button
v-if="nsfw && hideNsfwLocal" v-if="nsfw && hideNsfwLocal"
class="button-unstyled attachment-button" class="button-default attachment-button"
:title="$t('status.hide_attachment')" :title="$t('status.hide_attachment')"
@click.prevent="toggleHidden" @click.prevent="toggleHidden"
> >
@ -113,7 +113,7 @@
</button> </button>
<button <button
v-if="shiftUp" v-if="shiftUp"
class="button-unstyled attachment-button" class="button-default attachment-button"
:title="$t('status.move_up')" :title="$t('status.move_up')"
@click.prevent="onShiftUp" @click.prevent="onShiftUp"
> >
@ -121,7 +121,7 @@
</button> </button>
<button <button
v-if="shiftDn" v-if="shiftDn"
class="button-unstyled attachment-button" class="button-default attachment-button"
:title="$t('status.move_down')" :title="$t('status.move_down')"
@click.prevent="onShiftDn" @click.prevent="onShiftDn"
> >
@ -129,7 +129,7 @@
</button> </button>
<button <button
v-if="remove" v-if="remove"
class="button-unstyled attachment-button" class="button-default attachment-button"
:title="$t('status.remove_attachment')" :title="$t('status.remove_attachment')"
@click.prevent="onRemove" @click.prevent="onRemove"
> >

View file

@ -2,6 +2,7 @@ export default {
name: 'ButtonUnstyled', name: 'ButtonUnstyled',
selector: '.button-unstyled', selector: '.button-unstyled',
notEditable: true, notEditable: true,
transparent: true,
states: { states: {
toggled: '.toggled', toggled: '.toggled',
disabled: ':disabled', disabled: ':disabled',

View file

@ -95,6 +95,4 @@
</template> </template>
<script src="./chat.js"></script> <script src="./chat.js"></script>
<style lang="scss"> <style src="./chat.scss" lang="scss" />
@import "./chat";
</style>

View file

@ -47,6 +47,4 @@
<script src="./chat_list_item.js"></script> <script src="./chat_list_item.js"></script>
<style lang="scss"> <style src="./chat_list_item.scss" lang="scss" />
@import "./chat_list_item";
</style>

View file

@ -98,7 +98,5 @@
</template> </template>
<script src="./chat_message.js"></script> <script src="./chat_message.js"></script>
<style lang="scss">
@import "./chat_message";
</style> <style src="./chat_message.scss" lang="scss" />

View file

@ -47,6 +47,5 @@
</template> </template>
<script src="./chat_new.js"></script> <script src="./chat_new.js"></script>
<style lang="scss">
@import "./chat_new"; <style src="./chat_new.scss" lang="scss" />
</style>

View file

@ -63,8 +63,6 @@ export default {
</script> </script>
<style lang="scss"> <style lang="scss">
@import "../../mixins";
.checkbox { .checkbox {
position: relative; position: relative;
display: inline-block; display: inline-block;
@ -85,6 +83,8 @@ export default {
width: 1.2em; width: 1.2em;
height: 1.2em; height: 1.2em;
box-shadow: none; box-shadow: none;
--_shadow: var(--shadow);
} }
&-indicator::before { &-indicator::before {
@ -96,7 +96,7 @@ export default {
width: 1.1em; width: 1.1em;
height: 1.1em; height: 1.1em;
border-radius: var(--roundness); border-radius: var(--roundness);
box-shadow: var(--shadow); box-shadow: var(--_shadow);
background-color: var(--background); background-color: var(--background);
vertical-align: top; vertical-align: top;
text-align: center; text-align: center;

View file

@ -22,6 +22,7 @@ const ConfirmModal = {
type: String type: String
} }
}, },
emits: ['cancelled', 'accepted'],
computed: { computed: {
}, },
methods: { methods: {

View file

@ -1,8 +1,8 @@
<template> <template>
<dialog-modal <DialogModal
v-body-scroll-lock="true" v-body-scroll-lock="true"
class="confirm-modal" class="confirm-modal"
:on-cancel="onCancel" @cancel="onCancel"
> >
<template #header> <template #header>
<span v-text="title" /> <span v-text="title" />
@ -23,7 +23,7 @@
v-text="cancelText" v-text="cancelText"
/> />
</template> </template>
</dialog-modal> </DialogModal>
</template> </template>
<script src="./confirm_modal.js"></script> <script src="./confirm_modal.js"></script>

View file

@ -0,0 +1,121 @@
@use "../../mixins";
.EmojiReactions {
display: flex;
margin-top: 0.25em;
flex-wrap: wrap;
--emoji-size: calc(var(--emojiSize, 1.25em) * var(--emojiReactionsScale, 1));
.emoji-reaction-container {
display: flex;
align-items: stretch;
margin-top: 0.5em;
margin-right: 0.5em;
.emoji-reaction-popover {
padding: 0;
.emoji-reaction-count-button {
margin: 0;
height: 100%;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
box-sizing: border-box;
min-width: 2em;
display: inline-flex;
justify-content: center;
align-items: center;
}
}
}
.emoji-reaction {
padding-left: 0.5em;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
margin: 0;
.reaction-emoji {
width: var(--emoji-size);
height: var(--emoji-size);
margin-right: 0.25em;
line-height: var(--emoji-size);
display: flex;
justify-content: center;
align-items: center;
--_still_image-label-scale: 0.3;
}
.reaction-emoji-content {
max-width: 100%;
max-height: 100%;
width: var(--emoji-size);
height: var(--emoji-size);
line-height: inherit;
overflow: hidden;
font-size: calc(var(--emoji-size) * 0.8);
margin: 0;
img {
object-fit: contain;
}
}
&:focus {
outline: none;
}
.svg-inline--fa {
color: var(--text);
}
&.-picked-reaction {
.svg-inline--fa {
color: var(--accent);
}
}
@include mixins.unfocused-style {
.focus-marker {
visibility: hidden;
}
.active-marker {
visibility: visible;
}
}
@include mixins.focused-style {
.svg-inline--fa {
color: var(--accent);
}
.focus-marker {
visibility: visible;
}
.active-marker {
visibility: hidden;
}
}
}
.emoji-reaction-expand {
padding: 0 0.5em;
margin-right: 0.5em;
margin-top: 0.5em;
display: flex;
align-items: center;
justify-content: center;
&:hover {
text-decoration: underline;
}
}
}

View file

@ -70,126 +70,5 @@
</template> </template>
<script src="./emoji_reactions.js"></script> <script src="./emoji_reactions.js"></script>
<style lang="scss">
@import "../../mixins";
.EmojiReactions { <style src="./emoji_reactions.scss" lang="scss" />
display: flex;
margin-top: 0.25em;
flex-wrap: wrap;
--emoji-size: calc(var(--emojiSize, 1.25em) * var(--emojiReactionsScale, 1));
.emoji-reaction-container {
display: flex;
align-items: stretch;
margin-top: 0.5em;
margin-right: 0.5em;
.emoji-reaction-popover {
padding: 0;
.emoji-reaction-count-button {
margin: 0;
height: 100%;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
box-sizing: border-box;
min-width: 2em;
display: inline-flex;
justify-content: center;
align-items: center;
}
}
}
.emoji-reaction {
padding-left: 0.5em;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
margin: 0;
.reaction-emoji {
width: var(--emoji-size);
height: var(--emoji-size);
margin-right: 0.25em;
line-height: var(--emoji-size);
display: flex;
justify-content: center;
align-items: center;
--_still_image-label-scale: 0.3;
}
.reaction-emoji-content {
max-width: 100%;
max-height: 100%;
width: var(--emoji-size);
height: var(--emoji-size);
line-height: inherit;
overflow: hidden;
font-size: calc(var(--emoji-size) * 0.8);
margin: 0;
img {
object-fit: contain;
}
}
&:focus {
outline: none;
}
.svg-inline--fa {
color: var(--text);
}
&.-picked-reaction {
.svg-inline--fa {
color: var(--accent);
}
}
@include unfocused-style {
.focus-marker {
visibility: hidden;
}
.active-marker {
visibility: visible;
}
}
@include focused-style {
.svg-inline--fa {
color: var(--accent);
}
.focus-marker {
visibility: visible;
}
.active-marker {
visibility: hidden;
}
}
}
.emoji-reaction-expand {
padding: 0 0.5em;
margin-right: 0.5em;
margin-top: 0.5em;
display: flex;
align-items: center;
justify-content: center;
&:hover {
text-decoration: underline;
}
}
}
</style>

View file

@ -117,9 +117,6 @@ const MentionLink = {
this.highlightType this.highlightType
] ]
}, },
useAtIcon () {
return this.mergedConfig.useAtIcon
},
isRemote () { isRemote () {
return this.userName !== this.userNameFull return this.userName !== this.userNameFull
}, },

View file

@ -34,12 +34,7 @@
:user="user" :user="user"
/><span /><span
class="shortName" class="shortName"
><FAIcon >@<span
v-if="useAtIcon"
size="sm"
icon="at"
class="at"
/>{{ !useAtIcon ? '@' : '' }}<span
class="userName" class="userName"
v-html="userName" v-html="userName"
/><span /><span

View file

@ -3,7 +3,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
faPen faPen
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
import { usePostStatusStore } from 'src/stores/postStatus' import { usePostStatusStore } from 'src/stores/post_status'
library.add( library.add(
faPen faPen

View file

@ -238,6 +238,4 @@
<script src="./mrf_transparency_panel.js"></script> <script src="./mrf_transparency_panel.js"></script>
<style lang="scss"> <style src="./mrf_transparency_panel.scss" lang="scss"/>
@import "./mrf_transparency_panel";
</style>

View file

@ -7,7 +7,8 @@
position: fixed; position: fixed;
min-width: 0; min-width: 0;
max-width: calc(100vw - 20px); max-width: calc(100vw - 20px);
box-shadow: var(--shadow);
--_shadow: var(--shadow);
} }
.popover-default { .popover-default {
@ -19,7 +20,7 @@
left: -1px; left: -1px;
right: -1px; right: -1px;
z-index: -1px; z-index: -1px;
box-shadow: var(--shadow); box-shadow: var(--_shadow);
pointer-events: none; pointer-events: none;
} }
@ -54,6 +55,7 @@
grid-template-columns: 1fr; grid-template-columns: 1fr;
grid-auto-flow: column; grid-auto-flow: column;
grid-auto-columns: auto; grid-auto-columns: auto;
grid-gap: 0.5em;
.popover-wrapper { .popover-wrapper {
box-sizing: border-box; box-sizing: border-box;

View file

@ -363,6 +363,12 @@ const PostStatusForm = {
} }
}, },
safeToSaveDraft () { safeToSaveDraft () {
console.log('safe', (
this.newStatus.status ||
this.newStatus.spoilerText ||
this.newStatus.files?.length ||
this.newStatus.hasPoll
) && this.saveable)
return ( return (
this.newStatus.status || this.newStatus.status ||
this.newStatus.spoilerText || this.newStatus.spoilerText ||

View file

@ -334,22 +334,26 @@
class="dropdown-menu" class="dropdown-menu"
role="menu" role="menu"
> >
<button <div
v-if="!hideDraft || !disableDraft"
class="menu-item dropdown-item" class="menu-item dropdown-item"
role="menu"
:disabled="!safeToSaveDraft && saveable"
:class="{ disabled: !safeToSaveDraft }" :class="{ disabled: !safeToSaveDraft }"
@click.prevent="saveDraft"
@click="close"
> >
<template v-if="closeable"> <button
{{ $t('post_status.save_to_drafts_and_close_button') }} v-if="!hideDraft || !disableDraft"
</template> class="main-button"
<template v-else> role="menu"
{{ $t('post_status.save_to_drafts_button') }} :disabled="!safeToSaveDraft"
</template> @click.prevent="saveDraft"
</button> @click="close"
>
<template v-if="closeable">
{{ $t('post_status.save_to_drafts_and_close_button') }}
</template>
<template v-else>
{{ $t('post_status.save_to_drafts_button') }}
</template>
</button>
</div>
</div> </div>
</template> </template>
</Popover> </Popover>

View file

@ -1,7 +1,7 @@
import PostStatusForm from '../post_status_form/post_status_form.vue' import PostStatusForm from '../post_status_form/post_status_form.vue'
import Modal from '../modal/modal.vue' import Modal from '../modal/modal.vue'
import get from 'lodash/get' import get from 'lodash/get'
import { usePostStatusStore } from 'src/stores/postStatus' import { usePostStatusStore } from 'src/stores/post_status'
const PostStatusModal = { const PostStatusModal = {
components: { components: {

View file

@ -2,6 +2,7 @@ export default {
name: 'RichContent', name: 'RichContent',
selector: '.RichContent', selector: '.RichContent',
notEditable: true, notEditable: true,
transparent: true,
validInnerComponents: [ validInnerComponents: [
'Text', 'Text',
'FunText', 'FunText',

View file

@ -2,27 +2,6 @@ export default {
name: 'Root', name: 'Root',
selector: ':root', selector: ':root',
notEditable: true, notEditable: true,
validInnerComponents: [
// These are purely for --parent--text et such to work
'Text',
'Link',
'Border',
'Underlay',
'Modals',
'Popover',
'TopBar',
'Scrollbar',
'ScrollbarElement',
'MobileDrawer',
'Alert',
'Button' // mobile post button
],
validInnerComponentsLite: [
'Underlay',
'Scrollbar',
'ScrollbarElement'
],
defaultRules: [ defaultRules: [
{ {
directives: { directives: {

View file

@ -7,7 +7,7 @@ import Checkbox from 'src/components/checkbox/checkbox.vue'
import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue' import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { cloneDeep, isEqual } from 'lodash' import { cloneDeep, isEqual } from 'lodash'
import { mapState as mapPiniaState } from 'pinia' import { mapState, mapActions } from 'pinia'
import { import {
newImporter, newImporter,
newExporter newExporter
@ -165,11 +165,12 @@ const SettingsModal = {
}, },
pushAdminDraft () { pushAdminDraft () {
this.$store.dispatch('pushAdminDraft') this.$store.dispatch('pushAdminDraft')
} },
...mapActions(useInterfaceStore, ['temporaryChangesRevert', 'temporaryChangesConfirm'])
}, },
computed: { computed: {
...mapPiniaState(useInterfaceStore, { ...mapState(useInterfaceStore, {
temporaryChangesTimeoutId: store => store.layoutType === 'mobile', temporaryChangesTimeoutId: store => store.temporaryChangesTimeoutId,
currentSaveStateNotice: store => store.settings.currentSaveStateNotice, currentSaveStateNotice: store => store.settings.currentSaveStateNotice,
modalActivated: store => store.settingsModalState !== 'hidden', modalActivated: store => store.settingsModalState !== 'hidden',
modalMode: store => store.settingsModalMode, modalMode: store => store.settingsModalMode,

View file

@ -162,8 +162,8 @@
:title="$t('settings.confirm_new_setting')" :title="$t('settings.confirm_new_setting')"
:cancel-text="$t('settings.revert')" :cancel-text="$t('settings.revert')"
:confirm-text="$t('settings.confirm')" :confirm-text="$t('settings.confirm')"
@cancelled="$store.state.interface.temporaryChangesRevert" @cancelled="temporaryChangesRevert"
@accepted="$store.state.interface.temporaryChangesConfirm" @accepted="temporaryChangesConfirm"
> >
{{ $t('settings.confirm_new_question') }} {{ $t('settings.confirm_new_question') }}
</ConfirmModal> </ConfirmModal>

View file

@ -269,14 +269,17 @@
{{ $t('settings.image_compression') }} {{ $t('settings.image_compression') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
<li> <ul class="setting-list suboptions">
<BooleanSetting <li>
path="alwaysUseJpeg" <BooleanSetting
expert="1" path="alwaysUseJpeg"
> expert="1"
{{ $t('settings.always_use_jpeg') }} parent-path="imageCompression"
</BooleanSetting> >
</li> {{ $t('settings.always_use_jpeg') }}
</BooleanSetting>
</li>
</ul>
<li> <li>
<BooleanSetting <BooleanSetting
path="useContainFit" path="useContainFit"
@ -362,14 +365,6 @@
{{ $t('settings.mention_link_use_tooltip') }} {{ $t('settings.mention_link_use_tooltip') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
<li>
<BooleanSetting
path="useAtIcon"
expert="1"
>
{{ $t('settings.use_at_icon') }}
</BooleanSetting>
</li>
<li> <li>
<BooleanSetting path="mentionLinkShowAvatar"> <BooleanSetting path="mentionLinkShowAvatar">
{{ $t('settings.mention_link_show_avatar') }} {{ $t('settings.mention_link_show_avatar') }}

View file

@ -65,7 +65,7 @@ export default {
'getClass', 'getClass',
'getComponent', 'getComponent',
'doAction', 'doAction',
'close' 'outerClose'
], ],
components: { components: {
StatusBookmarkFolderMenu, StatusBookmarkFolderMenu,

View file

@ -1,4 +1,4 @@
@import "../../mixins"; @use "../../mixins";
/* stylelint-disable declaration-no-important */ /* stylelint-disable declaration-no-important */
.quick-action { .quick-action {
@ -52,7 +52,7 @@
grid-auto-columns: max-content; grid-auto-columns: max-content;
align-items: center; align-items: center;
@include unfocused-style { @include mixins.unfocused-style {
.focus-marker { .focus-marker {
visibility: hidden; visibility: hidden;
} }
@ -62,7 +62,7 @@
} }
} }
@include focused-style { @include mixins.focused-style {
.focus-marker { .focus-marker {
visibility: visible; visibility: visible;
} }

View file

@ -14,7 +14,7 @@
:tabindex="0" :tabindex="0"
:disabled="buttonClass.disabled" :disabled="buttonClass.disabled"
:href="getComponent(button) == 'a' ? button.link?.(funcArg) || remoteInteractionLink : undefined" :href="getComponent(button) == 'a' ? button.link?.(funcArg) || remoteInteractionLink : undefined"
@click="doActionWrap(button, close)" @click="doActionWrap(button, outerClose)"
> >
<FALayers> <FALayers>
<FAIcon <FAIcon
@ -84,10 +84,11 @@
fixed-width fixed-width
/> />
</template> </template>
<template #content> <template #content="{close}">
<StatusBookmarkFolderMenu <StatusBookmarkFolderMenu
v-if="button.name === 'bookmark'" v-if="button.name === 'bookmark'"
:status="status" :status="status"
:close="() => { close(); outerClose() }"
/> />
</template> </template>
</Popover> </Popover>

View file

@ -1,3 +1,4 @@
import { useEditStatusStore } from 'src/stores/editStatus.js'
const PRIVATE_SCOPES = new Set(['private', 'direct']) const PRIVATE_SCOPES = new Set(['private', 'direct'])
const PUBLIC_SCOPES = new Set(['public', 'unlisted']) const PUBLIC_SCOPES = new Set(['public', 'unlisted'])
export const BUTTONS = [{ export const BUTTONS = [{
@ -111,9 +112,9 @@ export const BUTTONS = [{
}, },
action ({ status, dispatch }) { action ({ status, dispatch }) {
if (status.pinned) { if (status.pinned) {
return dispatch('unpinStatus', { id: status.id }) return dispatch('unpinStatus', status.id)
} else { } else {
return dispatch('pinStatus', { id: status.id }) return dispatch('pinStatus', status.id)
} }
} }
}, { }, {
@ -151,7 +152,7 @@ export const BUTTONS = [{
}, },
action ({ dispatch, status }) { action ({ dispatch, status }) {
return dispatch('fetchStatusSource', { id: status.id }) return dispatch('fetchStatusSource', { id: status.id })
.then(data => dispatch('openEditStatusModal', { .then(data => useEditStatusStore().openEditStatusModal({
statusId: status.id, statusId: status.id,
subject: data.spoiler_text, subject: data.spoiler_text,
statusText: data.text, statusText: data.text,

View file

@ -1,4 +1,4 @@
@import "../../mixins"; @use "../../mixins";
.StatusActionButtons { .StatusActionButtons {
.quick-action-buttons { .quick-action-buttons {

View file

@ -86,7 +86,7 @@
:func-arg="funcArg" :func-arg="funcArg"
:get-class="getClass" :get-class="getClass"
:get-component="getComponent" :get-component="getComponent"
:close="close" :outerClose="close"
:do-action="doAction" :do-action="doAction"
/> />
<button <button

View file

@ -2,19 +2,22 @@ import { library } from '@fortawesome/fontawesome-svg-core'
import { faChevronRight, faFolder } from '@fortawesome/free-solid-svg-icons' import { faChevronRight, faFolder } from '@fortawesome/free-solid-svg-icons'
import { mapState } from 'vuex' import { mapState } from 'vuex'
import Popover from '../popover/popover.vue' import Popover from 'src/components/popover/popover.vue'
import StillImage from 'src/components/still-image/still-image.vue'
library.add(faChevronRight, faFolder) library.add(faChevronRight, faFolder)
const StatusBookmarkFolderMenu = { const StatusBookmarkFolderMenu = {
props: [ props: [
'status' 'status',
'close'
], ],
data () { data () {
return {} return {}
}, },
components: { components: {
Popover Popover,
StillImage
}, },
computed: { computed: {
...mapState({ ...mapState({

View file

@ -0,0 +1,9 @@
.bookmark-folder-menu {
--__horizontal-gap: 0.5em;
--_still-image-label-visibility: hidden;
.emoji {
width: var(--__line-height);
height: var(--__line-height);
}
}

View file

@ -1,22 +1,25 @@
<template> <template>
<div class="dropdown-menu"> <div class="dropdown-menu bookmark-folder-menu">
<div <div
v-for="folder in folders" v-for="folder in folders"
:key="folder.id" :key="folder.id"
class="menu-item dropdown-item -icon" class="menu-item dropdown-item -icon-double"
> >
<button <button
class="main-button" class="main-button"
@click="toggleFolder(folder.id)" @click="toggleFolder(folder.id)"
@click.stop="close"
> >
<span <span
class="input menu-checkbox -radio" class="input menu-checkbox -radio"
:class="{ 'menu-checkbox-checked': status.bookmark_folder_id == folder.id }" :class="{ 'menu-checkbox-checked': status.bookmark_folder_id == folder.id }"
/> />
{{ folder.name }} <StillImage :src="folder.emoji_url" class="emoji" />
{{ ' ' + folder.name }}
</button> </button>
</div> </div>
</div> </div>
</template> </template>
<script src="./status_bookmark_folder_menu.js"></script> <script src="./status_bookmark_folder_menu.js"></script>
<stlye src="./status_bookmark_folder_menu.scss" />

View file

@ -11,7 +11,7 @@ import RichContent from 'src/components/rich_content/rich_content.jsx'
import MuteConfirm from '../confirm_modal/mute_confirm.vue' import MuteConfirm from '../confirm_modal/mute_confirm.vue'
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'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import { usePostStatusStore } from 'src/stores/postStatus' import { usePostStatusStore } from 'src/stores/post_status'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
faBell, faBell,

View file

@ -129,7 +129,6 @@ export const defaultState = {
forcedRoundness: undefined, // instance default forcedRoundness: undefined, // instance default
navbarColumnStretch: false, navbarColumnStretch: false,
greentext: undefined, // instance default greentext: undefined, // instance default
useAtIcon: undefined, // instance default
mentionLinkDisplay: undefined, // instance default mentionLinkDisplay: undefined, // instance default
mentionLinkShowTooltip: undefined, // instance default mentionLinkShowTooltip: undefined, // instance default
mentionLinkShowAvatar: undefined, // instance default mentionLinkShowAvatar: undefined, // instance default

View file

@ -57,7 +57,6 @@ const defaultState = {
embeddedToS: true, embeddedToS: true,
collapseMessageWithSubject: false, collapseMessageWithSubject: false,
greentext: false, greentext: false,
useAtIcon: false,
mentionLinkDisplay: 'short', mentionLinkDisplay: 'short',
mentionLinkShowTooltip: true, mentionLinkShowTooltip: true,
mentionLinkShowAvatar: false, mentionLinkShowAvatar: false,

View file

@ -2,6 +2,7 @@
.panel { .panel {
--__panel-background: var(--background); --__panel-background: var(--background);
--__panel-backdrop-filter: var(--backdrop-filter); --__panel-backdrop-filter: var(--backdrop-filter);
--_shadow: var(--shadow);
.tab-switcher .tabs { .tab-switcher .tabs {
background: var(--__panel-background); background: var(--__panel-background);
@ -29,7 +30,7 @@
left: 0; left: 0;
right: 0; right: 0;
z-index: 5; z-index: 5;
box-shadow: var(--shadow); box-shadow: var(--_shadow);
pointer-events: none; pointer-events: none;
} }
} }
@ -154,11 +155,13 @@
linear-gradient(to bottom, var(--background), var(--background)), linear-gradient(to bottom, var(--background), var(--background)),
linear-gradient(to bottom, var(--__panel-background), var(--__panel-background)); linear-gradient(to bottom, var(--__panel-background), var(--__panel-background));
--_shadow: var(--shadow);
&::after { &::after {
background-color: var(--background); background-color: var(--background);
z-index: -2; z-index: -2;
border-radius: var(--roundness) var(--roundness) 0 0; border-radius: var(--roundness) var(--roundness) 0 0;
box-shadow: var(--shadow); box-shadow: var(--_shadow);
} }
&:not(.-flexible-height) { &:not(.-flexible-height) {

View file

@ -2,11 +2,8 @@ import { init, getEngineChecksum } from '../theme_data/theme_data_3.service.js'
import { getCssRules } from '../theme_data/css_utils.js' import { getCssRules } from '../theme_data/css_utils.js'
import { defaultState } from 'src/modules/default_config_state.js' import { defaultState } from 'src/modules/default_config_state.js'
import { chunk } from 'lodash' import { chunk } from 'lodash'
import pako from 'pako'
import localforage from 'localforage' import localforage from 'localforage'
console.log('CONFIG', defaultState)
// On platforms where this is not supported, it will return undefined // On platforms where this is not supported, it will return undefined
// Otherwise it will return an array // Otherwise it will return an array
const supportsAdoptedStyleSheets = !!document.adoptedStyleSheets const supportsAdoptedStyleSheets = !!document.adoptedStyleSheets
@ -93,32 +90,28 @@ export const generateTheme = (inputRuleset, callbacks, debug) => {
export const tryLoadCache = async () => { export const tryLoadCache = async () => {
console.info('Trying to load compiled theme data from cache') console.info('Trying to load compiled theme data from cache')
const data = await localforage.getItem('pleromafe-theme-cache') const cache = await localforage.getItem('pleromafe-theme-cache')
if (!data) return null if (!cache) return null
let cache
try { try {
const inflated = pako.inflate(data) if (cache.engineChecksum === getEngineChecksum()) {
const decoded = new TextDecoder().decode(inflated) const eagerStyles = createStyleSheet(EAGER_STYLE_ID)
cache = JSON.parse(decoded) const lazyStyles = createStyleSheet(LAZY_STYLE_ID)
console.info(`Loaded theme from cache, compressed=${Math.ceil(data.length / 1024)}kiB size=${Math.ceil(inflated.length / 1024)}kiB`)
cache.data[0].forEach(rule => eagerStyles.sheet.insertRule(rule, 'index-max'))
cache.data[1].forEach(rule => lazyStyles.sheet.insertRule(rule, 'index-max'))
adoptStyleSheets([eagerStyles, lazyStyles])
console.info(`Loaded theme from cache`)
return true
} else {
console.warn('Engine checksum doesn\'t match, cache not usable, clearing')
localStorage.removeItem('pleroma-fe-theme-cache')
}
} catch (e) { } catch (e) {
console.error('Failed to decode theme cache:', e) console.error('Failed to load theme cache:', e)
return false return false
} }
if (cache.engineChecksum === getEngineChecksum()) {
const eagerStyles = createStyleSheet(EAGER_STYLE_ID)
const lazyStyles = createStyleSheet(LAZY_STYLE_ID)
cache.data[0].forEach(rule => eagerStyles.sheet.insertRule(rule, 'index-max'))
cache.data[1].forEach(rule => lazyStyles.sheet.insertRule(rule, 'index-max'))
adoptStyleSheets([eagerStyles, lazyStyles])
return true
} else {
console.warn('Engine checksum doesn\'t match, cache not usable, clearing')
localStorage.removeItem('pleroma-fe-theme-cache')
}
} }
export const applyTheme = ( export const applyTheme = (
@ -157,15 +150,14 @@ export const applyTheme = (
onEagerFinished () { onEagerFinished () {
adoptStyleSheets([eagerStyles]) adoptStyleSheets([eagerStyles])
onEagerFinish() onEagerFinish()
console.info('Eager part of theme finished, waiting for lazy part to finish to store cache')
}, },
onLazyFinished () { onLazyFinished () {
adoptStyleSheets([eagerStyles, lazyStyles]) adoptStyleSheets([eagerStyles, lazyStyles])
const cache = { engineChecksum: getEngineChecksum(), data: [eagerStyles.rules, lazyStyles.rules] } const cache = { engineChecksum: getEngineChecksum(), data: [eagerStyles.rules, lazyStyles.rules] }
onFinish(cache) onFinish(cache)
const compress = (js) => { localforage.setItem('pleromafe-theme-cache', cache)
return pako.deflate(JSON.stringify(js)) console.info('Theme cache stored')
}
localforage.setItem('pleromafe-theme-cache', compress(cache))
} }
}, },
debug debug
@ -214,7 +206,6 @@ const extractStyleConfig = ({
return result return result
} }
console.log(defaultState)
const defaultStyleConfig = extractStyleConfig(defaultState) const defaultStyleConfig = extractStyleConfig(defaultState)
export const applyConfig = (input) => { export const applyConfig = (input) => {

View file

@ -1,2 +0,0 @@
export const sampleRules = [
]

View file

@ -32,9 +32,12 @@ const components = {
Link: null, Link: null,
Icon: null, Icon: null,
Border: null, Border: null,
PanelHeader: null,
Attachment: null,
Panel: null, Panel: null,
Chat: null, Chat: null,
ChatMessage: null ChatMessage: null,
Button: null
} }
export const findShadow = (shadows, { dynamicVars, staticVars }) => { export const findShadow = (shadows, { dynamicVars, staticVars }) => {
@ -152,6 +155,25 @@ componentsContext.keys().forEach(key => {
components[component.name] = component components[component.name] = component
}) })
Object.keys(components).forEach(key => {
if (key === 'Root') return
components.Root.validInnerComponents = components.Root.validInnerComponents || []
components.Root.validInnerComponents.push(key)
})
Object.keys(components).forEach(key => {
const component = components[key]
const { validInnerComponents = [] } = component
validInnerComponents.forEach(inner => {
const child = components[inner]
component.possibleChildren = component.possibleChildren || []
component.possibleChildren.push(child)
child.possibleParents = child.possibleParents || []
child.possibleParents.push(component)
})
})
const engineChecksum = sum(components) const engineChecksum = sum(components)
const ruleToSelector = genericRuleToSelector(components) const ruleToSelector = genericRuleToSelector(components)
@ -244,7 +266,21 @@ export const init = ({
} }
const virtualComponents = new Set(Object.values(components).filter(c => c.virtual).map(c => c.name)) const virtualComponents = new Set(Object.values(components).filter(c => c.virtual).map(c => c.name))
const transparentComponents = new Set(Object.values(components).filter(c => c.transparent).map(c => c.name))
const nonEditableComponents = new Set(Object.values(components).filter(c => c.notEditable).map(c => c.name)) const nonEditableComponents = new Set(Object.values(components).filter(c => c.notEditable).map(c => c.name))
const extraCompileComponents = new Set([])
Object.values(components).forEach(component => {
const relevantRules = ruleset.filter(r => r.component === component.name)
const backgrounds = relevantRules.map(r => r.directives.background).filter(x => x)
const opacities = relevantRules.map(r => r.directives.opacity).filter(x => x)
if (
backgrounds.some(x => x.match(/--parent/)) ||
opacities.some(x => x != null && x < 1))
{
extraCompileComponents.add(component.name)
}
})
const processCombination = (combination) => { const processCombination = (combination) => {
try { try {
@ -473,11 +509,21 @@ export const init = ({
let validInnerComponents let validInnerComponents
if (editMode) { if (editMode) {
const temp = (component.validInnerComponentsLite || component.validInnerComponents || []) const temp = (component.validInnerComponentsLite || component.validInnerComponents || [])
validInnerComponents = temp.filter(c => virtualComponents.has(c) && !nonEditableComponents.has(c)) validInnerComponents = temp
.filter(c => virtualComponents.has(c) && !nonEditableComponents.has(c))
} else if (liteMode) { } else if (liteMode) {
validInnerComponents = (component.validInnerComponentsLite || component.validInnerComponents || []) validInnerComponents = (component.validInnerComponentsLite || component.validInnerComponents || [])
} else { } else if (component.name === 'Root') {
validInnerComponents = component.validInnerComponents || [] validInnerComponents = component.validInnerComponents || []
} else {
validInnerComponents = component
.validInnerComponents
?.filter(
c => virtualComponents.has(c)
|| transparentComponents.has(c)
|| extraCompileComponents.has(c)
)
|| []
} }
// Normalizing states and variants to always include "normal" // Normalizing states and variants to always include "normal"
@ -491,7 +537,7 @@ export const init = ({
// Optimization: we only really need combinations without "normal" because all states implicitly have it // Optimization: we only really need combinations without "normal" because all states implicitly have it
const permutationStateKeys = Object.keys(states).filter(s => s !== 'normal') const permutationStateKeys = Object.keys(states).filter(s => s !== 'normal')
const stateCombinations = onlyNormalState const stateCombinations = (onlyNormalState && !virtualComponents.has(component.name))
? [ ? [
['normal'] ['normal']
] ]
@ -524,6 +570,16 @@ export const init = ({
combination.lazy = true combination.lazy = true
} }
if (
!liteMode &&
parent?.component !== 'Root' &&
!virtualComponents.has(component.name) &&
!transparentComponents.has(component.name) &&
extraCompileComponents.has(component.name)
) {
combination.lazy = true
}
combinations.push(combination) combinations.push(combination)
innerComponents.forEach(innerComponent => { innerComponents.forEach(innerComponent => {

View file

@ -12,6 +12,9 @@ export const usePostStatusStore = defineStore('postStatus', {
}, },
closePostStatusModal () { closePostStatusModal () {
this.modalActivated = false this.modalActivated = false
},
resetPostStatusModal () {
this.params = null
} }
} }
}) })

View file

@ -167,3 +167,12 @@ Tab:hover:active {
TopBar Link { TopBar Link {
textColor: #ffffff textColor: #ffffff
} }
MenuItem:hover {
background: --fg
}
Popover {
shadow: --buttonDefaultBevel, 5 5 0 0 #000000 / 0.2;
roundness: 0
}

View file

@ -1,4 +1,3 @@
// import { topoSort } from 'src/services/theme_data/theme_data.service.js'
import { import {
getAllPossibleCombinations getAllPossibleCombinations
} from 'src/services/theme_data/iss_utils.js' } from 'src/services/theme_data/iss_utils.js'
@ -120,6 +119,7 @@ describe('Theme Data 3', () => {
opacity: 0.5 opacity: 0.5
} }
}], }],
onlyNormalState: true,
ultimateBackgroundColor: '#DEADAF' ultimateBackgroundColor: '#DEADAF'
}) })
@ -142,9 +142,9 @@ describe('Theme Data 3', () => {
*/ */
expect(panelRule).to.have.nested.deep.property('dynamicVars.stacked.r').that.is.closeTo(88.8, 0.01) expect(panelRule).to.have.nested.deep.property('dynamicVars.stacked.r').that.is.closeTo(111, 0.01)
expect(panelRule).to.have.nested.deep.property('dynamicVars.stacked.g').that.is.closeTo(133.2, 0.01) expect(panelRule).to.have.nested.deep.property('dynamicVars.stacked.g').that.is.closeTo(150.5, 0.01)
expect(panelRule).to.have.nested.deep.property('dynamicVars.stacked.b').that.is.closeTo(134, 0.01) expect(panelRule).to.have.nested.deep.property('dynamicVars.stacked.b').that.is.closeTo(151.5, 0.01)
}) })
}) })
}) })

View file

@ -6614,11 +6614,6 @@ package-json-from-dist@^1.0.0:
resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505"
integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==
pako@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86"
integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==
pako@~1.0.2: pako@~1.0.2:
version "1.0.11" version "1.0.11"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"