From 34f6a1ab5b8304ef667fde8deec8b887d8476912 Mon Sep 17 00:00:00 2001 From: mgabdev <> Date: Tue, 22 Dec 2020 12:11:22 -0500 Subject: [PATCH] Progress new MediaAttachment video style :playable for mp4 to make videojs work with multiple files, hiding albums, hiding bookmark collections. may need tweaks on mediaattachment for mov and other formats : todo : --- .../api/v1/album_lists_controller.rb | 65 +++++++++++++++++++ app/controllers/api/v1/albums_controller.rb | 16 ++--- app/javascript/gabsocial/actions/albums.js | 5 +- app/javascript/gabsocial/components/album.js | 30 +++++++-- .../navigation_bar/profile_navigation_bar.js | 3 - .../components/panel/media_gallery_panel.js | 2 +- .../popover/status_options_popover.js | 13 ++-- .../gabsocial/components/profile_header.js | 4 +- .../gabsocial/components/status_check_box.js | 1 + .../gabsocial/components/status_media.js | 1 + app/javascript/gabsocial/components/video.js | 15 +++-- .../gabsocial/features/account_albums.js | 34 +++++----- .../features/account_photo_gallery.js | 11 ++-- .../gabsocial/features/album_create.js | 47 ++++++++++---- .../components/chat_message_compose_form.js | 2 +- app/javascript/gabsocial/features/ui/ui.js | 11 ++-- .../gabsocial/reducers/album_lists.js | 1 + app/javascript/gabsocial/reducers/albums.js | 45 ++++--------- app/javascript/gabsocial/reducers/index.js | 4 +- app/lib/sorting_query_builder.rb | 7 -- app/models/account.rb | 5 -- app/models/chat_conversation_account.rb | 2 - app/models/concerns/account_associations.rb | 1 + app/models/media_attachment.rb | 25 +++++-- app/models/media_attachment_album.rb | 3 + app/serializers/rest/album_serializer.rb | 12 ++++ .../rest/media_attachment_serializer.rb | 14 +++- config/routes.rb | 18 ++--- 28 files changed, 259 insertions(+), 138 deletions(-) create mode 100644 app/controllers/api/v1/album_lists_controller.rb create mode 100644 app/serializers/rest/album_serializer.rb diff --git a/app/controllers/api/v1/album_lists_controller.rb b/app/controllers/api/v1/album_lists_controller.rb new file mode 100644 index 00000000..aa3b3103 --- /dev/null +++ b/app/controllers/api/v1/album_lists_controller.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +class Api::V1::AlbumListsController < Api::BaseController + before_action :require_user! + + before_action :set_account, only: [:show] + after_action :insert_pagination_headers, only: :show + + def show + @albums = load_albums + render json: @albums, each_serializer: REST::AlbumSerializer + end + + private + + def load_albums + paginated_albums + end + + def paginated_albums + @paginated_albums = MediaAttachmentAlbum.where(account: @account) + .paginate_by_max_id( + limit_param(DEFAULT_ACCOUNTS_LIMIT), + params[:max_id], + params[:since_id] + ) + end + + def insert_pagination_headers + set_pagination_headers(next_path, prev_path) + end + + def next_path + if records_continue? + api_v1_album_list_url params[:id], pagination_params(max_id: pagination_max_id) + end + end + + def prev_path + unless paginated_albums.empty? + api_v1_album_list_url params[:id], pagination_params(since_id: pagination_since_id) + end + end + + def pagination_max_id + paginated_albums.last.id + end + + def pagination_since_id + paginated_albums.first.id + end + + def records_continue? + paginated_albums.size == limit_param(DEFAULT_ACCOUNTS_LIMIT) + end + + def pagination_params(core_params) + params.slice(:limit).permit(:limit).merge(core_params) + end + + def set_account + @account = Account.find(params[:id]) + end + +end diff --git a/app/controllers/api/v1/albums_controller.rb b/app/controllers/api/v1/albums_controller.rb index 9376dc63..3b574f28 100644 --- a/app/controllers/api/v1/albums_controller.rb +++ b/app/controllers/api/v1/albums_controller.rb @@ -2,15 +2,11 @@ class Api::V1::AlbumsController < Api::BaseController before_action :require_user! - before_action :set_albums, only: :index + before_action :set_album, only: [:show, :update, :destroy] - def index - render json: @albums, each_serializer: REST::AlbumSerializer - end - def create - @album = "" #current_account.custom_filters.create!(resource_params) + @album = current_account.media_attachment_albums.create!(resource_params) render json: @album, serializer: REST::AlbumSerializer end @@ -30,15 +26,11 @@ class Api::V1::AlbumsController < Api::BaseController private - def set_albums - @albums = "" #current_account.custom_filters - end - def set_album - @album = "" # current_account.custom_filters.find(params[:id]) + @album = current_account.media_attachment_albums.find(params[:id]) end def resource_params - params.permit(:title, :description, :visibility) + params.permit(:title, :description) end end diff --git a/app/javascript/gabsocial/actions/albums.js b/app/javascript/gabsocial/actions/albums.js index e94b114e..bd199be4 100644 --- a/app/javascript/gabsocial/actions/albums.js +++ b/app/javascript/gabsocial/actions/albums.js @@ -47,7 +47,7 @@ export const fetchAlbums = (accountId) => (dispatch, getState) => { dispatch(fetchAlbumsRequest(accountId)) - api(getState).get(`/api/v1/albums/find_by_account/${accountId}`).then((response) => { + api(getState).get(`/api/v1/album_lists/${accountId}`).then((response) => { const next = getLinks(response).refs.find(link => link.rel === 'next') dispatch(fetchAlbumsSuccess(response.data, accountId, next ? next.uri : null)) }).catch((error) => { @@ -119,7 +119,7 @@ const expandAlbumsFail = (accountId, error) => ({ /** * */ -export const createAlbum = (title, description, visibility) => (dispatch, getState) => { +export const createAlbum = (title, description) => (dispatch, getState) => { if (!me || !title) return dispatch(createAlbumRequest()) @@ -127,7 +127,6 @@ export const createAlbum = (title, description, visibility) => (dispatch, getSta api(getState).post('/api/v1/albums', { title, description, - visibility, }).then((response) => { dispatch(createAlbumSuccess(response.data)) }).catch((error) => { diff --git a/app/javascript/gabsocial/components/album.js b/app/javascript/gabsocial/components/album.js index 9d7bfbba..966fea83 100644 --- a/app/javascript/gabsocial/components/album.js +++ b/app/javascript/gabsocial/components/album.js @@ -21,13 +21,17 @@ class Album extends React.PureComponent { render() { const { + account, album, isAddable, } = this.props - - const title = isAddable ? 'New album' : 'Album title' - const subtitle = isAddable ? '' : '10 Items' - const to = isAddable ? undefined : `/photos` + + if (!isAddable && (!album || !account)) return null + + const title = isAddable ? 'New album' : album.get('title') + const subtitle = isAddable ? '' : `${album.get('count')} Items` + const to = isAddable ? undefined : `/${account.get('username')}/albums/${album.get('id')}` + const albumImageUrl = !!album ? album.getIn(['cover', 'preview_url'], null) : null return (
@@ -40,8 +44,17 @@ class Album extends React.PureComponent {
-
+
{ isAddable && } + { + albumImageUrl && + + }
@@ -58,14 +71,19 @@ class Album extends React.PureComponent { } Album.propTypes = { + account: ImmutablePropTypes.map, album: ImmutablePropTypes.map, isAddable: PropTypes.bool, } +const mapStateToProps = (state, { albumId }) => ({ + album: state.getIn(['albums', albumId]), +}) + const mapDispatchToProps = (dispatch) => ({ openAlbumCreate() { dispatch(openModal(MODAL_ALBUM_CREATE)) } }) -export default connect(null, mapDispatchToProps)(Album) \ No newline at end of file +export default connect(mapStateToProps, mapDispatchToProps)(Album) \ No newline at end of file diff --git a/app/javascript/gabsocial/components/navigation_bar/profile_navigation_bar.js b/app/javascript/gabsocial/components/navigation_bar/profile_navigation_bar.js index 5c744774..f53f2f07 100644 --- a/app/javascript/gabsocial/components/navigation_bar/profile_navigation_bar.js +++ b/app/javascript/gabsocial/components/navigation_bar/profile_navigation_bar.js @@ -23,9 +23,6 @@ class ProfileNavigationBar extends React.PureComponent { render() { const { titleHTML } = this.props - - // : todo : - // fix padding on mobile device return (
diff --git a/app/javascript/gabsocial/components/panel/media_gallery_panel.js b/app/javascript/gabsocial/components/panel/media_gallery_panel.js index 70382eca..ed587d37 100644 --- a/app/javascript/gabsocial/components/panel/media_gallery_panel.js +++ b/app/javascript/gabsocial/components/panel/media_gallery_panel.js @@ -55,7 +55,7 @@ class MediaGalleryPanel extends ImmutablePureComponent { noPadding title={intl.formatMessage(messages.title)} headerButtonTitle={!!account ? intl.formatMessage(messages.show_all) : undefined} - headerButtonTo={!!account ? `/${account.get('acct')}/albums` : undefined} + headerButtonTo={!!account ? `/${account.get('acct')}/photos` : undefined} >
{ diff --git a/app/javascript/gabsocial/components/popover/status_options_popover.js b/app/javascript/gabsocial/components/popover/status_options_popover.js index 45c95a32..e766e1f5 100644 --- a/app/javascript/gabsocial/components/popover/status_options_popover.js +++ b/app/javascript/gabsocial/components/popover/status_options_popover.js @@ -19,7 +19,7 @@ import { import { muteAccount, unmuteAccount, -} from '../../actions/interactions'; +} from '../../actions/accounts'; import { deleteStatus, editStatus, @@ -197,11 +197,12 @@ class StatusOptionsPopover extends ImmutablePureComponent { }) if (status.get('bookmarked')) { - menu.push({ - icon: 'bookmark', - title: 'Update bookmark collection', - onClick: this.handleBookmarkChangeClick, - }) + // : todo : + // menu.push({ + // icon: 'bookmark', + // title: 'Update bookmark collection', + // onClick: this.handleBookmarkChangeClick, + // }) } if (status.getIn(['account', 'id']) === me) { diff --git a/app/javascript/gabsocial/components/profile_header.js b/app/javascript/gabsocial/components/profile_header.js index c7b3561b..b5f2c8ed 100644 --- a/app/javascript/gabsocial/components/profile_header.js +++ b/app/javascript/gabsocial/components/profile_header.js @@ -121,7 +121,7 @@ class ProfileHeader extends ImmutablePureComponent { title: intl.formatMessage(messages.comments), }, { - to: `/${account.get('acct')}/albums`, + to: `/${account.get('acct')}/photos`, title: intl.formatMessage(messages.photos), }, { @@ -137,7 +137,7 @@ class ProfileHeader extends ImmutablePureComponent { title: 'Likes', }) tabs.push({ - to: `/${account.get('acct')}/bookmark_collections`, + to: `/${account.get('acct')}/bookmarks`, title: intl.formatMessage(messages.bookmarks), }) } diff --git a/app/javascript/gabsocial/components/status_check_box.js b/app/javascript/gabsocial/components/status_check_box.js index b38e13f8..11e9576e 100644 --- a/app/javascript/gabsocial/components/status_check_box.js +++ b/app/javascript/gabsocial/components/status_check_box.js @@ -32,6 +32,7 @@ class StatusCheckBox extends ImmutablePureComponent { preview={video.get('preview_url')} blurhash={video.get('blurhash')} src={video.get('url')} + sourceMp4={video.get('source_mp4')} alt={video.get('description')} aspectRatio={video.getIn(['meta', 'small', 'aspect'])} fileContentType={video.get('file_content_type')} diff --git a/app/javascript/gabsocial/components/status_media.js b/app/javascript/gabsocial/components/status_media.js index 1626f40c..1a0356f1 100644 --- a/app/javascript/gabsocial/components/status_media.js +++ b/app/javascript/gabsocial/components/status_media.js @@ -65,6 +65,7 @@ class StatusMedia extends ImmutablePureComponent { preview={video.get('preview_url')} blurhash={video.get('blurhash')} src={video.get('url')} + sourceMp4={video.get('source_mp4')} alt={video.get('description')} aspectRatio={video.getIn(['meta', 'small', 'aspect'])} fileContentType={video.get('file_content_type')} diff --git a/app/javascript/gabsocial/components/video.js b/app/javascript/gabsocial/components/video.js index 1687eabb..72b5ce0a 100644 --- a/app/javascript/gabsocial/components/video.js +++ b/app/javascript/gabsocial/components/video.js @@ -31,10 +31,16 @@ class Video extends ImmutablePureComponent { } componentDidMount() { - videoJsOptions.sources = [{ - src: this.props.src, - type: this.props.fileContentType, - }] + videoJsOptions.sources = [ + { + src: this.props.src, + type: this.props.fileContentType, + }, + { + src: this.props.sourceMp4, + type: 'video/mp4', + }, + ] this.videoPlayer = videojs(this.video, videoJsOptions) } @@ -182,6 +188,7 @@ const messages = defineMessages({ Video.propTypes = { preview: PropTypes.string, src: PropTypes.string.isRequired, + sourceMp4: PropTypes.string, alt: PropTypes.string, width: PropTypes.number, height: PropTypes.number, diff --git a/app/javascript/gabsocial/features/account_albums.js b/app/javascript/gabsocial/features/account_albums.js index c6b20346..4ff43fa8 100644 --- a/app/javascript/gabsocial/features/account_albums.js +++ b/app/javascript/gabsocial/features/account_albums.js @@ -5,8 +5,8 @@ import ImmutablePropTypes from 'react-immutable-proptypes' import ImmutablePureComponent from 'react-immutable-pure-component' import { me } from '../initial_state' import { - fetchAccountAlbums, - expandAccountAlbums, + fetchAlbums, + expandAlbums, } from '../actions/albums' import ColumnIndicator from '../components/column_indicator' import Heading from '../components/heading' @@ -48,7 +48,7 @@ class AccountAlbums extends ImmutablePureComponent { render() { const { isMe, - albums, + albumIds, account, accountId, hasMore, @@ -56,7 +56,9 @@ class AccountAlbums extends ImmutablePureComponent { } = this.props if (!account) return null - const hasAlbums = !!albums ? albums.size > 0 : false + const hasAlbums = !!albumIds ? albumIds.size > 0 : false + + console.log("albumIds:", albumIds) return ( @@ -69,11 +71,11 @@ class AccountAlbums extends ImmutablePureComponent { title: 'All Photos', to: `/${account.get('username')}/photos`, }, - { - title: 'Albums', - isActive: true, - to: `/${account.get('username')}/albums`, - }, + // { + // title: 'Albums', + // isActive: true, + // to: `/${account.get('username')}/albums`, + // }, ]}/>
@@ -82,10 +84,10 @@ class AccountAlbums extends ImmutablePureComponent { { hasAlbums && - albums.map((albums, i) => ( + albumIds.map((albumId, i) => ( )) @@ -119,7 +121,7 @@ const mapStateToProps = (state, { account, mediaType }) => { return { accountId, - albums: state.getIn(['album_lists', accountId, 'items']), + albumIds: state.getIn(['album_lists', accountId, 'items']), isLoading: state.getIn(['album_lists', accountId, 'isLoading'], false), hasMore: state.getIn(['album_lists', accountId, 'hasMore'], false), } @@ -127,17 +129,17 @@ const mapStateToProps = (state, { account, mediaType }) => { const mapDispatchToProps = (dispatch) => ({ onFetchAccountAlbums(accountId) { - + dispatch(fetchAlbums(accountId)) }, onExpandAccountAlbums(accountId) { - + dispatch(expandAlbums(accountId)) }, }) AccountAlbums.propTypes = { account: ImmutablePropTypes.map, accountId: PropTypes.string, - albums: ImmutablePropTypes.list, + albumIds: ImmutablePropTypes.list, isLoading: PropTypes.bool, hasMore: PropTypes.bool, intl: PropTypes.object.isRequired, diff --git a/app/javascript/gabsocial/features/account_photo_gallery.js b/app/javascript/gabsocial/features/account_photo_gallery.js index 71962f14..953616cb 100644 --- a/app/javascript/gabsocial/features/account_photo_gallery.js +++ b/app/javascript/gabsocial/features/account_photo_gallery.js @@ -74,7 +74,6 @@ class AccountPhotoGallery extends ImmutablePureComponent { if (!account) return null const hasAttachments = !!attachments ? attachments.size > 0 : false - console.log("account, isLoading, attachments:", account, isLoading, attachments, hasAttachments) return ( @@ -87,11 +86,11 @@ class AccountPhotoGallery extends ImmutablePureComponent { title: 'All Photos', to: `/${account.get('username')}/photos`, }, - { - title: 'Albums', - isActive: true, - to: `/${account.get('username')}/albums`, - }, + // { + // title: 'Albums', + // isActive: true, + // to: `/${account.get('username')}/albums`, + // }, ]}/>
diff --git a/app/javascript/gabsocial/features/album_create.js b/app/javascript/gabsocial/features/album_create.js index 387cbe3f..4cbcd162 100644 --- a/app/javascript/gabsocial/features/album_create.js +++ b/app/javascript/gabsocial/features/album_create.js @@ -8,35 +8,60 @@ import Button from '../components/button' import Input from '../components/input' import Form from '../components/form' import Text from '../components/text' +import Divider from '../components/divider' +import Textarea from '../components/textarea' class AlbumCreate extends React.PureComponent { state = { - value: '', + titleValue: '', + descriptionValue: '', + checked: false, } - onChange = (value) => { - this.setState({ value }) + onChangeTitle = (titleValue) => { + this.setState({ titleValue }) + } + + onChangeDescription = (descriptionValue) => { + this.setState({ descriptionValue }) } handleOnSubmit = () => { - this.props.onSubmit(this.state.value) + const { titleValue, descriptionValue, checked } = this.state + this.props.onSubmit(titleValue, descriptionValue, checked) + } + + onTogglePrivacy = (checked) => { + this.setState({ checked }) } render() { - const { value } = this.state + const { + titleValue, + descriptionValue, + } = this.state - const isDisabled = !value + const isDisabled = !titleValue + + console.log("HELLO") return (
- + +