diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2021-04-01 17:30:37 +0200 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2021-04-01 17:30:37 +0200 |
| commit | 7e344419330855dbbf10896c39e91b4e6861dd57 (patch) | |
| tree | a8baae6cb875a3e8dad47bc4d8392738445f00fd | |
| parent | 5cafa9d43b769e6f60740f59293ddf3588e7b8ad (diff) | |
displaying custom cursors on the frontend
19 files changed, 188 insertions, 43 deletions
diff --git a/frontend/app/types.js b/frontend/app/types.js index a830e71..a0dc717 100644 --- a/frontend/app/types.js +++ b/frontend/app/types.js @@ -17,6 +17,7 @@ export const page = crud_type('page', [ 'show_tile_list', 'hide_tile_list', 'toggle_tile_list', 'toggle_popups', 'load_popups', 'toggle_sidebar_side', + 'toggle_cursor_list', 'pick_cursor', ]) export const tile = crud_type('tile', [ diff --git a/frontend/app/views/index/components/graph.form.js b/frontend/app/views/index/components/graph.form.js index 5710beb..aa30d02 100644 --- a/frontend/app/views/index/components/graph.form.js +++ b/frontend/app/views/index/components/graph.form.js @@ -170,6 +170,12 @@ export default class GraphForm extends Component { data={data.settings} onChange={this.handleSettingsChange} /> + <TextArea + title="Custom fonts" + name="custom_fonts" + data={data.settings} + onChange={this.handleSettingsChange} + /> <SubmitButton title={submitTitle} onClick={this.handleSubmit} diff --git a/frontend/app/views/page/components/page.editor.js b/frontend/app/views/page/components/page.editor.js index a3e8513..cd61932 100644 --- a/frontend/app/views/page/components/page.editor.js +++ b/frontend/app/views/page/components/page.editor.js @@ -24,6 +24,7 @@ const defaultState = { w: 0, h: 0, }, tile: null, + cursors: {}, } class PageEditor extends Component { @@ -62,7 +63,15 @@ class PageEditor extends Component { document.body.addEventListener('mouseup', this.handleMouseUp) window.addEventListener('resize', this.handleWindowResize) const bounds = this.getBoundingClientRect() - this.setState({ bounds }) + + let cursors = this.props.graph.show.res.uploads + .filter(upload => upload.tag === 'cursor') + .reduce((a,b) => { + a[b.id] = b + return a + }, {}) + + this.setState({ bounds, cursors }) } componentDidUpdate(prevProps) { @@ -196,6 +205,7 @@ class PageEditor extends Component { tile={tile} bounds={this.state.bounds} videoBounds={videoBounds} + cursors={this.state.cursors} box={currentTile && tile.id === currentTile.id && currentBox} onMouseDown={e => this.handleMouseDown(e, tile)} onDoubleClick={e => this.props.pageActions.showEditTileForm(tile.id)} @@ -210,6 +220,7 @@ class PageEditor extends Component { tile={temporaryTile} bounds={this.state.bounds} videoBounds={videoBounds} + cursors={this.state.cursors} box={currentTile && temporaryTile.id === currentTile.id && currentBox} onMouseDown={e => this.handleMouseDown(e, temporaryTile)} onMouseEnter={e => {}} diff --git a/frontend/app/views/page/page.actions.js b/frontend/app/views/page/page.actions.js index e42d539..4a87a7f 100644 --- a/frontend/app/views/page/page.actions.js +++ b/frontend/app/views/page/page.actions.js @@ -50,6 +50,16 @@ export const toggleTileList = () => dispatch => { dispatch({ type: types.page.toggle_tile_list }) } +// Cursor list + +export const toggleCursorList = visible => dispatch => { + dispatch({ type: types.page.toggle_cursor_list, visible }) +} + +export const pickCursor = cursor => dispatch => { + dispatch({ type: types.page.pick_cursor, cursor }) +} + // Popups export const loadPopups = (page, popups) => dispatch => { diff --git a/frontend/app/views/page/page.container.js b/frontend/app/views/page/page.container.js index 0ad9806..27cf928 100644 --- a/frontend/app/views/page/page.container.js +++ b/frontend/app/views/page/page.container.js @@ -1,5 +1,4 @@ import React, { Component } from 'react' -import { Route } from 'react-router-dom' import { bindActionCreators } from 'redux' import { connect } from 'react-redux' @@ -16,6 +15,7 @@ import PageEdit from 'app/views/graph/components/page.edit' import TileNew from 'app/views/tile/components/tile.new' import TileEdit from 'app/views/tile/components/tile.edit' import TileList from 'app/views/tile/components/tile.list' +import CursorList from 'app/views/graph/components/cursor.list' import PageHeader from './components/page.header' import PageEditor from './components/page.editor' @@ -72,6 +72,7 @@ class PageContainer extends Component { <div className='body'> <PageEditor /> <div className={this.props.page.editor.sidebarOnRight ? 'sidebar' : 'sidebar left'}> + {this.props.page.editor.cursorList && <CursorList onClick={this.props.pageActions.pickCursor} />} {this.props.graph.editor.editingPage && <PageEdit />} {this.props.page.editor.addingTile && <TileNew />} {this.props.page.editor.editingTile && <TileEdit />} diff --git a/frontend/app/views/page/page.css b/frontend/app/views/page/page.css index 2e0efb9..8e6e156 100644 --- a/frontend/app/views/page/page.css +++ b/frontend/app/views/page/page.css @@ -174,3 +174,10 @@ width: 6rem; max-width: 6rem; } + +/* sample cursor */ + +.sampleCursor { + max-width: 50px; + max-height: 50px; +} diff --git a/frontend/app/views/page/page.reducer.js b/frontend/app/views/page/page.reducer.js index a1f281a..9eb6ff7 100644 --- a/frontend/app/views/page/page.reducer.js +++ b/frontend/app/views/page/page.reducer.js @@ -11,7 +11,9 @@ const initialState = crudState('page', { tileList: false, showingPopups: true, sidebarOnRight: true, + cursorList: false, popups: {}, + pickedCursor: null, }, options: { } @@ -98,6 +100,7 @@ export default function pageReducer(state = initialState, action) { addingTile: true, editingTile: false, tileList: false, + cursorList: false, } } @@ -107,6 +110,7 @@ export default function pageReducer(state = initialState, action) { editor: { ...state.editor, addingTile: false, + cursorList: false, } } @@ -118,6 +122,7 @@ export default function pageReducer(state = initialState, action) { addingTile: !state.editor.addingTile, editingTile: false, tileList: false, + cursorList: false, } } @@ -131,6 +136,7 @@ export default function pageReducer(state = initialState, action) { editingTile: true, currentEditTileId: action.tile_id, tileList: false, + cursorList: false, } } @@ -140,6 +146,7 @@ export default function pageReducer(state = initialState, action) { editor: { ...state.editor, editingTile: false, + cursorList: false, } } @@ -152,6 +159,7 @@ export default function pageReducer(state = initialState, action) { addingTile: false, editingTile: false, tileList: true, + cursorList: false, } } @@ -161,6 +169,7 @@ export default function pageReducer(state = initialState, action) { editor: { ...state.editor, tileList: false, + cursorList: false, } } @@ -172,6 +181,7 @@ export default function pageReducer(state = initialState, action) { addingTile: false, editingTile: false, tileList: !state.editor.tileList, + cursorList: false, } } @@ -183,6 +193,27 @@ export default function pageReducer(state = initialState, action) { addingTile: false, editingTile: false, tileList: false, + cursorList: false, + } + } + + case types.page.toggle_cursor_list: + return { + ...state, + editor: { + ...state.editor, + cursorList: (typeof action.visible !== undefined) + ? action.visible : !state.editor.cursorList + } + } + + case types.page.pick_cursor: + return { + ...state, + editor: { + ...state.editor, + cursorList: false, + pickedCursor: action.cursor, } } diff --git a/frontend/app/views/tile/components/tile.form.js b/frontend/app/views/tile/components/tile.form.js index 372cd1d..b50af2f 100644 --- a/frontend/app/views/tile/components/tile.form.js +++ b/frontend/app/views/tile/components/tile.form.js @@ -54,6 +54,7 @@ class TileForm extends Component { modified: false, pageList: [], popupList: [], + cursors: {}, } constructor(props){ @@ -88,7 +89,13 @@ class TileForm extends Component { ...POPUP_LIST_TOP_OPTIONS, ...Object.keys(page.editor.popups).map(popup_group => ({ name: popup_group, label: popup_group })) ] - this.setState({ pageList, popupList }) + let cursors = this.props.graph.show.res.uploads + .filter(upload => upload.tag === 'cursor') + .reduce((a,b) => { + a[b.id] = b + return a + }, {}) + this.setState({ pageList, popupList, cursors }) if (isNew) { const newTile = TILE_CONSTRUCTORS.image({ id: "new", @@ -110,6 +117,10 @@ class TileForm extends Component { errorFields: new Set([]), }) } + if (this.props.page.editor.pickedCursor !== prevProps.page.editor.pickedCursor) { + console.log("cursor >>", this.props.page.editor.pickedCursor.id) + this.handleSettingsSelect('custom_cursor_id', this.props.page.editor.pickedCursor.id) + } } componentWillUnmount() { @@ -175,6 +186,9 @@ class TileForm extends Component { [name]: value, } }) + if (name === 'cursor' && value === 'custom') { + this.props.pageActions.toggleCursorList(true) + } } handleAlignment(name, value) { @@ -315,6 +329,7 @@ class TileForm extends Component { <TileHyperlinkForm tile={temporaryTile} errorFields={errorFields} parent={this} pageList={this.state.pageList} popupList={this.state.popupList} + cursors={this.state.cursors} /> <TileMiscForm tile={temporaryTile} errorFields={errorFields} parent={this} /> <TileSoundForm tile={temporaryTile} errorFields={errorFields} parent={this} /> diff --git a/frontend/app/views/tile/forms/tile.constants.js b/frontend/app/views/tile/forms/tile.constants.js index f2dd0ad..d7dea31 100644 --- a/frontend/app/views/tile/forms/tile.constants.js +++ b/frontend/app/views/tile/forms/tile.constants.js @@ -58,6 +58,7 @@ export const CURSORS = [ { name: 'hand_left', label: 'Left', }, { name: 'hand_right', label: 'Right', }, { name: 'unclickable', label: 'Unclickable', }, + { name: 'custom', label: 'Custom', } ] export const MARQUEE_DIRECTIONS = [ diff --git a/frontend/app/views/tile/forms/tile.form.hyperlink.js b/frontend/app/views/tile/forms/tile.form.hyperlink.js index c444748..4d3e0b5 100644 --- a/frontend/app/views/tile/forms/tile.form.hyperlink.js +++ b/frontend/app/views/tile/forms/tile.form.hyperlink.js @@ -11,12 +11,18 @@ import { NO_POPUP, OPEN_POPUP_LINK, CLOSE_POPUP_LINK } from './tile.constants' -export default function TileHyperlinkForm({ tile, pageList, popupList, parent }) { +export default function TileHyperlinkForm({ tile, pageList, popupList, cursors, parent }) { const isExternalLink = tile.target_page_id === EXTERNAL_LINK // const isPopupLink = ( // tile.target_page_id === OPEN_POPUP_LINK || // tile.target_page_id === CLOSE_POPUP_LINK // ) + let cursor + console.log(tile.settings.cursor, tile.settings.custom_cursor_id) + if (tile.settings.cursor === 'custom' && tile.settings.custom_cursor_id) { + cursor = cursors[tile.settings.custom_cursor_id] + console.log(cursor) + } return ( <div> <div className={'row selects'}> @@ -36,6 +42,9 @@ export default function TileHyperlinkForm({ tile, pageList, popupList, parent }) onChange={parent.handleSettingsSelect} /> </div> + {cursor && ( + <img src={cursor.url} className="sampleCursor" /> + )} {isExternalLink && ( <div> <TextInput diff --git a/frontend/app/views/tile/handles/tile.gradient.js b/frontend/app/views/tile/handles/tile.gradient.js index 0b20ace..8d7091f 100644 --- a/frontend/app/views/tile/handles/tile.gradient.js +++ b/frontend/app/views/tile/handles/tile.gradient.js @@ -1,7 +1,7 @@ import React from 'react' -import { generateTransform, unitsDimension, hexToRgb } from 'app/views/tile/tile.utils' +import { generateTransform, unitsDimension, hexToRgb, pickCursor } from 'app/views/tile/tile.utils' -export default function TileGradient({ tile, box, bounds, videoBounds, viewing, onMouseDown, onDoubleClick, onMouseEnter }) { +export default function TileGradient({ tile, box, bounds, cursors, videoBounds, viewing, onMouseDown, onDoubleClick, onMouseEnter }) { // console.log(tile) const style = { transform: generateTransform(tile, box, bounds, videoBounds), @@ -9,10 +9,13 @@ export default function TileGradient({ tile, box, bounds, videoBounds, viewing, } // console.log(generateTransform(tile)) let className = ['tile', tile.type].join(' ') - if (tile.target_page_id || (viewing && tile.href)) { - if (viewing || tile.settings.cursor !== 'unclickable') { - className += ' ' + (tile.settings.cursor || 'hand_up') - } + + let [cursorClass, cursorStyle] = pickCursor(tile, cursors, viewing) + if (cursorClass) { + className += " " + cursorClass + } + if (cursorStyle) { + style.cursor = cursorStyle } className += ' ' + tile.settings.align diff --git a/frontend/app/views/tile/handles/tile.image.js b/frontend/app/views/tile/handles/tile.image.js index c4d5e58..78b492e 100644 --- a/frontend/app/views/tile/handles/tile.image.js +++ b/frontend/app/views/tile/handles/tile.image.js @@ -1,7 +1,7 @@ import React from 'react' -import { generateTransform } from 'app/views/tile/tile.utils' +import { generateTransform, pickCursor } from 'app/views/tile/tile.utils' -export default function TileImage({ tile, box, bounds, videoBounds, viewing, onMouseDown, onDoubleClick, onMouseEnter }) { +export default function TileImage({ tile, box, bounds, cursors, videoBounds, viewing, onMouseDown, onDoubleClick, onMouseEnter }) { // console.log(tile) const style = { transform: generateTransform(tile, box, bounds, videoBounds), @@ -10,10 +10,13 @@ export default function TileImage({ tile, box, bounds, videoBounds, viewing, onM // console.log(generateTransform(tile)) let content let className = ['tile', tile.type].join(' ') - if (tile.target_page_id || (viewing && tile.href)) { - if (viewing || tile.settings.cursor !== 'unclickable') { - className += ' ' + (tile.settings.cursor || 'hand_up') - } + + let [cursorClass, cursorStyle] = pickCursor(tile, cursors, viewing) + if (cursorClass) { + className += " " + cursorClass + } + if (cursorStyle) { + style.cursor = cursorStyle } if (!tile.settings.url) { diff --git a/frontend/app/views/tile/handles/tile.link.js b/frontend/app/views/tile/handles/tile.link.js index 8ddc3ea..2d0e368 100644 --- a/frontend/app/views/tile/handles/tile.link.js +++ b/frontend/app/views/tile/handles/tile.link.js @@ -1,7 +1,7 @@ import React from 'react' -import { generateTransform, unitsDimension } from 'app/views/tile/tile.utils' +import { generateTransform, unitsDimension, pickCursor } from 'app/views/tile/tile.utils' -export default function TileLink({ tile, box, bounds, videoBounds, viewing, onMouseDown, onDoubleClick, onMouseEnter }) { +export default function TileLink({ tile, box, bounds, videoBounds, cursors, viewing, onMouseDown, onDoubleClick, onMouseEnter }) { // console.log(tile) const style = { transform: generateTransform(tile, box, bounds, videoBounds), @@ -9,10 +9,13 @@ export default function TileLink({ tile, box, bounds, videoBounds, viewing, onMo } // console.log(generateTransform(tile)) let className = ['tile', tile.type].join(' ') - if (tile.target_page_id || (viewing && tile.href)) { - if (viewing || tile.settings.cursor !== 'unclickable') { - className += ' ' + (tile.settings.cursor || 'hand_up') - } + + let [cursorClass, cursorStyle] = pickCursor(tile, cursors, viewing) + if (cursorClass) { + className += " " + cursorClass + } + if (cursorStyle) { + style.cursor = cursorStyle } let content = "" diff --git a/frontend/app/views/tile/handles/tile.script.js b/frontend/app/views/tile/handles/tile.script.js index e844adf..44a525b 100644 --- a/frontend/app/views/tile/handles/tile.script.js +++ b/frontend/app/views/tile/handles/tile.script.js @@ -10,7 +10,7 @@ export default class TileScript extends Component { } render() { if (viewing) { - return <div style={{ display: 'none' }} /> + return null } const { tile, box, bounds, videoBounds, viewing, onMouseDown, onDoubleClick } = this.props diff --git a/frontend/app/views/tile/handles/tile.text.js b/frontend/app/views/tile/handles/tile.text.js index 6ef8734..cfd4b30 100644 --- a/frontend/app/views/tile/handles/tile.text.js +++ b/frontend/app/views/tile/handles/tile.text.js @@ -1,8 +1,12 @@ import React from 'react' -import { generateTransform, unitsDimension, hexToRgb } from 'app/views/tile/tile.utils' +import { generateTransform, unitsDimension, hexToRgb, pickCursor } from 'app/views/tile/tile.utils' import Marquee from "react-fast-marquee" -export default function TileScript({ tile, box, bounds, videoBounds, viewing, onMouseDown, onDoubleClick, onMouseEnter }) { +export default function TileText({ tile, box, bounds, videoBounds, cursors, viewing, onMouseDown, onDoubleClick, onMouseEnter }) { + if (!tile.settings.content) { + return null + } + // console.log(tile) const style = { transform: generateTransform(tile, box, bounds, videoBounds), @@ -10,15 +14,15 @@ export default function TileScript({ tile, box, bounds, videoBounds, viewing, on } // console.log(generateTransform(tile)) let className = ['tile', tile.type].join(' ') - if (tile.target_page_id || (viewing && tile.href)) { - if (viewing || tile.settings.cursor !== 'unclickable') { - className += ' ' + (tile.settings.cursor || 'hand_up') - } - } - if (!tile.settings.content) { - return null + let [cursorClass, cursorStyle] = pickCursor(tile, cursors, viewing) + if (cursorClass) { + className += " " + cursorClass } + if (cursorStyle) { + style.cursor = cursorStyle + } + let content = <span dangerouslySetInnerHTML={{ __html: tile.settings.content }} /> className += ' ' + tile.settings.align diff --git a/frontend/app/views/tile/handles/tile.video.js b/frontend/app/views/tile/handles/tile.video.js index e8dbc72..dbcc856 100644 --- a/frontend/app/views/tile/handles/tile.video.js +++ b/frontend/app/views/tile/handles/tile.video.js @@ -1,6 +1,6 @@ import React, { Component } from 'react' -import { generateTransform, generateVideoStyle } from 'app/views/tile/tile.utils' +import { generateTransform, generateVideoStyle, pickCursor } from 'app/views/tile/tile.utils' import { timestampToSeconds } from 'app/utils' export default class TileVideo extends Component { @@ -65,22 +65,29 @@ export default class TileVideo extends Component { } render() { - let { tile, box, bounds, videoBounds, viewing, onMouseDown, onDoubleClick, onMouseEnter } = this.props + let { tile, box, bounds, videoBounds, cursors, viewing, onMouseDown, onDoubleClick, onMouseEnter } = this.props + + if (!tile.settings.url) { + return null + } + // console.log(tile) const style = { transform: generateTransform(tile, box, bounds, videoBounds), opacity: tile.settings.opacity, } + let className = ['tile', tile.type].join(' ') - if (tile.target_page_id || (viewing && tile.href)) { - if (viewing || tile.settings.cursor !== 'unclickable') { - className += ' ' + (tile.settings.cursor || 'hand_up') - } + + let [cursorClass, cursorStyle] = pickCursor(tile, cursors, viewing) + if (cursorClass) { + className += " " + cursorClass } - // console.log(tile.settings) - if (!tile.settings.url) { - return null + if (cursorStyle) { + style.cursor = cursorStyle } + + // console.log(tile.settings) className += ' ' + tile.settings.align const muted = viewing ? tile.settings.muted diff --git a/frontend/app/views/tile/tile.utils.js b/frontend/app/views/tile/tile.utils.js index 043732b..b946716 100644 --- a/frontend/app/views/tile/tile.utils.js +++ b/frontend/app/views/tile/tile.utils.js @@ -103,4 +103,24 @@ export const hexToRgb = (hex) => { g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null +} + +export const pickCursor = (tile, cursors, viewing) => { + const { cursor, custom_cursor_id } = tile.settings + const isCustom = cursor === 'custom' && custom_cursor_id in cursors + const customCursor = isCustom ? cursors[custom_cursor_id] : null + const x = isCustom ? Math.round(customCursor.settings.width / 2) : null + const y = isCustom ? Math.round(customCursor.settings.height / 2) : null + let className, cursorStyle + if (tile.target_page_id || (viewing && tile.href)) { + if ((viewing || cursor !== 'unclickable') && !isCustom) { + className = (tile.settings.cursor || 'hand_up') + } + } + if (isCustom) { + className = null + cursorStyle = `url(${customCursor.url}) ${x} ${y}, ` + cursorStyle += (tile.target_page_id || tile.href) ? 'pointer' : 'default' + } + return [className, cursorStyle] }
\ No newline at end of file diff --git a/frontend/site/site/site.reducer.js b/frontend/site/site/site.reducer.js index 9763e48..8b31786 100644 --- a/frontend/site/site/site.reducer.js +++ b/frontend/site/site/site.reducer.js @@ -5,7 +5,8 @@ const initialState = { interactive: false, graph: { loading: true, - } + }, + cursors: {}, } export default function siteReducer(state = initialState, action) { @@ -21,6 +22,7 @@ export default function siteReducer(state = initialState, action) { return { ...state, graph: action.data.graph, + cursors: buildCursors(action.data.graph), } case types.site.interact: @@ -41,3 +43,12 @@ export default function siteReducer(state = initialState, action) { return state } } + +function buildCursors(graph) { + return graph.uploads + .filter(upload => upload.tag === 'cursor') + .reduce((accumulator, item) => { + accumulator[item.id] = item + return accumulator + }, {}) +}
\ No newline at end of file diff --git a/frontend/site/viewer/viewer.container.js b/frontend/site/viewer/viewer.container.js index 24534f6..09f04c3 100644 --- a/frontend/site/viewer/viewer.container.js +++ b/frontend/site/viewer/viewer.container.js @@ -34,10 +34,10 @@ class ViewerContainer extends Component { componentDidUpdate(prevProps) { // console.log('didUpdate', this.props.graph !== prevProps.graph, this.props.location.pathname !== prevProps.location.pathname) + // console.log(this.props.location.pathname, prevProps.location.pathname, this.props.interactive) if (this.props.graph !== prevProps.graph || this.props.location.pathname !== prevProps.location.pathname) { this.load() } - console.log(this.props.location.pathname, prevProps.location.pathname, this.props.interactive) if (this.props.interactive && (this.props.interactive !== prevProps.interactive)) { this.setState({ roadblock: false }) this.props.audio.player.playPage(this.state.page) @@ -195,6 +195,7 @@ class ViewerContainer extends Component { tile={tile} audio={audio} bounds={this.state.bounds} + cursors={this.props.cursors} videoBounds={videoBounds} onMouseDown={e => this.handleMouseDown(e, tile)} onPlaybackEnded={e => this.handlePlaybackEnded(e, tile)} @@ -237,6 +238,7 @@ const mapStateToProps = state => ({ site: state.site, audio: state.audio, graph: state.site.graph, + cursors: state.site.cursors, interactive: state.site.interactive, }) |
