Merge remote-tracking branch 'origin/develop' into shigusegubu

* origin/develop:
  changelong
  Fix pinned statuses and perhaps some other stuff
  update changelog
  Remove title from index.html, title is now from server generated meta
  changelog mention
  fix emoji not working in profile field names
  change method of fix to rounding
  changelog
  prevent call to scroll if the value doesn't change because firefox is stupid
  Update CHANGELOG.md
  wrap react button icon to a span to fix popover overflow
  Update CHANGELOG.md to match master
  change favicon dimensions for high res, add handling when favicon isn't available
  remove the favicon changes
  make badge just a ball, make it use theming
  add favicon badge for unread notifs
shigusegubu
Henry Jameson 2 years ago
commit d8ac75f58a
  1. 26
      CHANGELOG.md
  2. 1
      index.html
  3. 3
      src/boot/after_store.js
  4. 3
      src/components/notifications/notifications.js
  5. 2
      src/components/post_status_form/post_status_form.js
  6. 14
      src/components/react_button/react_button.vue
  7. 7
      src/components/user_profile/user_profile.vue
  8. 6
      src/modules/users.js
  9. 14
      src/services/entity_normalizer/entity_normalizer.service.js
  10. 61
      src/services/favicon_service/favicon_service.js

@ -3,17 +3,29 @@ 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/).
## [Unreleased]
### Fixed
- Fixed the occasional bug where screen would scroll 1px when typing into a reply form
- Fixed custom emoji not working in profile field names
- Fixed pinned statuses not appearing in user profiles
## [2.2.1] - 2020-11-11
### Fixed
- Fixed regression in react popup alignment and overflowing
## [2.2.0] - 2020-11-06
### Added
- New option to optimize timeline rendering to make the site more responsive (enabled by default)
- New instance option `logoLeft` to move logo to the left side in desktop nav bar
- Import/export a muted users
- Proper handling of deletes when using websocket streaming
- Added optimistic chat message sending, so you can start writing next message before the previous one has been sent
- Added a small red badge to the favicon when there's unread notifications
### Fixed
- Fixed chats list not updating its order when new messages come in
- Fixed chat messages sometimes getting lost when you receive a message at the same time
- Fixed clicking NSFW hider through status popover
- Fixed chat-view back button being hard to click
- Fixed fresh chat notifications being cleared immediately while leaving the chat view and not having time to actually see the messages
@ -29,6 +41,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Logo is now clickable
- Changed default logo to SVG version
## [2.1.2] - 2020-09-17
### Fixed
- Fixed chats list not updating its order when new messages come in
- Fixed chat messages sometimes getting lost when you receive a message at the same time
## [2.1.1] - 2020-09-08
### Changed
- Polls will be hidden with status content if "Collapse posts with subjects" is enabled and the post is collapsed.
@ -154,8 +173,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Ability to change user's email
- About page
- Added remote user redirect
- Bookmarks
### Changed
- changed the way fading effects for user profile/long statuses works, now uses css-mask instead of gradient background hacks which weren't exactly compatible with semi-transparent themes
### Fixed
- improved hotkey behavior on autocomplete popup

@ -3,7 +3,6 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1,user-scalable=no">
<title>Pleroma</title>
<link rel="apple-touch-icon" sizes="180x180" href="/ngs/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/ngs/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/ngs/favicon-16x16.png">

@ -7,6 +7,7 @@ import { getOrCreateApp, getClientToken } from '../services/new_api/oauth.js'
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js'
import { applyTheme } from '../services/style_setter/style_setter.js'
import FaviconService from '../services/favicon_service/favicon_service.js'
let staticInitialResults = null
@ -326,6 +327,8 @@ const afterStoreSetup = async ({ store, i18n }) => {
const width = windowWidth()
store.dispatch('setMobileLayout', width <= 800)
FaviconService.initFaviconService()
const overrides = window.___pleromafe_dev_overrides || {}
const server = (typeof overrides.target !== 'undefined') ? overrides.target : window.location.origin
store.dispatch('setInstanceOption', { name: 'server', value: server })

@ -6,6 +6,7 @@ import {
filteredNotificationsFromStore,
unseenNotificationsFromStore
} from '../../services/notification_utils/notification_utils.js'
import FaviconService from '../../services/favicon_service/favicon_service.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
@ -75,8 +76,10 @@ const Notifications = {
watch: {
unseenCountTitle (count) {
if (count > 0) {
FaviconService.drawFaviconBadge()
this.$store.dispatch('setPageTitle', `(${count})`)
} else {
FaviconService.clearFaviconBadge()
this.$store.dispatch('setPageTitle', '')
}
}

@ -531,7 +531,7 @@ const PostStatusForm = {
!(isFormBiggerThanScroller &&
this.$refs.textarea.selectionStart !== this.$refs.textarea.value.length)
const totalDelta = shouldScrollToBottom ? bottomChangeDelta : 0
const targetScroll = currentScroll + totalDelta
const targetScroll = Math.round(currentScroll + totalDelta)
if (scrollerRef === window) {
scrollerRef.scroll(0, targetScroll)

@ -4,6 +4,7 @@
placement="top"
:offset="{ y: 5 }"
class="react-button-popover"
:bound-to="{ x: 'container' }"
>
<div
slot="content"
@ -37,12 +38,13 @@
<div class="reaction-bottom-fader" />
</div>
</div>
<FAIcon
slot="trigger"
class="fa-scale-110 fa-old-padding add-reaction-button"
:icon="['far', 'smile-beam']"
:title="$t('tool_tip.add_reaction')"
/>
<span slot="trigger">
<FAIcon
class="fa-scale-110 fa-old-padding add-reaction-button"
:icon="['far', 'smile-beam']"
:title="$t('tool_tip.add_reaction')"
/>
</span>
</Popover>
</template>

@ -20,14 +20,13 @@
:key="index"
class="user-profile-field"
>
<!-- eslint-disable vue/no-v-html -->
<dt
:title="user.fields_text[index].name"
class="user-profile-field-name"
@click.prevent="linkClicked"
>
{{ field.name }}
</dt>
<!-- eslint-disable vue/no-v-html -->
v-html="field.name"
/>
<dd
:title="user.fields_text[index].value"
class="user-profile-field-value"

@ -137,11 +137,11 @@ export const mutations = {
},
saveFriendIds (state, { id, friendIds }) {
const user = state.usersObject[id]
user.friendIds = uniq(concat(user.friendIds, friendIds))
user.friendIds = uniq(concat(user.friendIds || [], friendIds))
},
saveFollowerIds (state, { id, followerIds }) {
const user = state.usersObject[id]
user.followerIds = uniq(concat(user.followerIds, followerIds))
user.followerIds = uniq(concat(user.followerIds || [], followerIds))
},
// Because frontend doesn't have a reason to keep these stuff in memory
// outside of viewing someones user profile.
@ -202,7 +202,9 @@ export const mutations = {
},
setPinnedToUser (state, status) {
const user = state.usersObject[status.user.id]
user.pinnedStatusIds = user.pinnedStatusIds || []
const index = user.pinnedStatusIds.indexOf(status.id)
if (status.pinned && index === -1) {
user.pinnedStatusIds.push(status.id)
} else if (!status.pinned && index !== -1) {

@ -2,6 +2,15 @@ import escape from 'escape-html'
import parseLinkHeader from 'parse-link-header'
import { isStatusNotification } from '../notification_utils/notification_utils.js'
/** NOTICE! **
* Do not initialize UI-generated data here.
* It will override existing data.
*
* i.e. user.pinnedStatusIds was set to [] here
* UI code would update it with data but upon next user fetch
* it would be reverted back to []
*/
const qvitterStatusType = (status) => {
if (status.is_post_verb) {
return 'status'
@ -53,7 +62,7 @@ export const parseUser = (data) => {
output.fields = data.fields
output.fields_html = data.fields.map(field => {
return {
name: addEmojis(field.name, data.emojis),
name: addEmojis(escape(field.name), data.emojis),
value: addEmojis(field.value, data.emojis)
}
})
@ -173,9 +182,6 @@ export const parseUser = (data) => {
output.locked = data.locked
output.followers_count = data.followers_count
output.statuses_count = data.statuses_count
output.friendIds = []
output.followerIds = []
output.pinnedStatusIds = []
if (data.pleroma) {
output.follow_request_count = data.pleroma.follow_request_count

@ -0,0 +1,61 @@
import { find } from 'lodash'
const createFaviconService = () => {
let favimg, favcanvas, favcontext, favicon
const faviconWidth = 128
const faviconHeight = 128
const badgeRadius = 32
const initFaviconService = () => {
const nodes = document.getElementsByTagName('link')
favicon = find(nodes, node => node.rel === 'icon')
if (favicon) {
favcanvas = document.createElement('canvas')
favcanvas.width = faviconWidth
favcanvas.height = faviconHeight
favimg = new Image()
favimg.src = favicon.href
favcontext = favcanvas.getContext('2d')
}
}
const isImageLoaded = (img) => img.complete && img.naturalHeight !== 0
const clearFaviconBadge = () => {
if (!favimg || !favcontext || !favicon) return
favcontext.clearRect(0, 0, faviconWidth, faviconHeight)
if (isImageLoaded(favimg)) {
favcontext.drawImage(favimg, 0, 0, favimg.width, favimg.height, 0, 0, faviconWidth, faviconHeight)
}
favicon.href = favcanvas.toDataURL('image/png')
}
const drawFaviconBadge = () => {
if (!favimg || !favcontext || !favcontext) return
clearFaviconBadge()
const style = getComputedStyle(document.body)
const badgeColor = `${style.getPropertyValue('--badgeNotification') || 'rgb(240, 100, 100)'}`
if (isImageLoaded(favimg)) {
favcontext.drawImage(favimg, 0, 0, favimg.width, favimg.height, 0, 0, faviconWidth, faviconHeight)
}
favcontext.fillStyle = badgeColor
favcontext.beginPath()
favcontext.arc(faviconWidth - badgeRadius, badgeRadius, badgeRadius, 0, 2 * Math.PI, false)
favcontext.fill()
favicon.href = favcanvas.toDataURL('image/png')
}
return {
initFaviconService,
clearFaviconBadge,
drawFaviconBadge
}
}
const FaviconService = createFaviconService()
export default FaviconService
Loading…
Cancel
Save