diff --git a/BREAKING_CHANGES.md b/BREAKING_CHANGES.md new file mode 100644 index 00000000..924c38da --- /dev/null +++ b/BREAKING_CHANGES.md @@ -0,0 +1,10 @@ +# v1.0 +## Removed features/radically changed behavior +### minimalScopesMode +As of !633, `scopeOptions` is no longer available and instead is changed for `minimalScopesMode` (default: `false`) + +Reasoning is that scopeOptions option originally existed mostly as a backwards-compatibility with GNU Social which only had `public` scope available and using scope selector would''t work. Since at some point we dropped GNU Social support, this option was mostly a nuisance (being default `false`'), however some people think scopes are an annoyance to a certain degree and want as less of that feature as possible. + +Solution - to only show minimal set among: *Direct*, *User default* and *Scope of post replying to*. This also makes it impossible to reply to a DM with a non-DM post from UI. + +*This setting is admin-default, user-configurable. Admin can choose different default for their instance but user can override it.* diff --git a/README.md b/README.md index 80938c45..889f0837 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ FE Build process also leaves current commit hash in global variable `___pleromaf # Configuration -Edit config.json for configuration. scopeOptionsEnabled gives you input fields for CWs and the scope settings. +Edit config.json for configuration. ## Options diff --git a/src/App.scss b/src/App.scss index dcc913d6..5fc0dd27 100644 --- a/src/App.scss +++ b/src/App.scss @@ -735,3 +735,54 @@ nav { .btn.btn-default { min-height: 28px; } + +.autocomplete { + &-panel { + position: relative; + + &-body { + margin: 0 0.5em 0 0.5em; + border-radius: $fallback--tooltipRadius; + border-radius: var(--tooltipRadius, $fallback--tooltipRadius); + position: absolute; + z-index: 1; + box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.5); + // this doesn't match original but i don't care, making it uniform. + box-shadow: var(--popupShadow); + min-width: 75%; + background: $fallback--bg; + background: var(--bg, $fallback--bg); + color: $fallback--lightText; + color: var(--lightText, $fallback--lightText); + } + } + + &-item { + cursor: pointer; + padding: 0.2em 0.4em 0.2em 0.4em; + border-bottom: 1px solid rgba(0, 0, 0, 0.4); + display: flex; + + img { + width: 24px; + height: 24px; + object-fit: contain; + } + + span { + line-height: 24px; + margin: 0 0.1em 0 0.2em; + } + + small { + margin-left: .5em; + color: $fallback--faint; + color: var(--faint, $fallback--faint); + } + + &.highlighted { + background-color: $fallback--fg; + background-color: var(--lightBg, $fallback--fg); + } + } +} \ No newline at end of file diff --git a/src/boot/after_store.js b/src/boot/after_store.js index e03b7f27..66169546 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -95,7 +95,7 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => { copyInstanceOption('redirectRootNoLogin') copyInstanceOption('redirectRootLogin') copyInstanceOption('showInstanceSpecificPanel') - copyInstanceOption('scopeOptionsEnabled') + copyInstanceOption('minimalScopesMode') copyInstanceOption('formattingOptionsEnabled') copyInstanceOption('hideMutedPosts') copyInstanceOption('collapseMessageWithSubject') diff --git a/src/components/emoji-input/emoji-input.js b/src/components/emoji-input/emoji-input.js new file mode 100644 index 00000000..a5bb6eaf --- /dev/null +++ b/src/components/emoji-input/emoji-input.js @@ -0,0 +1,107 @@ +import Completion from '../../services/completion/completion.js' +import { take, filter, map } from 'lodash' + +const EmojiInput = { + props: [ + 'value', + 'placeholder', + 'type', + 'classname' + ], + data () { + return { + highlighted: 0, + caret: 0 + } + }, + computed: { + suggestions () { + const firstchar = this.textAtCaret.charAt(0) + if (firstchar === ':') { + if (this.textAtCaret === ':') { return } + const matchedEmoji = filter(this.emoji.concat(this.customEmoji), (emoji) => emoji.shortcode.startsWith(this.textAtCaret.slice(1))) + if (matchedEmoji.length <= 0) { + return false + } + return map(take(matchedEmoji, 5), ({shortcode, image_url, utf}, index) => ({ + shortcode: `:${shortcode}:`, + utf: utf || '', + // eslint-disable-next-line camelcase + img: utf ? '' : this.$store.state.instance.server + image_url, + highlighted: index === this.highlighted + })) + } else { + return false + } + }, + textAtCaret () { + return (this.wordAtCaret || {}).word || '' + }, + wordAtCaret () { + const word = Completion.wordAtPosition(this.value, this.caret - 1) || {} + return word + }, + emoji () { + return this.$store.state.instance.emoji || [] + }, + customEmoji () { + return this.$store.state.instance.customEmoji || [] + } + }, + methods: { + replace (replacement) { + const newValue = Completion.replaceWord(this.value, this.wordAtCaret, replacement) + this.$emit('input', newValue) + this.caret = 0 + }, + replaceEmoji (e) { + const len = this.suggestions.length || 0 + if (this.textAtCaret === ':' || e.ctrlKey) { return } + if (len > 0) { + e.preventDefault() + const emoji = this.suggestions[this.highlighted] + const replacement = emoji.utf || (emoji.shortcode + ' ') + const newValue = Completion.replaceWord(this.value, this.wordAtCaret, replacement) + this.$emit('input', newValue) + this.caret = 0 + this.highlighted = 0 + } + }, + cycleBackward (e) { + const len = this.suggestions.length || 0 + if (len > 0) { + e.preventDefault() + this.highlighted -= 1 + if (this.highlighted < 0) { + this.highlighted = this.suggestions.length - 1 + } + } else { + this.highlighted = 0 + } + }, + cycleForward (e) { + const len = this.suggestions.length || 0 + if (len > 0) { + if (e.shiftKey) { return } + e.preventDefault() + this.highlighted += 1 + if (this.highlighted >= len) { + this.highlighted = 0 + } + } else { + this.highlighted = 0 + } + }, + onKeydown (e) { + e.stopPropagation() + }, + onInput (e) { + this.$emit('input', e.target.value) + }, + setCaret ({target: {selectionStart}}) { + this.caret = selectionStart + } + } +} + +export default EmojiInput diff --git a/src/components/emoji-input/emoji-input.vue b/src/components/emoji-input/emoji-input.vue new file mode 100644 index 00000000..338b77cd --- /dev/null +++ b/src/components/emoji-input/emoji-input.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/src/components/features_panel/features_panel.js b/src/components/features_panel/features_panel.js index e0b7a118..5f0b7b25 100644 --- a/src/components/features_panel/features_panel.js +++ b/src/components/features_panel/features_panel.js @@ -6,7 +6,7 @@ const FeaturesPanel = { gopher: function () { return this.$store.state.instance.gopherAvailable }, whoToFollow: function () { return this.$store.state.instance.suggestionsEnabled }, mediaProxy: function () { return this.$store.state.instance.mediaProxyAvailable }, - scopeOptions: function () { return this.$store.state.instance.scopeOptionsEnabled }, + minimalScopesMode: function () { return this.$store.state.instance.minimalScopesMode }, textlimit: function () { return this.$store.state.instance.textlimit } } } diff --git a/src/components/features_panel/features_panel.vue b/src/components/features_panel/features_panel.vue index 445143e9..7a263e01 100644 --- a/src/components/features_panel/features_panel.vue +++ b/src/components/features_panel/features_panel.vue @@ -12,7 +12,7 @@
  • {{$t('features_panel.gopher')}}
  • {{$t('features_panel.who_to_follow')}}
  • {{$t('features_panel.media_proxy')}}
  • -
  • {{$t('features_panel.scope_options')}}
  • +
  • {{$t('features_panel.scope_options')}}
  • {{$t('features_panel.text_limit')}} = {{textlimit}}
  • diff --git a/src/components/notification/notification.js b/src/components/notification/notification.js index fe5b7018..42a48f3f 100644 --- a/src/components/notification/notification.js +++ b/src/components/notification/notification.js @@ -31,6 +31,15 @@ const Notification = { const highlight = this.$store.state.config.highlight const user = this.notification.action.user return highlightStyle(highlight[user.screen_name]) + }, + userInStore () { + return this.$store.getters.findUser(this.notification.action.user.id) + }, + user () { + if (this.userInStore) { + return this.userInStore + } + return {} } } } diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue index 5e9cef97..8f532747 100644 --- a/src/components/notification/notification.vue +++ b/src/components/notification/notification.vue @@ -1,11 +1,11 @@