From 567894f614dae6d5dd3e13607635fbb5242c5973 Mon Sep 17 00:00:00 2001 From: mgabdev <> Date: Wed, 4 Mar 2020 17:26:01 -0500 Subject: [PATCH] Progress --- .../gabsocial/actions/interactions.js | 106 ++++----- app/javascript/gabsocial/actions/timelines.js | 38 ++-- .../gabsocial/components/media_item.js | 132 +++++++++++ .../gabsocial/components/modal/boost_modal.js | 8 +- .../components/modal/hotkeys_modal.js | 8 +- .../components/panel/profile_stats_panel.js | 2 +- .../popover/status_options_popover.js | 2 +- .../gabsocial/components/scrollable_list.js | 73 ++++--- .../gabsocial/components/status/status.js | 12 +- .../status_action_bar/status_action_bar.js | 22 +- .../gabsocial/components/status_header.js | 2 +- .../gabsocial/containers/status_container.js | 22 +- .../gabsocial/features/account_gallery.js | 125 +++++++++++ .../account_gallery/account_gallery.js | 205 ------------------ .../account_gallery/account_gallery.scss | 5 - .../components/media_item/index.js | 1 - .../components/media_item/media_item.js | 156 ------------- .../components/media_item/media_item.scss | 17 -- .../features/account_gallery/index.js | 1 - .../account_timeline/account_timeline.js | 104 ++++----- .../components/header/header.js | 8 +- .../components/inner_header/inner_header.js | 6 +- .../components/profile_info_panel/index.js | 1 - .../profile_info_panel/profile_info_panel.js | 135 ------------ .../profile_info_panel.scss | 133 ------------ .../containers/header_container.js | 2 +- .../gabsocial/features/{blocks => }/blocks.js | 16 +- .../gabsocial/features/blocks/index.js | 1 - .../{domain_blocks => }/domain_blocks.js | 8 +- .../gabsocial/features/domain_blocks/index.js | 2 +- .../gabsocial/features/favorites/favorites.js | 6 +- .../gabsocial/features/followers.js | 100 +++++++++ .../gabsocial/features/followers/followers.js | 132 ----------- .../gabsocial/features/followers/index.js | 1 - .../gabsocial/features/following.js | 100 +++++++++ .../gabsocial/features/following/following.js | 134 ------------ .../gabsocial/features/following/index.js | 2 +- .../generic_not_found.js | 2 +- .../features/generic_not_found/index.js | 2 +- .../{group_timeline => }/group_timeline.js | 8 +- .../features/group_timeline/index.js | 2 +- .../groups_collection.js | 6 +- .../features/groups_collection/index.js | 2 +- .../hashtag_timeline.js | 6 +- .../features/hashtag_timeline/index.js | 1 - .../features/introduction/introduction.js | 4 +- .../{list_timeline => }/list_timeline.js | 14 +- .../gabsocial/features/list_timeline/index.js | 1 - .../gabsocial/features/{mutes => }/mutes.js | 8 +- .../gabsocial/features/mutes/index.js | 2 +- .../column_settings/column_settings.js | 12 +- .../components/notification/notification.js | 32 +-- .../components/notification/notification.scss | 59 ----- .../notification_filter_bar.js | 8 +- .../containers/notification_container.js | 24 +- .../gabsocial/features/reblogs/index.js | 2 +- .../{reblogs/reblogs.js => reposts.js} | 32 +-- .../gabsocial/features/{search => }/search.js | 2 +- .../search/components/header/header.js | 57 ----- .../search/components/header/header.scss | 44 ---- .../search/components/header/index.js | 1 - .../gabsocial/features/search/index.js | 2 +- .../containers/detailed_status_container.js | 24 +- .../gabsocial/features/status/status.js | 38 ++-- app/javascript/gabsocial/features/ui/ui.js | 13 +- app/javascript/gabsocial/features/ui/ui.scss | 47 ---- .../features/ui/util/async-components.js | 4 +- .../gabsocial/layouts/profile_layout.js | 8 +- app/javascript/gabsocial/locales/ast.json | 2 +- app/javascript/gabsocial/locales/bg.json | 2 +- app/javascript/gabsocial/locales/cy.json | 2 +- app/javascript/gabsocial/locales/da.json | 2 +- .../gabsocial/locales/defaultMessages.json | 2 +- app/javascript/gabsocial/locales/en.json | 2 +- app/javascript/gabsocial/locales/es.json | 2 +- app/javascript/gabsocial/locales/fi.json | 2 +- app/javascript/gabsocial/locales/he.json | 2 +- app/javascript/gabsocial/locales/hi.json | 2 +- app/javascript/gabsocial/locales/hr.json | 2 +- app/javascript/gabsocial/locales/hu.json | 2 +- app/javascript/gabsocial/locales/hy.json | 2 +- app/javascript/gabsocial/locales/id.json | 2 +- app/javascript/gabsocial/locales/io.json | 2 +- app/javascript/gabsocial/locales/ka.json | 2 +- app/javascript/gabsocial/locales/lv.json | 2 +- app/javascript/gabsocial/locales/ms.json | 2 +- app/javascript/gabsocial/locales/no.json | 2 +- app/javascript/gabsocial/locales/sl.json | 2 +- app/javascript/gabsocial/locales/sr-Latn.json | 2 +- app/javascript/gabsocial/locales/sr.json | 2 +- app/javascript/gabsocial/locales/sv.json | 2 +- app/javascript/gabsocial/locales/ta.json | 2 +- app/javascript/gabsocial/locales/th.json | 2 +- app/javascript/gabsocial/locales/uk.json | 2 +- app/javascript/gabsocial/locales/zh-CN.json | 2 +- app/javascript/gabsocial/locales/zh-HK.json | 2 +- .../gabsocial/pages/profile_page.js | 38 +++- .../gabsocial/reducers/user_lists.js | 4 +- .../service_worker/web_push_notifications.js | 8 +- app/javascript/styles/global.css | 24 +- app/views/layouts/application.html.haml | 2 - config/locales/en.yml | 2 +- config/locales/en_GB.yml | 2 +- config/locales/kk.yml | 2 +- config/locales/nl.yml | 2 +- config/locales/ru.yml | 2 +- config/locales/sv.yml | 2 +- config/webpack/shared.js | 4 +- streaming/index.js | 176 +++++++-------- 109 files changed, 976 insertions(+), 1643 deletions(-) create mode 100644 app/javascript/gabsocial/components/media_item.js create mode 100644 app/javascript/gabsocial/features/account_gallery.js delete mode 100644 app/javascript/gabsocial/features/account_gallery/account_gallery.js delete mode 100644 app/javascript/gabsocial/features/account_gallery/account_gallery.scss delete mode 100644 app/javascript/gabsocial/features/account_gallery/components/media_item/index.js delete mode 100644 app/javascript/gabsocial/features/account_gallery/components/media_item/media_item.js delete mode 100644 app/javascript/gabsocial/features/account_gallery/components/media_item/media_item.scss delete mode 100644 app/javascript/gabsocial/features/account_gallery/index.js delete mode 100644 app/javascript/gabsocial/features/account_timeline/components/profile_info_panel/index.js delete mode 100644 app/javascript/gabsocial/features/account_timeline/components/profile_info_panel/profile_info_panel.js delete mode 100644 app/javascript/gabsocial/features/account_timeline/components/profile_info_panel/profile_info_panel.scss rename app/javascript/gabsocial/features/{blocks => }/blocks.js (79%) delete mode 100644 app/javascript/gabsocial/features/blocks/index.js rename app/javascript/gabsocial/features/{domain_blocks => }/domain_blocks.js (85%) create mode 100644 app/javascript/gabsocial/features/followers.js delete mode 100644 app/javascript/gabsocial/features/followers/followers.js delete mode 100644 app/javascript/gabsocial/features/followers/index.js create mode 100644 app/javascript/gabsocial/features/following.js delete mode 100644 app/javascript/gabsocial/features/following/following.js rename app/javascript/gabsocial/features/{generic_not_found => }/generic_not_found.js (68%) rename app/javascript/gabsocial/features/{group_timeline => }/group_timeline.js (91%) rename app/javascript/gabsocial/features/{groups_collection => }/groups_collection.js (86%) rename app/javascript/gabsocial/features/{hashtag_timeline => }/hashtag_timeline.js (94%) delete mode 100644 app/javascript/gabsocial/features/hashtag_timeline/index.js rename app/javascript/gabsocial/features/{list_timeline => }/list_timeline.js (88%) delete mode 100644 app/javascript/gabsocial/features/list_timeline/index.js rename app/javascript/gabsocial/features/{mutes => }/mutes.js (85%) delete mode 100644 app/javascript/gabsocial/features/notifications/components/notification/notification.scss rename app/javascript/gabsocial/features/{reblogs/reblogs.js => reposts.js} (64%) rename app/javascript/gabsocial/features/{search => }/search.js (83%) delete mode 100644 app/javascript/gabsocial/features/search/components/header/header.js delete mode 100644 app/javascript/gabsocial/features/search/components/header/header.scss delete mode 100644 app/javascript/gabsocial/features/search/components/header/index.js delete mode 100644 app/javascript/gabsocial/features/ui/ui.scss diff --git a/app/javascript/gabsocial/actions/interactions.js b/app/javascript/gabsocial/actions/interactions.js index bfa79fcd..86e6f085 100644 --- a/app/javascript/gabsocial/actions/interactions.js +++ b/app/javascript/gabsocial/actions/interactions.js @@ -2,25 +2,25 @@ import api from '../api'; import { importFetchedAccounts, importFetchedStatus } from './importer'; import { me } from '../initial_state'; -export const REBLOG_REQUEST = 'REBLOG_REQUEST'; -export const REBLOG_SUCCESS = 'REBLOG_SUCCESS'; -export const REBLOG_FAIL = 'REBLOG_FAIL'; +export const REPOST_REQUEST = 'REPOST_REQUEST'; +export const REPOST_SUCCESS = 'REPOST_SUCCESS'; +export const REPOST_FAIL = 'REPOST_FAIL'; export const FAVORITE_REQUEST = 'FAVORITE_REQUEST'; export const FAVORITE_SUCCESS = 'FAVORITE_SUCCESS'; export const FAVORITE_FAIL = 'FAVORITE_FAIL'; -export const UNREBLOG_REQUEST = 'UNREBLOG_REQUEST'; -export const UNREBLOG_SUCCESS = 'UNREBLOG_SUCCESS'; -export const UNREBLOG_FAIL = 'UNREBLOG_FAIL'; +export const UNREPOST_REQUEST = 'UNREPOST_REQUEST'; +export const UNREPOST_SUCCESS = 'UNREPOST_SUCCESS'; +export const UNREPOST_FAIL = 'UNREPOST_FAIL'; export const UNFAVORITE_REQUEST = 'UNFAVORITE_REQUEST'; export const UNFAVORITE_SUCCESS = 'UNFAVORITE_SUCCESS'; export const UNFAVORITE_FAIL = 'UNFAVORITE_FAIL'; -export const REBLOGS_FETCH_REQUEST = 'REBLOGS_FETCH_REQUEST'; -export const REBLOGS_FETCH_SUCCESS = 'REBLOGS_FETCH_SUCCESS'; -export const REBLOGS_FETCH_FAIL = 'REBLOGS_FETCH_FAIL'; +export const REPOSTS_FETCH_REQUEST = 'REPOSTS_FETCH_REQUEST'; +export const REPOSTS_FETCH_SUCCESS = 'REPOSTS_FETCH_SUCCESS'; +export const REPOSTS_FETCH_FAIL = 'REPOSTS_FETCH_FAIL'; export const PIN_REQUEST = 'PIN_REQUEST'; export const PIN_SUCCESS = 'PIN_SUCCESS'; @@ -30,119 +30,119 @@ export const UNPIN_REQUEST = 'UNPIN_REQUEST'; export const UNPIN_SUCCESS = 'UNPIN_SUCCESS'; export const UNPIN_FAIL = 'UNPIN_FAIL'; -export function reblog(status) { +export function repost(status) { return function (dispatch, getState) { if (!me) return; - dispatch(reblogRequest(status)); + dispatch(repostRequest(status)); api(getState).post(`/api/v1/statuses/${status.get('id')}/reblog`).then(function (response) { // The reblog API method returns a new status wrapped around the original. In this case we are only // interested in how the original is modified, hence passing it skipping the wrapper dispatch(importFetchedStatus(response.data.reblog)); - dispatch(reblogSuccess(status)); + dispatch(repostSuccess(status)); }).catch(function (error) { - dispatch(reblogFail(status, error)); + dispatch(repostFail(status, error)); }); }; }; -export function unreblog(status) { +export function unrepost(status) { return (dispatch, getState) => { if (!me) return; - dispatch(unreblogRequest(status)); + dispatch(unrepostRequest(status)); api(getState).post(`/api/v1/statuses/${status.get('id')}/unreblog`).then(response => { dispatch(importFetchedStatus(response.data)); - dispatch(unreblogSuccess(status)); + dispatch(unrepostSuccess(status)); }).catch(error => { - dispatch(unreblogFail(status, error)); + dispatch(unrepostFail(status, error)); }); }; }; -export function reblogRequest(status) { +export function repostRequest(status) { return { - type: REBLOG_REQUEST, + type: REPOST_REQUEST, status: status, skipLoading: true, }; }; -export function reblogSuccess(status) { +export function repostSuccess(status) { return { - type: REBLOG_SUCCESS, + type: REPOST_SUCCESS, status: status, skipLoading: true, }; }; -export function reblogFail(status, error) { +export function repostFail(status, error) { return { - type: REBLOG_FAIL, + type: REPOST_FAIL, status: status, error: error, skipLoading: true, }; }; -export function unreblogRequest(status) { +export function unrepostRequest(status) { return { - type: UNREBLOG_REQUEST, + type: UNREPOST_REQUEST, status: status, skipLoading: true, }; }; -export function unreblogSuccess(status) { +export function unrepostSuccess(status) { return { - type: UNREBLOG_SUCCESS, + type: UNREPOST_SUCCESS, status: status, skipLoading: true, }; }; -export function unreblogFail(status, error) { +export function unrepostFail(status, error) { return { - type: UNREBLOG_FAIL, + type: UNREPOST_FAIL, status: status, error: error, skipLoading: true, }; }; -export function favourite(status) { +export function favorite(status) { return function (dispatch, getState) { if (!me) return; - dispatch(favouriteRequest(status)); + dispatch(favoriteRequest(status)); api(getState).post(`/api/v1/statuses/${status.get('id')}/favourite`).then(function (response) { dispatch(importFetchedStatus(response.data)); - dispatch(favouriteSuccess(status)); + dispatch(favoriteSuccess(status)); }).catch(function (error) { - dispatch(favouriteFail(status, error)); + dispatch(favoriteFail(status, error)); }); }; }; -export function unfavourite(status) { +export function unfavorite(status) { return (dispatch, getState) => { if (!me) return; - dispatch(unfavouriteRequest(status)); + dispatch(unfavoriteRequest(status)); api(getState).post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then(response => { dispatch(importFetchedStatus(response.data)); - dispatch(unfavouriteSuccess(status)); + dispatch(unfavoriteSuccess(status)); }).catch(error => { - dispatch(unfavouriteFail(status, error)); + dispatch(unfavoriteFail(status, error)); }); }; }; -export function favouriteRequest(status) { +export function favoriteRequest(status) { return { type: FAVORITE_REQUEST, status: status, @@ -150,7 +150,7 @@ export function favouriteRequest(status) { }; }; -export function favouriteSuccess(status) { +export function favoriteSuccess(status) { return { type: FAVORITE_SUCCESS, status: status, @@ -158,7 +158,7 @@ export function favouriteSuccess(status) { }; }; -export function favouriteFail(status, error) { +export function favoriteFail(status, error) { return { type: FAVORITE_FAIL, status: status, @@ -167,7 +167,7 @@ export function favouriteFail(status, error) { }; }; -export function unfavouriteRequest(status) { +export function unfavoriteRequest(status) { return { type: UNFAVORITE_REQUEST, status: status, @@ -175,7 +175,7 @@ export function unfavouriteRequest(status) { }; }; -export function unfavouriteSuccess(status) { +export function unfavoriteSuccess(status) { return { type: UNFAVORITE_SUCCESS, status: status, @@ -183,7 +183,7 @@ export function unfavouriteSuccess(status) { }; }; -export function unfavouriteFail(status, error) { +export function unfavoriteFail(status, error) { return { type: UNFAVORITE_FAIL, status: status, @@ -192,39 +192,39 @@ export function unfavouriteFail(status, error) { }; }; -export function fetchReblogs(id) { +export function fetchReposts(id) { return (dispatch, getState) => { if (!me) return; - dispatch(fetchReblogsRequest(id)); + dispatch(fetchRepostsRequest(id)); api(getState).get(`/api/v1/statuses/${id}/reblogged_by`).then(response => { dispatch(importFetchedAccounts(response.data)); - dispatch(fetchReblogsSuccess(id, response.data)); + dispatch(fetchRepostsSuccess(id, response.data)); }).catch(error => { - dispatch(fetchReblogsFail(id, error)); + dispatch(fetchRepostsFail(id, error)); }); }; }; -export function fetchReblogsRequest(id) { +export function fetchRepostsRequest(id) { return { - type: REBLOGS_FETCH_REQUEST, + type: REPOSTS_FETCH_REQUEST, id, }; }; -export function fetchReblogsSuccess(id, accounts) { +export function fetchRepostsSuccess(id, accounts) { return { - type: REBLOGS_FETCH_SUCCESS, + type: REPOSTS_FETCH_SUCCESS, id, accounts, }; }; -export function fetchReblogsFail(id, error) { +export function fetchRepostsFail(id, error) { return { - type: REBLOGS_FETCH_FAIL, + type: REPOSTS_FETCH_FAIL, error, }; }; diff --git a/app/javascript/gabsocial/actions/timelines.js b/app/javascript/gabsocial/actions/timelines.js index 78f372b2..67e60feb 100644 --- a/app/javascript/gabsocial/actions/timelines.js +++ b/app/javascript/gabsocial/actions/timelines.js @@ -2,18 +2,18 @@ import { importFetchedStatus, importFetchedStatuses } from './importer'; import api, { getLinks } from '../api'; import { Map as ImmutableMap, List as ImmutableList, toJS } from 'immutable'; -export const TIMELINE_UPDATE = 'TIMELINE_UPDATE'; -export const TIMELINE_DELETE = 'TIMELINE_DELETE'; -export const TIMELINE_CLEAR = 'TIMELINE_CLEAR'; +export const TIMELINE_UPDATE = 'TIMELINE_UPDATE'; +export const TIMELINE_DELETE = 'TIMELINE_DELETE'; +export const TIMELINE_CLEAR = 'TIMELINE_CLEAR'; export const TIMELINE_UPDATE_QUEUE = 'TIMELINE_UPDATE_QUEUE'; export const TIMELINE_DEQUEUE = 'TIMELINE_DEQUEUE'; export const TIMELINE_SCROLL_TOP = 'TIMELINE_SCROLL_TOP'; export const TIMELINE_EXPAND_REQUEST = 'TIMELINE_EXPAND_REQUEST'; export const TIMELINE_EXPAND_SUCCESS = 'TIMELINE_EXPAND_SUCCESS'; -export const TIMELINE_EXPAND_FAIL = 'TIMELINE_EXPAND_FAIL'; +export const TIMELINE_EXPAND_FAIL = 'TIMELINE_EXPAND_FAIL'; -export const TIMELINE_CONNECT = 'TIMELINE_CONNECT'; +export const TIMELINE_CONNECT = 'TIMELINE_CONNECT'; export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT'; export const MAX_QUEUED_ITEMS = 40; @@ -94,9 +94,9 @@ export function dequeueTimeline(timeline, expandFunc, optionalExpandArgs) { export function deleteFromTimelines(id) { return (dispatch, getState) => { - const accountId = getState().getIn(['statuses', id, 'account']); + const accountId = getState().getIn(['statuses', id, 'account']); const references = getState().get('statuses').filter(status => status.get('reblog') === id).map(status => [status.get('id'), status.get('account')]); - const reblogOf = getState().getIn(['statuses', id, 'reblog'], null); + const reblogOf = getState().getIn(['statuses', id, 'reblog'], null); dispatch({ type: TIMELINE_DELETE, @@ -114,7 +114,7 @@ export function clearTimeline(timeline) { }; }; -const noOp = () => {}; +const noOp = () => { }; const parseTags = (tags = {}, mode) => { return (tags[mode] || []).map((tag) => { @@ -152,20 +152,20 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) { }; }; -export const expandHomeTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('home', '/api/v1/timelines/home', { max_id: maxId }, done); -export const expandPublicTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`public${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { max_id: maxId, only_media: !!onlyMedia }, done); -export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, max_id: maxId, only_media: !!onlyMedia }, done); -export const expandAccountTimeline = (accountId, { maxId, withReplies } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, max_id: maxId }); +export const expandHomeTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('home', '/api/v1/timelines/home', { max_id: maxId }, done); +export const expandPublicTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`public${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { max_id: maxId, only_media: !!onlyMedia }, done); +export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, max_id: maxId, only_media: !!onlyMedia }, done); +export const expandAccountTimeline = (accountId, { maxId, withReplies } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, max_id: maxId }); export const expandAccountFeaturedTimeline = accountId => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true }); -export const expandAccountMediaTimeline = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: 40 }); -export const expandListTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done); -export const expandGroupTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`group:${id}`, `/api/v1/timelines/group/${id}`, { max_id: maxId }, done); -export const expandHashtagTimeline = (hashtag, { maxId, tags } = {}, done = noOp) => { +export const expandAccountMediaTimeline = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: 20 }); +export const expandListTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done); +export const expandGroupTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`group:${id}`, `/api/v1/timelines/group/${id}`, { max_id: maxId }, done); +export const expandHashtagTimeline = (hashtag, { maxId, tags } = {}, done = noOp) => { return expandTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`, { max_id: maxId, - any: parseTags(tags, 'any'), - all: parseTags(tags, 'all'), - none: parseTags(tags, 'none'), + any: parseTags(tags, 'any'), + all: parseTags(tags, 'all'), + none: parseTags(tags, 'none'), }, done); }; diff --git a/app/javascript/gabsocial/components/media_item.js b/app/javascript/gabsocial/components/media_item.js new file mode 100644 index 00000000..34928b31 --- /dev/null +++ b/app/javascript/gabsocial/components/media_item.js @@ -0,0 +1,132 @@ +import ImmutablePropTypes from 'react-immutable-proptypes' +import ImmutablePureComponent from 'react-immutable-pure-component' +import { NavLink } from 'react-router-dom' +import { decode } from 'blurhash' +import { autoPlayGif, displayMedia } from '../initial_state' +import Icon from './icon' +import Image from './image' +import Text from './text' + +export default class MediaItem extends ImmutablePureComponent { + + static propTypes = { + attachment: ImmutablePropTypes.map.isRequired, + } + + state = { + visible: displayMedia !== 'hide_all' && !this.props.attachment.getIn(['status', 'sensitive']) || displayMedia === 'show_all', + loaded: false, + } + + componentDidMount() { + if (this.props.attachment.get('blurhash')) { + this._decode() + } + } + + componentDidUpdate(prevProps) { + if (prevProps.attachment.get('blurhash') !== this.props.attachment.get('blurhash') && this.props.attachment.get('blurhash')) { + this._decode() + } + } + + _decode() { + const hash = this.props.attachment.get('blurhash') + const pixels = decode(hash, 160, 160) + + if (pixels && this.canvas) { + const ctx = this.canvas.getContext('2d') + const imageData = new ImageData(pixels, 160, 160) + + ctx.putImageData(imageData, 0, 0) + } + } + + setCanvasRef = c => { + this.canvas = c + } + + handleImageLoad = () => { + this.setState({ loaded: true }) + } + + hoverToPlay() { + return !autoPlayGif && ['gifv', 'video'].indexOf(this.props.attachment.get('type')) !== -1 + } + + render() { + const { attachment } = this.props + const { visible, loaded } = this.state + + const status = attachment.get('status') + const title = status.get('spoiler_text') || attachment.get('description') + + const attachmentType = attachment.get('type') + let badge = null + + if (attachmentType === 'video') { + const duration = attachment.getIn(['meta', 'duration']) + badge = (duration / 60).toFixed(2) + } else if (attachmentType === 'gifv') { + badge = 'GIF' + } + + return ( +
+
+ + { + (!loaded || !visible) && + + } + + { + visible && + {attachment.get('description')} + } + +
+ { + !visible && + + } + + { + !!badge && +
+ + {badge} + +
+ } + +
+ +
+
+
+ ) + } + +} diff --git a/app/javascript/gabsocial/components/modal/boost_modal.js b/app/javascript/gabsocial/components/modal/boost_modal.js index 515b4f54..26cb63b1 100644 --- a/app/javascript/gabsocial/components/modal/boost_modal.js +++ b/app/javascript/gabsocial/components/modal/boost_modal.js @@ -24,7 +24,7 @@ class BoostModal extends ImmutablePureComponent { static propTypes = { status: ImmutablePropTypes.map.isRequired, - onReblog: PropTypes.func.isRequired, + onRepost: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, }; @@ -33,8 +33,8 @@ class BoostModal extends ImmutablePureComponent { this.button.focus(); } - handleReblog = () => { - this.props.onReblog(this.props.status); + handleRepost = () => { + this.props.onRepost(this.props.status); this.props.onClose(); } @@ -96,7 +96,7 @@ class BoostModal extends ImmutablePureComponent { } })} -