diff --git a/README.md b/README.md index 6b28c306..411fd385 100644 --- a/README.md +++ b/README.md @@ -71,14 +71,8 @@ npm run dev - Visit `localhost:1337` in a browser. -### BROKEN: Run electron (MacOS) - -@jimmylee broke the current version of the client. +### Run electron (MacOS) ```sh -rm -rf .next -npm run build-electron -npm run electron-pack +npm run electron-dev ``` - -Open **Slate.app** in `dist/mac/slate.app`. diff --git a/common/navigation-data.js b/common/navigation-data.js index cb7c51c2..f5f63e51 100644 --- a/common/navigation-data.js +++ b/common/navigation-data.js @@ -31,12 +31,11 @@ export const getCurrentById = (navigation, targetId) => { }; const constructFilesTreeForNavigation = (library) => { - let bytes = 0; - library[0].children.forEach((o) => { - bytes = o.size + bytes; - }); - - return { ...library[0], name: `Data (${Strings.bytesToSize(bytes)})`, children: [] }; + return { + ...library[0], + name: `Data`, + children: [], + }; }; const constructSlatesTreeForNavigation = (slates) => { @@ -103,7 +102,7 @@ export const generate = ({ library = [], slates = [] }) => [ }, { id: 16, - name: "Developer API", + name: "API", pageTitle: "Developer API", decorator: "SETTINGS_DEVELOPER", children: null, @@ -116,16 +115,9 @@ export const generate = ({ library = [], slates = [] }) => [ children: null, ignore: true, }, - { - id: 5, - name: "Public profile", - pageTitle: "Profile Page", - decorator: "PROFILE_PAGE", - children: [], - }, { id: 2, - name: "Filecoin Wallet", + name: "Wallet", pageTitle: "Your wallet and addresses", decorator: "WALLET", children: [ diff --git a/common/styles/global.js b/common/styles/global.js index 71adee64..7cc11ceb 100644 --- a/common/styles/global.js +++ b/common/styles/global.js @@ -100,12 +100,13 @@ export const injectTooltipStyles = () => } .tippy-tooltip { - font-family: ${Constants.font.text}; + font-family: ${Constants.font.code}; color: ${Constants.system.white}; background-color: ${Constants.system.pitchBlack}; position: relative; border-radius: 4px; - font-size: 1rem; + font-size: 11px; + text-transform: uppercase; padding: 12px; text-align: center; will-change: transform; diff --git a/components/core/Application.js b/components/core/Application.js index 91dac596..d95ab0ae 100644 --- a/components/core/Application.js +++ b/components/core/Application.js @@ -350,12 +350,6 @@ export default class ApplicationPage extends React.Component { }; _handleNavigateTo = (next, data = null) => { - // TODO(jim): Refactor this hack for profile pages. - if (next.id === 5) { - window.open(`/@${this.state.viewer.username}`); - return; - } - this.state.history[this.state.currentIndex].scrollTop = window.scrollY; this.state.history[this.state.currentIndex].data = data; diff --git a/components/core/ApplicationControlMenu.js b/components/core/ApplicationControlMenu.js new file mode 100644 index 00000000..dab65feb --- /dev/null +++ b/components/core/ApplicationControlMenu.js @@ -0,0 +1,78 @@ +import * as React from "react"; +import * as Constants from "~/common/constants"; + +import { css } from "@emotion/react"; + +import Dismissible from "~/components/core/Dismissible"; + +const STYLES_AVATAR = css` + display: inline-flex; + background-size: cover; + background-position: 50% 50%; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2); + position: relative; + background-color: ${Constants.system.black}; + color: ${Constants.system.white}; + transition: 100ms ease all; + align-items: center; + justify-content: center; + + :hover { + background-color: ${Constants.system.brand}; + } +`; + +const STYLES_AVATAR_ONLINE = css` + height: 16px; + width: 16px; + background-color: ${Constants.system.green}; + border: 2px solid ${Constants.system.white}; + position: absolute; + bottom: -4px; + right: -4px; + border-radius: 16px; +`; + +export default class ApplicationControlMenu extends React.Component { + state = {}; + + _handleClick = (e) => { + if (this.props.popover) { + this.setState({ visible: !this.state.visible }); + } + + if (this.props.onClick) { + this.props.onClick(e); + } + }; + + _handleHide = () => { + this.setState({ visible: false }); + }; + + render() { + return ( + + {this.props.icon ? this.props.icon : null} + {this.state.visible ? this.props.popover : null} + {this.props.online ? : null} + + ); + } +} diff --git a/components/core/ApplicationHeader.js b/components/core/ApplicationHeader.js index abff88fe..0a49ed54 100644 --- a/components/core/ApplicationHeader.js +++ b/components/core/ApplicationHeader.js @@ -2,10 +2,12 @@ import * as React from "react"; import * as Constants from "~/common/constants"; import * as System from "~/components/system"; import * as SVG from "~/common/svg"; +import * as OldSVG from "~/components/system/svg"; import { css } from "@emotion/react"; +import { Tooltip } from "react-tippy"; -import Avatar from "~/components/core/Avatar"; +import ApplicationControlMenu from "~/components/core/ApplicationControlMenu"; const STYLES_CIRCLE = css` height: 32px; @@ -55,7 +57,7 @@ const STYLES_HOME = css` user-select: none; margin-right: 24px; margin-left: 24px; - font-size: 11px; + font-size: 14px; text-transform: uppercase; font-family: ${Constants.font.codeBold}; `; @@ -92,27 +94,37 @@ const STYLES_RIGHT = css` padding-right: 16px; `; -const STYLES_INPUT = css` - width: 100%; - max-width: 1024px; - font-size: 16px; - height: 40px; - padding: 0 16px 0 16px; - background-color: ${Constants.system.white}; - border-radius: 4px; - box-shadow: inset 0 0 0 1px #e0e0e0, 0 1px 4px rgba(0, 0, 0, 0.04); - border: 0; - outline: 0; - box-sizing: border-box; +const STYLES_PROFILE = css` + font-family: ${Constants.font.semiBold}; + background-color: ${Constants.system.pitchBlack}; + color: ${Constants.system.white}; + font-size: 12px; + line-height: 12px; + text-decoration: none; + height: 36px; + padding-right: 24px; + border-radius: 36px; + display: flex; + align-items: center; + justify-content: flex-start; transition: 200ms ease all; - :focus { - box-shadow: 0 1px 4px rgba(0, 71, 255, 0.3), - inset 0 0 0 1px ${Constants.system.brand}; - outline: 0; + :hover { + background-color: ${Constants.system.brand}; } `; +const STYLES_IMAGE = css` + background-size: cover; + background-position: 50% 50%; + flex-shrink: 0; + height: 32px; + width: 32px; + border-radius: 32px; + margin-right: 16px; + margin-left: 2px; +`; + export default class ApplicationHeader extends React.Component { render() { const isBackDisabled = @@ -125,7 +137,7 @@ export default class ApplicationHeader extends React.Component { return (
- Slate {Constants.values.version} + Slate
- {}} - size={32} - url={this.props.viewer.data.photo} - popover={ - + + - } - /> + {this.props.viewer.username} + + + + + {}} + size={36} + icon={} + popover={ + + } + /> +
); diff --git a/components/core/ApplicationNavigation.js b/components/core/ApplicationNavigation.js index a2eb134b..92be8058 100644 --- a/components/core/ApplicationNavigation.js +++ b/components/core/ApplicationNavigation.js @@ -6,6 +6,7 @@ import * as SVG from "~/common/svg"; import { css } from "@emotion/react"; import Pill from "~/components/core/Pill"; +import DataMeter from "~/components/core/DataMeter"; const IconMap = { HOME: , @@ -235,6 +236,13 @@ class NodeReference extends React.Component { export default class ApplicationNavigation extends React.Component { render() { + // TODO(jim): + // Calculate this idea elsewhere if you keep it. + let bytes = 0; + this.props.viewer.library[0].children.forEach((each) => { + bytes = each.size + bytes; + }); + return ( ); } diff --git a/components/core/DataMeter.js b/components/core/DataMeter.js new file mode 100644 index 00000000..70887497 --- /dev/null +++ b/components/core/DataMeter.js @@ -0,0 +1,130 @@ +import * as React from "react"; +import * as Constants from "~/common/constants"; +import * as Strings from "~/common/strings"; +import * as System from "~/components/system"; + +import { css } from "@emotion/react"; + +// NOTE(jim): 10 GB +const MAX_IN_BYTES = 10737418240; + +const STYLES_CONTAINER = css` + border-radius: 4px; + border: 1px solid ${Constants.system.border}; + padding: 16px; +`; + +const STYLES_GUTTER = css` + padding: 16px 16px 16px 16px; +`; + +const STYLES_DATA = css` + width: 100%; + display: flex; + align-items: center; + height: 8px; + border-radius: 3px; + background-color: ${Constants.system.border}; + overflow: hidden; +`; + +const STYLES_DATA_METER = css` + flex-shrink: 0; + height: 100%; + background-color: ${Constants.system.brand}; + background-image: linear-gradient( + 315deg, + ${Constants.system.brand} 0%, + #009ffd 74% + ); +`; + +const STYLES_ROW = css` + display: flex; + align-items: flex-end; + justify-content: space-between; + font-family: ${Constants.font.code}; + color: ${Constants.system.darkGray}; + font-size: 10px; + margin-top: 2px; + text-transform: uppercase; +`; + +const STYLES_STATS_ROW = css` + display: flex; + align-items: flex-end; + justify-content: space-between; + font-family: ${Constants.font.code}; + color: ${Constants.system.black}; + font-size: 12px; + text-transform: uppercase; +`; + +const STYLES_LEFT = css` + min-width: 10%; + width: 100% ""; +`; + +const STYLES_RIGHT = css` + flex-shrink: 0; +`; + +const STYLES_TITLE = css` + font-family: ${Constants.font.semiBold}; + font-weight: 400; + font-size: 14px; + display: block; + margin-bottom: 4px; +`; + +const STYLES_HREF = css` + font-family: ${Constants.font.semiBold}; + font-weight: 400; + cursor: pointer; + transition: 200ms ease color; + + :hover { + color: ${Constants.system.brand}; + } +`; + +export default (props) => { + const percentage = props.currentBytes / MAX_IN_BYTES; + console.log(percentage * 100); + + return ( +
+
+ + Usage + Slate users get 10GB of IPFS storage for free.{" "} + alert("TODO: SUBSCRIPTION OPTIONS")} + > + (upgrade) + +
+
+
+ +
+
{Strings.bytesToSize(props.currentBytes)}
+
{Strings.bytesToSize(MAX_IN_BYTES)}
+
+ +
+
Used
+
Total
+
+ +
+
+
+
+
+ ); +}; diff --git a/components/system/components/Input.js b/components/system/components/Input.js index 31608a84..574b5878 100644 --- a/components/system/components/Input.js +++ b/components/system/components/Input.js @@ -160,6 +160,7 @@ export class Input extends React.Component { full={this.props.full} tooltip={this.props.tooltip} label={this.props.label} + style={this.props.descriptionStyle} description={this.props.description} />
diff --git a/components/system/components/PopoverNavigation.js b/components/system/components/PopoverNavigation.js index 1b784c74..e73ec175 100644 --- a/components/system/components/PopoverNavigation.js +++ b/components/system/components/PopoverNavigation.js @@ -9,7 +9,9 @@ const STYLES_POPOVER = css` position: absolute; width: 288px; border-radius: 4px; + user-select: none; background-color: ${Constants.system.white}; + color: ${Constants.system.pitchBlack}; box-shadow: inset 0 0 0 1px ${Constants.system.border}, 0 1px 4px rgba(0, 0, 0, 0.07); `; diff --git a/scenes/SceneFilesFolder.js b/scenes/SceneFilesFolder.js index 5492f2e9..6611ec8d 100644 --- a/scenes/SceneFilesFolder.js +++ b/scenes/SceneFilesFolder.js @@ -1,6 +1,7 @@ import * as React from "react"; import * as Actions from "~/common/actions"; import * as System from "~/components/system"; +import * as Strings from "~/common/strings"; import { css } from "@emotion/react"; @@ -53,10 +54,15 @@ export default class SceneFilesFolder extends React.Component { } render() { + let bytes = 0; let rows = this.props.viewer.library[0].children.map((each) => { + bytes = each.size + bytes; return { ...each, - button: each.networks && each.networks.includes("FILECOIN") ? null : "Store on Filecoin", + button: + each.networks && each.networks.includes("FILECOIN") + ? null + : "Store on Filecoin", }; }); @@ -102,14 +108,15 @@ export default class SceneFilesFolder extends React.Component { {this.props.current.name}
+ ]} + > @@ -116,10 +118,12 @@ export default class SceneSlate extends React.Component { label="Will the Slate page look like this in the final product?" description="No! Consider this page just a functionality test. Slates will be collaborative mood boards and will have a much more intuitive experience than this." /> - - https://slate.host/@{this.props.viewer.username}/{slatename} - -
+ {slatename} +
- Changing the slatename will change your public slate URL. Your slate URL is:{" "} + Changing the slatename will change your public slate URL. Your + slate URL is:{" "} {slateURL} @@ -154,12 +160,19 @@ export default class SceneSlate extends React.Component { />
- +
- + Save changes