From 47cd60f85121f31697b1d815da230b83f5e8eb0b Mon Sep 17 00:00:00 2001 From: mgabdev <> Date: Thu, 17 Dec 2020 23:46:37 -0500 Subject: [PATCH] Progress added composer query string functionality for url, text. fixed issue with no user in base_controller, cleaned up video component, albums starting --- app/controllers/api/base_controller.rb | 1 + app/javascript/gabsocial/components/album.js | 33 +- .../compose_navigation_bar_xs.js | 22 +- .../navigation_bar/profile_navigation_bar.js | 23 +- .../gabsocial/components/profile_header.js | 13 + app/javascript/gabsocial/components/video.js | 524 +----------------- .../gabsocial/features/account_albums.js | 202 ++++--- .../gabsocial/features/compose/compose.js | 28 +- .../features/ui/util/async_components.js | 1 + .../gabsocial/layouts/compose_layout.js | 27 +- .../gabsocial/layouts/profile_layout.js | 2 +- .../gabsocial/pages/compose_page.js | 1 - app/javascript/gabsocial/reducers/albums.js | 8 +- app/javascript/gabsocial/utils/fullscreen.js | 46 -- app/javascript/styles/global.css | 2 + app/models/media_attachment_album.rb | 1 + app/models/status_bookmark_collection.rb | 1 - ...18_add_count_to_media_attachment_albums.rb | 7 + db/schema.rb | 3 +- 19 files changed, 269 insertions(+), 676 deletions(-) delete mode 100644 app/javascript/gabsocial/utils/fullscreen.js create mode 100644 db/migrate/20201218012018_add_count_to_media_attachment_albums.rb diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index 647fa856..e64d7e95 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -98,6 +98,7 @@ class Api::BaseController < ApplicationController end def superapp? + return true if doorkeeper_token.nil? doorkeeper_token && doorkeeper_token.application.superapp? || false end diff --git a/app/javascript/gabsocial/components/album.js b/app/javascript/gabsocial/components/album.js index fe0d03ca..ef41127d 100644 --- a/app/javascript/gabsocial/components/album.js +++ b/app/javascript/gabsocial/components/album.js @@ -1,5 +1,6 @@ import React from 'react' import PropTypes from 'prop-types' +import { NavLink } from 'react-router-dom' import ImmutablePropTypes from 'react-immutable-proptypes' import ImmutablePureComponent from 'react-immutable-pure-component' import { CX } from '../constants' @@ -15,17 +16,30 @@ class Album extends React.PureComponent { } render() { - const { album } = this.props + const { album, isDummy } = this.props return ( - +
+ { + !isDummy && + +
+
+
+
+
+
+
+
+ Profile Photos + 1 Item +
+ + } +
) } @@ -34,6 +48,7 @@ class Album extends React.PureComponent { Album.propTypes = { album: ImmutablePropTypes.map, isAddable: PropTypes.bool, + isDummy: PropTypes.bool, } export default Album \ No newline at end of file diff --git a/app/javascript/gabsocial/components/navigation_bar/compose_navigation_bar_xs.js b/app/javascript/gabsocial/components/navigation_bar/compose_navigation_bar_xs.js index de31b1b7..5ef1787c 100644 --- a/app/javascript/gabsocial/components/navigation_bar/compose_navigation_bar_xs.js +++ b/app/javascript/gabsocial/components/navigation_bar/compose_navigation_bar_xs.js @@ -3,7 +3,10 @@ import PropTypes from 'prop-types' import { connect } from 'react-redux' import { length } from 'stringz' import { openPopover } from '../../actions/popover' -import { MAX_POST_CHARACTER_COUNT } from '../../constants' +import { + CX, + MAX_POST_CHARACTER_COUNT, +} from '../../constants' import Heading from '../heading' import Button from '../button' import BackButton from '../back_button' @@ -23,15 +26,27 @@ class ComposeNavigationBar extends React.PureComponent { isSubmitting, anyMedia, text, + isXS, } = this.props const disabledButton = isSubmitting || isUploading || isChangingUpload || length(text) > MAX_POST_CHARACTER_COUNT || (length(text.trim()) === 0 && !anyMedia) - + const innerClasses = CX({ + d: 1, + flexRow: 1, + saveAreaInsetPT: 1, + saveAreaInsetPL: 1, + saveAreaInsetPR: 1, + w100PC: 1, + maxW640PX: !isXS, + mlAuto: !isXS, + mrAuto: !isXS, + }) + return (
-
+
{ + this.props.openProfileOptionsPopover({ + account: this.props.account, + targetRef: this.openMoreNode, + position: 'bottom', + }) + } + + setOpenMoreNodeRef = (n) => { + this.openMoreNode = n + } + render() { const { titleHTML } = this.props @@ -51,9 +66,15 @@ class ProfileNavigationBar extends React.PureComponent { } +const mapDispatchToProps = (dispatch) => ({ + openProfileOptionsPopover(props) { + dispatch(openPopover(POPOVER_PROFILE_OPTIONS, props)) + }, +}) + ProfileNavigationBar.propTypes = { titleHTML: PropTypes.string, showBackBtn: PropTypes.bool, } -export default ProfileNavigationBar \ No newline at end of file +export default connect(null, mapDispatchToProps)(ProfileNavigationBar) \ No newline at end of file diff --git a/app/javascript/gabsocial/components/profile_header.js b/app/javascript/gabsocial/components/profile_header.js index 081d4b6e..61d87fec 100644 --- a/app/javascript/gabsocial/components/profile_header.js +++ b/app/javascript/gabsocial/components/profile_header.js @@ -226,6 +226,7 @@ class ProfileHeader extends ImmutablePureComponent { iconClassName={_s.inheritFill} color='brand' backgroundColor='none' + // : TODO : className={[_s.jcCenter, _s.aiCenter, _s.mr10, _s.px10].join(' ')} onClick={this.handleOpenMore} buttonRef={this.setOpenMoreNodeRef} @@ -365,6 +366,18 @@ class ProfileHeader extends ImmutablePureComponent { onClick={this.handleOpenMore} buttonRef={this.setOpenMoreNodeRef} /> +
} diff --git a/app/javascript/gabsocial/components/video.js b/app/javascript/gabsocial/components/video.js index 008a61f8..9c08268a 100644 --- a/app/javascript/gabsocial/components/video.js +++ b/app/javascript/gabsocial/components/video.js @@ -5,21 +5,10 @@ import ImmutablePropTypes from 'react-immutable-proptypes' import ImmutablePureComponent from 'react-immutable-pure-component' import { defineMessages, injectIntl } from 'react-intl' import { is } from 'immutable' -import throttle from 'lodash.throttle' import { decode } from 'blurhash' import videojs from 'video.js' -import { isFullscreen, requestFullscreen, exitFullscreen } from '../utils/fullscreen' import { isPanoramic, isPortrait, minimumAspectRatio, maximumAspectRatio } from '../utils/media_aspect_ratio' -import { - openPopover, -} from '../actions/popover' import { displayMedia } from '../initial_state' -import { - CX, - POPOVER_VIDEO_STATS, - BREAKPOINT_EXTRA_SMALL, -} from '../constants' -import Responsive from '../features/ui/util/responsive_component' import Button from './button' import Icon from './icon' import SensitiveMediaItem from './sensitive_media_item' @@ -27,10 +16,6 @@ import Text from './text' import '!style-loader!css-loader!video.js/dist/video-js.min.css' -// check every 100 ms for buffer -const checkInterval = 100 -const FIXED_VAR = 6 - const videoJsOptions = { autoplay: false, playbackRates: [0.5, 1, 1.5, 2], @@ -38,130 +23,19 @@ const videoJsOptions = { sources: [{}], } -const formatTime = (secondsNum) => { - if (isNaN(secondsNum)) secondsNum = 0 - - let hours = Math.floor(secondsNum / 3600) - let minutes = Math.floor((secondsNum - (hours * 3600)) / 60) - let seconds = Math.floor(secondsNum) - (hours * 3600) - (minutes * 60) - - if (hours < 10) hours = '0' + hours - if (minutes < 10) minutes = '0' + minutes - if (seconds < 10) seconds = '0' + seconds - - return (hours === '00' ? '' : `${hours}:`) + `${minutes}:${seconds}` -} - -export const findElementPosition = (el) => { - let box - - if (el.getBoundingClientRect && el.parentNode) { - box = el.getBoundingClientRect() - } - - if (!box) { - return { - left: 0, - top: 0, - } - } - - const docEl = document.documentElement - const body = document.body - - const clientLeft = docEl.clientLeft || body.clientLeft || 0 - const scrollLeft = window.pageXOffset || body.scrollLeft - const left = (box.left + scrollLeft) - clientLeft - - const clientTop = docEl.clientTop || body.clientTop || 0 - const scrollTop = window.pageYOffset || body.scrollTop - const top = (box.top + scrollTop) - clientTop - - return { - left: Math.round(left), - top: Math.round(top), - } -} - -export const getPointerPosition = (el, event) => { - const position = {} - const box = findElementPosition(el) - const boxW = el.offsetWidth - const boxH = el.offsetHeight - const boxY = box.top - const boxX = box.left - - let pageY = event.pageY - let pageX = event.pageX - - if (event.changedTouches) { - pageX = event.changedTouches[0].pageX - pageY = event.changedTouches[0].pageY - } - - position.y = Math.max(0, Math.min(1, (pageY - boxY) / boxH)) - position.x = Math.max(0, Math.min(1, (pageX - boxX) / boxW)) - - return position -} - class Video extends ImmutablePureComponent { state = { - currentTime: 0, - duration: 0, - volume: 0.5, - paused: true, - dragging: false, - draggingVolume: false, containerWidth: this.props.width, - fullscreen: false, - hovered: false, - muted: false, - hoveringVolumeButton: false, - hoveringVolumeControl: false, revealed: this.props.visible !== undefined ? this.props.visible : (displayMedia !== 'hide_all' && !this.props.sensitive || displayMedia === 'show_all'), - pipAvailable: true, - isBuffering: false, } - bufferCheckInterval = null - lastPlayPos = 0 - volHeight = 100 - volOffset = 13 - componentDidMount() { - const { meta, blurhash } = this.props - - document.addEventListener('fullscreenchange', this.handleFullscreenChange, true) - document.addEventListener('webkitfullscreenchange', this.handleFullscreenChange, true) - document.addEventListener('mozfullscreenchange', this.handleFullscreenChange, true) - document.addEventListener('MSFullscreenChange', this.handleFullscreenChange, true) - - if (meta) { - this.setState({ duration: parseInt(meta.get('duration')) }) - } - - if ('pictureInPictureEnabled' in document) { - this.setState({ pipAvailable: true }) - } - videoJsOptions.sources = [{ src: this.props.src }] - console.log("videoJsOptions:", videoJsOptions) - // instantiate video.js - this.videoPlayer = videojs(this.videoNode, videoJsOptions, function onPlayerReady() { - console.log('onPlayerReady', this) - }) + this.videoPlayer = videojs(this.video, videoJsOptions) } componentWillUnmount() { - document.removeEventListener('fullscreenchange', this.handleFullscreenChange, true) - document.removeEventListener('webkitfullscreenchange', this.handleFullscreenChange, true) - document.removeEventListener('mozfullscreenchange', this.handleFullscreenChange, true) - document.removeEventListener('MSFullscreenChange', this.handleFullscreenChange, true) - - clearInterval(this.bufferCheckInterval) - if (this.videoPlayer) { this.videoPlayer.dispose() } @@ -179,34 +53,6 @@ class Video extends ImmutablePureComponent { } } - checkBuffering = () => { - const { isBuffering, paused } = this.state - if (!this.video) { - this.handlePause() - return - } - const { currentTime } = this.video - - // Checking offset should be at most the check interval but allow for some margin - let offset = (checkInterval - 30) / 1000 - - if (!isBuffering && currentTime < (this.lastPlayPos + offset) && !paused) { - // If no buffering is currently detected, and the position does not seem to increase - // and the player isn't manually paused... - this.setState({ isBuffering: true }) - } else if (isBuffering && currentTime > (this.lastPlayPos + offset) && !paused) { - // If we were buffering but the player has advanced, then there is no buffering - this.setState({ isBuffering: false }) - } - - this.lastPlayPos = currentTime - } - - volHandleOffset = (v) => { - const offset = v * this.volHeight + this.volOffset - return (offset > 110) ? 110 : offset - } - setPlayerRef = (n) => { this.player = n @@ -220,197 +66,10 @@ class Video extends ImmutablePureComponent { setVideoRef = (n) => { this.video = n - this.videoNode = n - - if (this.video) { - const { volume, muted } = this.video - this.setState({ - volume, - muted, - }) - } - } - - setSeekRef = (n) => { - this.seek = n - } - - setVolumeRef = (n) => { - this.volume = n - } - - setSettingsBtnRef = (n) => { - this.settingsBtn = n } handleClickRoot = (e) => e.stopPropagation() - handlePlay = () => { - this.setState({ paused: false }) - - this.bufferCheckInterval = setInterval(this.checkBuffering, checkInterval) - } - - handlePause = () => { - this.setState({ - paused: true, - isBuffering: false, - }) - - clearInterval(this.bufferCheckInterval) - } - - handleTimeUpdate = () => { - const { currentTime, duration } = this.video - this.setState({ - currentTime: currentTime.toFixed(FIXED_VAR), - duration: duration.toFixed(FIXED_VAR), - }) - } - - handleVolumeMouseDown = (e) => { - document.addEventListener('mousemove', this.handleMouseVolSlide, true) - document.addEventListener('mouseup', this.handleVolumeMouseUp, true) - document.addEventListener('touchmove', this.handleMouseVolSlide, true) - document.addEventListener('touchend', this.handleVolumeMouseUp, true) - - this.handleMouseVolSlide(e) - - e.preventDefault() - e.stopPropagation() - - this.setState({ draggingVolume: true }) - } - - handleVolumeMouseUp = () => { - this.handleMouseLeaveVolumeControl() - - document.removeEventListener('mousemove', this.handleMouseVolSlide, true) - document.removeEventListener('mouseup', this.handleVolumeMouseUp, true) - document.removeEventListener('touchmove', this.handleMouseVolSlide, true) - document.removeEventListener('touchend', this.handleVolumeMouseUp, true) - - this.setState({ draggingVolume: false }) - } - - handleMouseVolSlide = throttle((e) => { - const rect = this.volume.getBoundingClientRect() - const y = 1 - ((e.clientY - rect.top) / this.volHeight) - - if (!isNaN(y)) { - const slideamt = y - if (y > 1) { - slideamt = 1 - } else if (y < 0) { - slideamt = 0 - } - this.video.volume = slideamt - this.setState({ volume: slideamt }) - } - }, 60) - - handleMouseDown = (e) => { - document.addEventListener('mousemove', this.handleMouseMove, true) - document.addEventListener('mouseup', this.handleMouseUp, true) - document.addEventListener('touchmove', this.handleMouseMove, true) - document.addEventListener('touchend', this.handleMouseUp, true) - - this.setState({ dragging: true }) - this.video.pause() - this.handleMouseMove(e) - - e.preventDefault() - e.stopPropagation() - } - - handleMouseUp = () => { - document.removeEventListener('mousemove', this.handleMouseMove, true) - document.removeEventListener('mouseup', this.handleMouseUp, true) - document.removeEventListener('touchmove', this.handleMouseMove, true) - document.removeEventListener('touchend', this.handleMouseUp, true) - - this.setState({ dragging: false }) - this.video.play() - } - - handleMouseMove = throttle(e => { - const { x } = getPointerPosition(this.seek, e) - const currentTime = parseFloat(this.video.duration * x).toFixed(FIXED_VAR) - - if (!isNaN(currentTime)) { - this.video.currentTime = currentTime - this.setState({ currentTime }) - } - }, 60) - - togglePlay = () => { - if (this.state.paused) { - this.video.play() - } else { - this.video.pause() - } - } - - toggleFullscreen = () => { - if (isFullscreen()) { - exitFullscreen() - } else { - requestFullscreen(this.player) - } - } - - togglePip = () => { - try { - if (this.video !== document.pictureInPictureElement) { - if (this.state.paused) { - this.video.play() - } - setTimeout(() => { // : hack : - this.video.requestPictureInPicture() - }, 500) - } else { - document.exitPictureInPicture() - } - } catch(e) { - // - } - } - - handleFullscreenChange = () => { - this.setState({ fullscreen: isFullscreen() }) - } - - handleMouseEnter = () => { - this.setState({ hovered: true }) - } - - handleMouseLeave = () => { - this.setState({ hovered: false }) - } - - handleMouseEnterAudio = () => { - this.setState({ hoveringVolumeButton: true }) - } - - handleMouseLeaveAudio = throttle(() => { - this.setState({ hoveringVolumeButton: false }) - }, 2500) - - handleMouseEnterVolumeControl = () => { - this.setState({ hoveringVolumeControl: true }) - } - - handleMouseLeaveVolumeControl = throttle(() => { - if (!this.state.draggingVolume) { - this.setState({ hoveringVolumeControl: false }) - } - }, 2500) - - toggleMute = () => { - this.video.muted = !this.video.muted - this.setState({ muted: this.video.muted }) - } - toggleReveal = () => { if (this.props.onToggleVisibility) { this.props.onToggleVisibility() @@ -419,36 +78,6 @@ class Video extends ImmutablePureComponent { } } - handleLoadedData = () => { - if (this.props.startTime) { - this.video.currentTime = this.props.startTime - this.video.play() - } - } - - handleProgress = () => { - const { buffered, duration } = this.video - - if (!buffered) return - if (buffered.length > 0) { - this.setState({ - buffer: buffered.end(0) / duration * 100, - }) - } - } - - handleVolumeChange = () => { - const { volume, muted } = this.video - this.setState({ - volume, - muted, - }) - } - - handleOnClickSettings = () => { - this.props.onOpenVideoStatsPopover(this.settingsBtn, this.props.meta) - } - render() { const { preview, @@ -464,26 +93,9 @@ class Video extends ImmutablePureComponent { const { containerWidth, - currentTime, - duration, - volume, - buffer, - dragging, - paused, - fullscreen, - hovered, - muted, revealed, - hoveringVolumeButton, - hoveringVolumeControl, - pipAvailable, - isBuffering, } = this.state - const progress = (currentTime / duration) * 100 - - const volumeHeight = (muted) ? 0 : volume * this.volHeight - const volumeHandleLoc = (muted) ? this.volHandleOffset(0) : this.volHandleOffset(volume) const playerStyle = {} let { width, height } = this.props @@ -505,7 +117,7 @@ class Video extends ImmutablePureComponent { let preload - if (startTime || fullscreen || dragging) { + if (startTime) { preload = 'auto' } else if (detailed) { preload = 'metadata' @@ -513,87 +125,13 @@ class Video extends ImmutablePureComponent { preload = 'none' } - const mainContainerClasses = CX({ - d: 1, - mt10: 1, - outlineNone: 1, - }) - - const seekHandleClasses = CX({ - d: 1, - posAbs: 1, - circle: 1, - h20PX: 1, - w20PX: 1, - bgTransparent: 1, - mlNeg5PX: 1, - mr5: 1, - z3: 1, - aiCenter: 1, - jcCenter: 1, - videoEase: 1, - opacity0: !dragging, - opacity1: dragging || hovered, - }) - - const seekInnerHandleClasses = CX({ - d: 1, - circle: 1, - h14PX: 1, - w14PX: 1, - bgBrand: 1, - boxShadow1: 1, - }) - - const progressClasses = CX({ - d: 1, - radiusSmall: 1, - mt10: 1, - posAbs: 1, - h4PX: 1, - videoEase: 1, - }) - - const volumeControlClasses = CX({ - d: 1, - posAbs: 1, - bgBlackOpaque: 1, - videoPlayerVolume: 1, - h122PX: 1, - circle: 1, - displayNone: !hoveringVolumeButton && !hoveringVolumeControl || !hovered, - }) - - const videoControlsBackgroundClasses = CX({ - d: 1, - z2: 1, - px15: 1, - videoPlayerControlsBackground: 1, - posAbs: 1, - bottom0: 1, - right0: 1, - left0: 1, - displayNone: !hovered && !paused, - }) - - const overlayClasses = CX({ - d: 1, - top50PC: 1, - left50PC: 1, - posAbs: 1, - z2: 1, - aiCenter: 1, - jcCenter: 1, - displayNone: !paused && !isBuffering, - }) - if (!revealed && sensitive) { return } return (
- -
- { - !paused && true && - - } -
-
@@ -651,30 +173,9 @@ class Video extends ImmutablePureComponent { } const messages = defineMessages({ - play: { id: 'video.play', defaultMessage: 'Play' }, - pause: { id: 'video.pause', defaultMessage: 'Pause' }, - mute: { id: 'video.mute', defaultMessage: 'Mute sound' }, - unmute: { id: 'video.unmute', defaultMessage: 'Unmute sound' }, - hide: { id: 'video.hide', defaultMessage: 'Hide video' }, - fullscreen: { id: 'video.fullscreen', defaultMessage: 'Full screen' }, - exit_fullscreen: { id: 'video.exit_fullscreen', defaultMessage: 'Exit full screen' }, - sensitive: { id: 'status.sensitive_warning', defaultMessage: 'Sensitive content' }, - hidden: { id: 'status.media_hidden', defaultMessage: 'Media hidden' }, - video_stats: { id: 'video.stats_label', defaultMessage: 'Video meta stats' }, toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: 'Hide media' }, }) - -const mapDispatchToProps = (dispatch) => ({ - onOpenVideoStatsPopover(targetRef, meta) { - dispatch(openPopover(POPOVER_VIDEO_STATS, { - targetRef, - meta, - position: 'top', - })) - } -}) - Video.propTypes = { preview: PropTypes.string, src: PropTypes.string.isRequired, @@ -692,7 +193,6 @@ Video.propTypes = { blurhash: PropTypes.string, aspectRatio: PropTypes.number, meta: ImmutablePropTypes.map, - onOpenVideoStatsPopover: PropTypes.func.isRequired, } -export default injectIntl(connect(null, mapDispatchToProps)(Video)) \ No newline at end of file +export default injectIntl(Video) \ No newline at end of file diff --git a/app/javascript/gabsocial/features/account_albums.js b/app/javascript/gabsocial/features/account_albums.js index 5f7f7fd6..4f5974e8 100644 --- a/app/javascript/gabsocial/features/account_albums.js +++ b/app/javascript/gabsocial/features/account_albums.js @@ -7,109 +7,149 @@ import { injectIntl, defineMessages } from 'react-intl' import { expandAccountMediaTimeline } from '../actions/timelines' import { getAccountGallery } from '../selectors' import ColumnIndicator from '../components/column_indicator' +import Heading from '../components/heading' +import TabBar from '../components/tab_bar' import MediaItem from '../components/media_item' import LoadMore from '../components/load_more' import Block from '../components/block' +import Image from '../components/image' +import Album from '../components/album' import MediaGalleryPlaceholder from '../components/placeholder/media_gallery_placeholder' class AccountAlbums extends ImmutablePureComponent { - componentDidMount() { - const { accountId, mediaType } = this.props + // componentDidMount() { + // const { accountId, mediaType } = this.props - if (accountId && accountId !== -1) { - this.props.dispatch(expandAccountMediaTimeline(accountId, { mediaType })) - } - } + // if (accountId && accountId !== -1) { + // this.props.dispatch(expandAccountMediaTimeline(accountId, { mediaType })) + // } + // } - componentWillReceiveProps(nextProps) { - if ( - (nextProps.accountId && nextProps.accountId !== this.props.accountId) || - (nextProps.accountId && nextProps.mediaType !== this.props.mediaType) - ) { - this.props.dispatch(expandAccountMediaTimeline(nextProps.accountId, { - mediaType: nextProps.mediaType, - })) - } - } + // componentWillReceiveProps(nextProps) { + // if ( + // (nextProps.accountId && nextProps.accountId !== this.props.accountId) || + // (nextProps.accountId && nextProps.mediaType !== this.props.mediaType) + // ) { + // this.props.dispatch(expandAccountMediaTimeline(nextProps.accountId, { + // mediaType: nextProps.mediaType, + // })) + // } + // } - handleScrollToBottom = () => { - if (this.props.hasMore) { - this.handleLoadMore(this.props.attachments.size > 0 ? this.props.attachments.last().getIn(['status', 'id']) : undefined) - } - } + // handleScrollToBottom = () => { + // if (this.props.hasMore) { + // this.handleLoadMore(this.props.attachments.size > 0 ? this.props.attachments.last().getIn(['status', 'id']) : undefined) + // } + // } - handleScroll = (e) => { - const { scrollTop, scrollHeight, clientHeight } = e.target - const offset = scrollHeight - scrollTop - clientHeight + // handleScroll = (e) => { + // const { scrollTop, scrollHeight, clientHeight } = e.target + // const offset = scrollHeight - scrollTop - clientHeight - if (150 > offset && !this.props.isLoading) { - this.handleScrollToBottom() - } - } + // if (150 > offset && !this.props.isLoading) { + // this.handleScrollToBottom() + // } + // } - handleLoadMore = (maxId) => { - if (this.props.accountId && this.props.accountId !== -1) { - this.props.dispatch(expandAccountMediaTimeline(this.props.accountId, { - maxId, - mediaType: this.props.mediaType, - })) - } - } + // handleLoadMore = (maxId) => { + // if (this.props.accountId && this.props.accountId !== -1) { + // this.props.dispatch(expandAccountMediaTimeline(this.props.accountId, { + // maxId, + // mediaType: this.props.mediaType, + // })) + // } + // } - handleLoadOlder = (e) => { - e.preventDefault() - this.handleScrollToBottom() - } + // handleLoadOlder = (e) => { + // e.preventDefault() + // this.handleScrollToBottom() + // } render() { - const { - attachments, - isLoading, - hasMore, - intl, - account, - } = this.props - - if (!account) return null - return ( -
- - { - attachments.map((attachment, i) => ( - - )) - } - - { - isLoading && attachments.size === 0 && -
- -
- } - - { - !isLoading && attachments.size === 0 && - - } +
+
+ Photos +
+
- { - hasMore && !(isLoading && attachments.size === 0) && - - } +
+ + + + + + + + + + + + + +
) + // const { + // attachments, + // isLoading, + // hasMore, + // intl, + // account, + // } = this.props + + // if (!account) return null + + // return ( + // + //
+ + // { + // attachments.map((attachment, i) => ( + // + // )) + // } + + // { + // isLoading && attachments.size === 0 && + //
+ // + //
+ // } + + // { + // !isLoading && attachments.size === 0 && + // + // } + //
+ + // { + // hasMore && !(isLoading && attachments.size === 0) && + // + // } + //
+ // ) } } diff --git a/app/javascript/gabsocial/features/compose/compose.js b/app/javascript/gabsocial/features/compose/compose.js index 8d016880..21669554 100644 --- a/app/javascript/gabsocial/features/compose/compose.js +++ b/app/javascript/gabsocial/features/compose/compose.js @@ -1,11 +1,31 @@ import React from 'react' import PropTypes from 'prop-types' import { connect } from 'react-redux' -import { clearCompose } from '../../actions/compose' +import { withRouter } from 'react-router-dom' +import queryString from 'query-string' +import { clearCompose, changeCompose } from '../../actions/compose' import ComposeFormContainer from './containers/compose_form_container' class Compose extends React.PureComponent { + componentDidMount() { + const search = this.context.router.route.location.search + try { + const qp = queryString.parse(search) + const url = `${qp.url || ''}` + const text = `${qp.text || ''}` + + if (url.length > 0 || text.length > 0) { + let value = "" + if (text.length > 0) value += `${text} ` + if (url.length > 0) value += url + this.props.dispatch(changeCompose(value)) + } + } catch (error) { + // + } + } + componentWillUnmount() { this.props.dispatch(clearCompose()) } @@ -16,4 +36,8 @@ class Compose extends React.PureComponent { } -export default connect()(Compose) \ No newline at end of file +Compose.contextTypes = { + router: PropTypes.object.isRequired, +} + +export default withRouter(connect()(Compose)) \ No newline at end of file diff --git a/app/javascript/gabsocial/features/ui/util/async_components.js b/app/javascript/gabsocial/features/ui/util/async_components.js index 982cc781..45017655 100644 --- a/app/javascript/gabsocial/features/ui/util/async_components.js +++ b/app/javascript/gabsocial/features/ui/util/async_components.js @@ -2,6 +2,7 @@ export function About() { return import(/* webpackChunkName: "features/about/abo export function AboutSidebar() { return import(/* webpackChunkName: "components/about_sidebar" */'../../../components/sidebar/about_sidebar') } export function AccountTimeline() { return import(/* webpackChunkName: "features/account_timeline" */'../../account_timeline') } export function AccountCommentsTimeline() { return import(/* webpackChunkName: "features/account_comments_timeline" */'../../account_comments_timeline') } +export function AccountAlbums() { return import(/* webpackChunkName: "features/account_albums" */'../../account_albums') } export function AccountGallery() { return import(/* webpackChunkName: "features/account_gallery" */'../../account_gallery') } export function AlbumCreate() { return import(/* webpackChunkName: "features/album_create" */'../../album_create') } export function AlbumCreateModal() { return import(/* webpackChunkName: "components/album_create_modal" */'../../../components/modal/album_create_modal') } diff --git a/app/javascript/gabsocial/layouts/compose_layout.js b/app/javascript/gabsocial/layouts/compose_layout.js index bbba76ff..8761075e 100644 --- a/app/javascript/gabsocial/layouts/compose_layout.js +++ b/app/javascript/gabsocial/layouts/compose_layout.js @@ -1,28 +1,27 @@ import React from 'react' import PropTypes from 'prop-types' import { me } from '../initial_state' -import DefaultSidebar from '../components/sidebar/default_sidebar' +import { CX } from '../constants' import ComposeNavigationBar from '../components/navigation_bar/compose_navigation_bar_xs' -import Responsive from '../features/ui/util/responsive_component' -import WrappedBundle from '../features/ui/util/wrapped_bundle' -import { - SidebarXS, -} from '../features/ui/util/async_components' class ComposeLayout extends React.PureComponent { render() { const { children, isXS } = this.props - - if (!isXS) return null + + const mainClasses = CX({ + d: 1, + w100PC: 1, + flexGrow1: 1, + borderRight1PX: !isXS, + borderLeft1PX: !isXS, + borderColorSecondary: !isXS, + }) return ( -
- - - - -
+
+ +
{ children }
diff --git a/app/javascript/gabsocial/layouts/profile_layout.js b/app/javascript/gabsocial/layouts/profile_layout.js index 7027072c..04dc2d88 100644 --- a/app/javascript/gabsocial/layouts/profile_layout.js +++ b/app/javascript/gabsocial/layouts/profile_layout.js @@ -88,7 +88,7 @@ class ProfileLayout extends ImmutablePureComponent { { !!me && - + } { !me && diff --git a/app/javascript/gabsocial/pages/compose_page.js b/app/javascript/gabsocial/pages/compose_page.js index 9c1b5ab1..cdc113d7 100644 --- a/app/javascript/gabsocial/pages/compose_page.js +++ b/app/javascript/gabsocial/pages/compose_page.js @@ -35,7 +35,6 @@ class ComposePage extends React.PureComponent { const { width } = this.state const isXS = width <= BREAKPOINT_EXTRA_SMALL - if (!isXS) throw 'This page does not exist' return ( diff --git a/app/javascript/gabsocial/reducers/albums.js b/app/javascript/gabsocial/reducers/albums.js index 91841747..27e114bc 100644 --- a/app/javascript/gabsocial/reducers/albums.js +++ b/app/javascript/gabsocial/reducers/albums.js @@ -4,7 +4,7 @@ import { ALBUMS_FETCH_FAIL, ALBUMS_CREATE_SUCCESS, ALBUMS_REMOVE_REQUEST, -} from '../actions/bookmarks' +} from '../actions/albums' import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable' const initialState = ImmutableMap({ @@ -24,7 +24,7 @@ export default function albums(state = initialState, action) { }) case ALBUMS_FETCH_SUCCESS: return state.withMutations((map) => { - map.set('items', fromJS(action.bookmarkCollections)) + map.set('items', fromJS(action.albums)) map.set('isLoading', false) map.set('isFetched', true) map.set('isError', false) @@ -36,10 +36,10 @@ export default function albums(state = initialState, action) { map.set('isError', true) }) case ALBUMS_CREATE_SUCCESS: - return state.update('items', list => list.push(fromJS(action.bookmarkCollection))) + return state.update('items', list => list.push(fromJS(action.albums))) case ALBUMS_REMOVE_REQUEST: return state.update('items', list => list.filterNot((item) => { - return item.get('id') === action.bookmarkCollectionId + return item.get('id') === action.albumId })) default: return state diff --git a/app/javascript/gabsocial/utils/fullscreen.js b/app/javascript/gabsocial/utils/fullscreen.js deleted file mode 100644 index cf5d0cf9..00000000 --- a/app/javascript/gabsocial/utils/fullscreen.js +++ /dev/null @@ -1,46 +0,0 @@ -// APIs for normalizing fullscreen operations. Note that Edge uses -// the WebKit-prefixed APIs currently (as of Edge 16). - -export const isFullscreen = () => document.fullscreenElement || - document.webkitFullscreenElement || - document.mozFullScreenElement; - -export const exitFullscreen = () => { - if (document.exitFullscreen) { - document.exitFullscreen(); - } else if (document.webkitExitFullscreen) { - document.webkitExitFullscreen(); - } else if (document.mozCancelFullScreen) { - document.mozCancelFullScreen(); - } -}; - -export const requestFullscreen = el => { - if (el.requestFullscreen) { - el.requestFullscreen(); - } else if (el.webkitRequestFullscreen) { - el.webkitRequestFullscreen(); - } else if (el.mozRequestFullScreen) { - el.mozRequestFullScreen(); - } -}; - -export const attachFullscreenListener = (listener) => { - if ('onfullscreenchange' in document) { - document.addEventListener('fullscreenchange', listener); - } else if ('onwebkitfullscreenchange' in document) { - document.addEventListener('webkitfullscreenchange', listener); - } else if ('onmozfullscreenchange' in document) { - document.addEventListener('mozfullscreenchange', listener); - } -}; - -export const detachFullscreenListener = (listener) => { - if ('onfullscreenchange' in document) { - document.removeEventListener('fullscreenchange', listener); - } else if ('onwebkitfullscreenchange' in document) { - document.removeEventListener('webkitfullscreenchange', listener); - } else if ('onmozfullscreenchange' in document) { - document.removeEventListener('mozfullscreenchange', listener); - } -}; diff --git a/app/javascript/styles/global.css b/app/javascript/styles/global.css index e49ac239..1cf7070c 100644 --- a/app/javascript/styles/global.css +++ b/app/javascript/styles/global.css @@ -600,6 +600,7 @@ pre { .maxW212PX { max-width: 212px; } .minW330PX { min-width: 330px; } +.minW162PX { min-width: 162px; } .minW120PX { min-width: 120px; } .minW84PX { min-width: 84px; } .minW76PX { min-width: 76px; } @@ -849,6 +850,7 @@ pre { .mtNeg50PX { margin-top: -50px; } .mtNeg75PX { margin-top: -75px; } +.pt100PC { padding-top: 100%; } .pt5625PC { padding-top: 56.25%; } .pt25PC { padding-top: 25%; } .pt53PX { padding-top: 53px; } diff --git a/app/models/media_attachment_album.rb b/app/models/media_attachment_album.rb index 07396fbf..7c2b6598 100644 --- a/app/models/media_attachment_album.rb +++ b/app/models/media_attachment_album.rb @@ -11,6 +11,7 @@ # created_at :datetime not null # updated_at :datetime not null # cover_id :bigint(8) +# count :integer default(0), not null # class MediaAttachmentAlbum < ApplicationRecord diff --git a/app/models/status_bookmark_collection.rb b/app/models/status_bookmark_collection.rb index d7f99140..0c75e8ba 100644 --- a/app/models/status_bookmark_collection.rb +++ b/app/models/status_bookmark_collection.rb @@ -8,7 +8,6 @@ # account_id :integer not null # created_at :datetime not null # updated_at :datetime not null -# visibility :string # class StatusBookmarkCollection < ApplicationRecord diff --git a/db/migrate/20201218012018_add_count_to_media_attachment_albums.rb b/db/migrate/20201218012018_add_count_to_media_attachment_albums.rb new file mode 100644 index 00000000..390ca2ec --- /dev/null +++ b/db/migrate/20201218012018_add_count_to_media_attachment_albums.rb @@ -0,0 +1,7 @@ +class AddCountToMediaAttachmentAlbums < ActiveRecord::Migration[5.2] + disable_ddl_transaction! + + def change + safety_assured { add_column :media_attachment_albums, :count, :integer, null: false, default: 0 } + end +end diff --git a/db/schema.rb b/db/schema.rb index c3e3448e..7d87fac8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_12_17_003945) do +ActiveRecord::Schema.define(version: 2020_12_18_012018) do # These are extensions that must be enabled in order to support this database enable_extension "pg_stat_statements" @@ -420,6 +420,7 @@ ActiveRecord::Schema.define(version: 2020_12_17_003945) do t.datetime "created_at", null: false t.datetime "updated_at", null: false t.bigint "cover_id" + t.integer "count", default: 0, null: false t.index ["cover_id"], name: "index_media_attachment_albums_on_cover_id" end