Skip to content

Commit

Permalink
polish edit activity ux
Browse files Browse the repository at this point in the history
- add "new script" button to blank landing page
- add animated spinner when loading data
  • Loading branch information
ngwese committed Sep 1, 2021
1 parent bff94d9 commit 74eaaf4
Show file tree
Hide file tree
Showing 8 changed files with 312 additions and 30 deletions.
1 change: 1 addition & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"react-redux": "^6.0.0",
"react-router": "^5.1.2",
"react-scripts": "1.0.17",
"react-spinners-kit": "^1.9.1",
"react-split-pane": "^0.1.74",
"react-tooltip": "^3.5.1",
"react-treebeard": "^2.1.0",
Expand Down
25 changes: 15 additions & 10 deletions web/src/bound-edit-activity.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { push as pushHistory } from 'connected-react-router'
import { push as pushHistory } from 'connected-react-router';
import EditActivity from './edit-activity';
import { MATRON_COMPONENT } from './constants';
import { MATRON_COMPONENT, UNTITLED_SCRIPT, USER_DATA_PATH } from './constants';
import { nodeForResource } from './model/listing';
import api from './api';
import { resourceToEditPath } from './url-utils'
import api, { DUST_CODE_RESOURCE } from './api';
import { resourceToEditPath } from './url-utils';

import {
rootList,
Expand All @@ -21,6 +21,7 @@ import {
toolInvoke,
explorerActiveNode,
explorerToggleNode,
explorerRevealNodeByURL,
directoryCreate,
} from './model/edit-actions';

Expand Down Expand Up @@ -122,11 +123,9 @@ const mapDispatchToProps = dispatch => ({
scriptRun: resource => {
const file = api.fileFromResource(resource);
if (file) {
if (file.includes("/lib/") ||
file.includes("/data/") ||
file.includes("/audio/")) {
console.log("files under /lib/, /data/, and /audio/ cannot be run as a script")
return undefined
if (file.includes('/lib/') || file.includes('/data/') || file.includes('/audio/')) {
console.log('files under /lib/, /data/, and /audio/ cannot be run as a script');
return undefined;
}
const cmd = `norns.script.load("${file}")`;
dispatch(replSend(MATRON_COMPONENT, cmd));
Expand All @@ -135,7 +134,7 @@ const mapDispatchToProps = dispatch => ({
}
},
scriptClear: () => {
const cmd = "norns.script.clear()";
const cmd = 'norns.script.clear()';
dispatch(replSend(MATRON_COMPONENT, cmd));
},
selectionEval: code => {
Expand Down Expand Up @@ -187,6 +186,12 @@ const mapDispatchToProps = dispatch => ({
dispatch(toggleCategory(name));
},

// editor
editorScriptNew: () => {
dispatch(scriptNew(DUST_CODE_RESOURCE, undefined, UNTITLED_SCRIPT, USER_DATA_PATH));
dispatch(explorerRevealNodeByURL(DUST_CODE_RESOURCE));
},

// config
editorConfig: resource => {
dispatch(editorConfig(resource));
Expand Down
2 changes: 1 addition & 1 deletion web/src/constants.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Set } from 'immutable';

export const UNTITLED_SCRIPT = 'UNTITLED_SCRIPT';
export const UNTITLED_SCRIPT = 'untitled.lua';

export const MATRON_COMPONENT = 'matron';
export const CRONE_COMPONENT = 'crone';
Expand Down
22 changes: 22 additions & 0 deletions web/src/edit-activity.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,28 @@
display: flex;
}

.spinner-pane {
display: flex;
height: 100%;
align-items: center;
justify-content: center;
}

.landing-pane {
color: #979797;
background-color: #F9F9F9;
display: flex;
height: 100%;
align-items: center;
justify-content: center;
}

.landing-pane > .message {
color: #757575;
font-style: italic;
text-transform: lowercase;
}

/* sytling for react-split-pane */

.Resizer {
Expand Down
38 changes: 26 additions & 12 deletions web/src/edit-activity.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import React, { Component } from 'react';
import SplitPane from 'react-split-pane';
import ReactAudioPlayer from 'react-audio-player';
import { ImpulseSpinner } from 'react-spinners-kit';
import Explorer from './explorer';
import Editor from './editor';
import ToolBar from './tool-bar';
import IconButton from './icon-button';
import { ICONS } from './svg-icons';
import { commandService } from './services';
import OS from './utils';
import { bufferIsEditable } from './model/edit-helpers';
import { bufferIsAudio } from './model/edit-helpers';
import { bufferIsEditable, bufferIsAudio } from './model/edit-helpers';
import ReplActivity from './bound-repl-activity';

import './edit-activity.css';
Expand Down Expand Up @@ -214,7 +214,7 @@ class EditActivity extends Component {

isAudio = buffer => {
return buffer && bufferIsAudio(buffer);
}
};

render() {
const activeBuffer = this.props.activeBuffer;
Expand Down Expand Up @@ -263,18 +263,28 @@ class EditActivity extends Component {

const listener = (
<div className="listener-pane">
<ReactAudioPlayer
className="listener-container"
src={activeBuffer}
autoPlay
controls
/>
<ReactAudioPlayer className="listener-container" src={activeBuffer} autoPlay controls />
</div>
);

const loading = (
// TODO: this should be a loading indicator instead of a blank frame
<div className="spinner-pane"></div>
<div className="spinner-pane">
<ImpulseSpinner frontColor="#979797" backColor="#F1F1F1" loading />
</div>
);

const landing = (
<div className="landing-pane">
<span className="message">new script</span>
<IconButton
action={() => this.props.editorScriptNew()}
tooltipMessage="new script"
tooltipPosition="bottom"
icon={ICONS.plus}
color="hsl(0, 0%, 59%)"
size="24"
/>
</div>
);

const sidebarSplitStyle = {
Expand All @@ -285,11 +295,15 @@ class EditActivity extends Component {

const explorerStyle = {
height: this.props.height,
}
};

// MAINT: this is ugly, ideally there would be states in the model which
// correspond to each pane and the whole component refactored
let element = loading;
if (buffer) {
element = canListen ? listener : editor;
} else if (!activeBuffer) {
element = landing;
}

return (
Expand Down
6 changes: 6 additions & 0 deletions web/src/model/edit-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export const TOOL_INVOKE = 'TOOL_INVOKE';

export const EXPLORER_TOGGLE_NODE = 'EXPLORER_TOGGLE_NODE';
export const EXPLORER_ACTIVE_NODE = 'EXPLORER_ACTIVE_NODE';
export const EXPLORER_REVEAL_NODE_BY_URL = 'EXPLORER_REVEAL_NODE_BY_URL';

//
// sync actions
Expand Down Expand Up @@ -172,6 +173,11 @@ export const explorerToggleNode = (node, toggled) => ({
toggled,
});

export const explorerRevealNodeByURL = url => ({
type: EXPLORER_REVEAL_NODE_BY_URL,
url,
});

//
// async actions
//
Expand Down
14 changes: 8 additions & 6 deletions web/src/model/edit-reducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,14 @@ import {
TOOL_INVOKE,
EXPLORER_ACTIVE_NODE,
EXPLORER_TOGGLE_NODE,
EXPLORER_REVEAL_NODE_BY_URL,
scriptNew,
} from './edit-actions';

import {
bufferIsEditable
} from './edit-helpers';
import { bufferIsEditable } from './edit-helpers';

import api from '../api';
import { DUST_CODE_RESOURCE } from '../api';
import api, { DUST_CODE_RESOURCE } from '../api';
import { UNTITLED_SCRIPT } from '../constants';

/*
Expand Down Expand Up @@ -93,7 +92,7 @@ const handleScriptNew = (action, state) => {
}
}

const newName = generateNodeName(siblings, action.name || 'untitled.lua');
const newName = generateNodeName(siblings, action.name || UNTITLED_SCRIPT);

let newResource;
if (siblingIsDir) {
Expand Down Expand Up @@ -336,6 +335,9 @@ const edit = (state = initialEditState, action) => {
}
return { ...state, expandedNodes: state.expandedNodes.delete(action.node.url) };

case EXPLORER_REVEAL_NODE_BY_URL:
return { ...state, expandedNodes: state.expandedNodes.add(action.url) };

default:
return state;
}
Expand Down
Loading

0 comments on commit 74eaaf4

Please sign in to comment.