diff --git a/common/navigation-data.js b/common/navigation-data.js index 3aef075e..46711afc 100644 --- a/common/navigation-data.js +++ b/common/navigation-data.js @@ -32,17 +32,18 @@ export const getCurrentById = (navigation, targetId) => { const constructFilesTreeForNavigation = (library) => { return { ...library[0], - name: `Data`, - children: [ - { - id: "V1_NAVIGATION_ENCRYPTED_DATA", - decorator: "ENCRYPTED", - name: "Encrypted Data", - pageTitle: "Encrypted data", - children: null, - }, - ], - ignore: true, + id: "NAV_DATA", + decorator: "DATA", + name: "Home", + // children: [ + // { + // id: "V1_NAVIGATION_ENCRYPTED_DATA", + // decorator: "ENCRYPTED", + // name: "Encrypted Data", + // pageTitle: "Encrypted data", + // children: null, + // }, + // ], }; }; @@ -60,15 +61,17 @@ const constructFilesTreeForNavigation = (library) => { // }; export const generate = ({ library = [], slates = [] }) => [ + constructFilesTreeForNavigation(library), { - id: "V1_NAVIGATION_HOME", - decorator: "HOME", - name: "Home", + id: "NAV_ACTIVITY", + decorator: "ACTIVITY", + name: "Activity", pageTitle: "Welcome back!", children: null, + ignore: true, }, { - id: "V1_NAVIGATION_SLATES", + id: "NAV_SLATES", decorator: "SLATES", name: "Slates", pageTitle: "Slates", @@ -76,7 +79,7 @@ export const generate = ({ library = [], slates = [] }) => [ ignore: true, }, { - id: "V1_NAVIGATION_SLATES_FOLLOWING", + id: "NAV_SLATES_FOLLOWING", decorator: "SLATES_FOLLOWING", name: "Slates", pageTitle: "Slates", @@ -84,14 +87,14 @@ export const generate = ({ library = [], slates = [] }) => [ ignore: true, }, { - id: "V1_NAVIGATION_DIRECTORY", + id: "NAV_DIRECTORY", decorator: "DIRECTORY", name: "Directory", pageTitle: "Your directory", children: null, }, { - id: "V1_NAVIGATION_DIRECTORY_FOLLOWERS", + id: "NAV_DIRECTORY_FOLLOWERS", decorator: "DIRECTORY_FOLLOWERS", name: "Directory", pageTitle: "Your directory", @@ -99,15 +102,14 @@ export const generate = ({ library = [], slates = [] }) => [ ignore: true, }, { - id: "V1_NAVIGATION_SLATE", - decorator: "PUBLIC_SLATE", + id: "NAV_SLATE", + decorator: "SLATE", name: "Slate", pageTitle: "Slate", children: null, ignore: true, }, // ...constructSlatesTreeForNavigation(slates), - constructFilesTreeForNavigation(library), /* { id: "V1_NAVIGATION_LOCAL", @@ -126,7 +128,7 @@ export const generate = ({ library = [], slates = [] }) => [ }, */ { - id: "V1_NAVIGATION_ARCHIVE", + id: "NAV_FILECOIN", decorator: "FILECOIN", name: "Filecoin", pageTitle: "Archive on Filecoin", @@ -134,29 +136,29 @@ export const generate = ({ library = [], slates = [] }) => [ children: null, }, { - id: "V1_NAVIGATION_FILECOIN_STORAGE_DEAL", - decorator: "MAKE_DEAL", + id: "NAV_STORAGE_DEAL", + decorator: "STORAGE_DEAL", name: "Storage Deal", filecoin: true, pageTitle: "Make an one-off Filecoin storage deal", }, { - id: "V1_NAVIGATION_API", - decorator: "SETTINGS_DEVELOPER", + id: "NAV_API", + decorator: "API", name: "API", pageTitle: "Developer API", children: null, }, { - id: "V1_NAVIGATION_PROFILE_EDIT", - decorator: "EDIT_ACCOUNT", + id: "NAV_SETTINGS", + decorator: "SETTINGS", name: "Profile & Account Settings", pageTitle: "Your Profile & Account Settings", children: null, ignore: true, }, { - id: "V1_NAVIGATION_PROFILE", + id: "NAV_PROFILE", decorator: "PUBLIC_PROFILE", name: "Profile", pageTitle: "Profile", @@ -164,7 +166,7 @@ export const generate = ({ library = [], slates = [] }) => [ ignore: true, }, { - id: "V1_NAVIGATION_FILE", + id: "NAV_FILE", decorator: "FILE", name: "File", pageTitle: "File", diff --git a/components/core/Application.js b/components/core/Application.js index 6e4149e7..69ac8bf0 100644 --- a/components/core/Application.js +++ b/components/core/Application.js @@ -18,7 +18,6 @@ import * as Events from "~/common/custom-events"; import SceneEditAccount from "~/scenes/SceneEditAccount"; import SceneFile from "~/scenes/SceneFile"; import SceneFilesFolder from "~/scenes/SceneFilesFolder"; -import SceneHome from "~/scenes/SceneHome"; import SceneSettings from "~/scenes/SceneSettings"; import SceneSlates from "~/scenes/SceneSlates"; import SceneLocalData from "~/scenes/SceneLocalData"; @@ -75,23 +74,22 @@ const SIDEBARS = { }; const SCENES = { - HOME: , + ACTIVITY: , DIRECTORY: , PUBLIC_PROFILE: , PROFILE: , - FOLDER: , + DATA: , FILE: , - PUBLIC_SLATE: , - SLATE: , - SETTINGS_DEVELOPER: , - EDIT_ACCOUNT: , + SLATE: , + API: , + SETTINGS: , SLATES: , SLATES_FOLLOWING: , LOCAL_DATA: , DIRECTORY: , DIRECTORY_FOLLOWERS: , FILECOIN: , - MAKE_DEAL: , + STORAGE_DEAL: , }; let mounted; @@ -102,7 +100,6 @@ export default class ApplicationPage extends React.Component { state = { selected: {}, viewer: this.props.viewer, - history: [{ id: "V1_NAVIGATION_HOME", scrollTop: 0, data: null }], currentIndex: 0, data: null, sidebar: null, @@ -125,7 +122,7 @@ export default class ApplicationPage extends React.Component { window.addEventListener("online", this._handleOnlineStatus); window.addEventListener("offline", this._handleOnlineStatus); window.addEventListener("resize", this._handleWindowResize); - window.onpopstate = this._handleBrowserBack; + window.onpopstate = this._handleBackForward; if (this.state.viewer) { await this._handleSetupWebsocket(); @@ -142,7 +139,6 @@ export default class ApplicationPage extends React.Component { window.removeEventListener("online", this._handleOnlineStatus); window.removeEventListener("offline", this._handleOnlineStatus); window.removeEventListener("resize", this._handleWindowResize); - window.removeEventListener("onpopstate", this._handleBrowserBack); mounted = false; @@ -231,7 +227,13 @@ export default class ApplicationPage extends React.Component { }); const navigation = NavigationData.generate(this.state.viewer); - const next = this.state.history[this.state.currentIndex]; + let next; + if (typeof window !== "undefined") { + next = window?.history?.state; + } + if (!next || !next.id) { + next = { id: "NAV_DATA", scrollTop: 0, data: null }; + } const current = NavigationData.getCurrentById(navigation, next.id); let slate = null; @@ -425,7 +427,7 @@ export default class ApplicationPage extends React.Component { let redirected = this._handleURLRedirect(); if (!redirected) { - this._handleAction({ type: "NAVIGATE", value: "V1_NAVIGATION_HOME" }); + this._handleAction({ type: "NAVIGATE", value: "NAV_DATA" }); } return response; }; @@ -437,7 +439,7 @@ export default class ApplicationPage extends React.Component { const cid = Window.getQueryParameterByName("cid"); if (!Strings.isEmpty(id) && this.state.viewer) { - this._handleNavigateTo({ id, user, slate, cid }); + this._handleNavigateTo({ id, user, slate, cid }, null, true); return true; } return false; @@ -498,47 +500,23 @@ export default class ApplicationPage extends React.Component { }; _handleNavigateTo = (next, data = null, redirect = false) => { - if (next.id) { + if (redirect) { + window.history.replaceState( + { ...next, data }, + "Slate", + `/_${next.id ? `?scene=${next.id}` : ""}` + ); + } else { window.history.pushState( { ...next, data }, "Slate", - `` //maybe don't need to do this scene thing. b/c going to change it to the other format anyways. ideally would set the data at the same time as the string stuff. but should i put that here or inside scenepublicslate? + `/_${next.id ? `?scene=${next.id}` : ""}` ); } - if (redirect) { - const adjustedArray = [...this.state.history]; - adjustedArray.length = this.state.currentIndex; - return this.setState({ - history: [...adjustedArray, next], - data, - sidebar: null, - }); - } - let body = document.documentElement || document.body; - this.state.history[this.state.currentIndex].scrollTop = body.scrollTop; - this.state.history[this.state.currentIndex].data = this.state.data; - - if (this.state.currentIndex !== this.state.history.length - 1) { - const adjustedArray = [...this.state.history]; - adjustedArray.length = this.state.currentIndex + 1; - - return this.setState( - { - history: [...adjustedArray, next], - currentIndex: this.state.currentIndex + 1, - data, - sidebar: null, - }, - () => body.scrollTo(0, 0) - ); - } - this.setState( { - history: [...this.state.history, next], - currentIndex: this.state.currentIndex + 1, data, sidebar: null, }, @@ -546,52 +524,15 @@ export default class ApplicationPage extends React.Component { ); }; - _handleBrowserBack = (e) => { + _handleBackForward = (e) => { let next = window.history.state; + console.log(next); + window.history.replaceState({ ...next }, "Slate", `/_${next.id ? `?scene=${next.id}` : ""}`); this.setState({ + sidebar: null, data: next.data, }); - }; - - _handleBack = () => { - let body = document.documentElement || document.body; - this.state.history[this.state.currentIndex].scrollTop = body.scrollTop; - this.state.history[this.state.currentIndex].data = this.state.data; - - const next = this.state.history[this.state.currentIndex - 1]; - window.history.replaceState({ ...next }, "Slate", `?scene=${next.id}`); - - this.setState( - { - currentIndex: this.state.currentIndex - 1, - sidebar: null, - data: { ...next.data }, - }, - () => { - console.log({ next }); - body.scrollTo(0, next.scrollTop); - } - ); - }; - - _handleForward = () => { - let body = document.documentElement || document.body; - this.state.history[this.state.currentIndex].scrollTop = body.scrollTop; - const next = this.state.history[this.state.currentIndex + 1]; - - window.history.replaceState({ ...next }, "Slate", `?scene=${next.id}`); - - this.setState( - { - currentIndex: this.state.currentIndex + 1, - sidebar: null, - data: { ...next.data }, - }, - () => { - console.log({ next }); - body.scrollTo(0, next.scrollTop); - } - ); + Events.dispatchCustomEvent({ name: "slate-global-close-carousel", detail: {} }); }; render() { @@ -620,9 +561,8 @@ export default class ApplicationPage extends React.Component { next = window?.history?.state; } if (!next || !next.id) { - next = { id: "V1_NAVIGATION_HOME", scrollTop: 0, data: null }; + next = { id: "NAV_DATA", scrollTop: 0, data: null }; } - // const next = this.state.history[this.state.currentIndex]; const current = NavigationData.getCurrentById(navigation, next.id); // NOTE(jim): Only happens during a bad query parameter. @@ -636,12 +576,7 @@ export default class ApplicationPage extends React.Component { viewer={this.state.viewer} navigation={navigation} activeIds={current.activeIds} - pageTitle={current.target.pageTitle} - currentIndex={this.state.currentIndex} - history={this.state.history} onAction={this._handleAction} - onBack={this._handleBack} - onForward={this._handleForward} mobile={this.state.mobile} /> ); @@ -654,8 +589,6 @@ export default class ApplicationPage extends React.Component { onSelectedChange: this._handleSelectedChange, onAction: this._handleAction, onUpload: this._handleUploadFiles, - onBack: this._handleBack, - onForward: this._handleForward, onUpdateData: this._handleUpdateData, onUpdateViewer: this._handleUpdateViewer, sceneId: current.target.id, @@ -708,12 +641,7 @@ export default class ApplicationPage extends React.Component { onUpdateViewer={this._handleUpdateViewer} resources={this.props.resources} viewer={this.state.viewer} - current={ - current.target && - (current.target.decorator === "SLATE" || current.target.decorator === "HOME") - ? current.target - : this.state.data //NOTE(martina): for slates that are not your own - } + current={this.state.data} slates={this.state.viewer.slates} onAction={this._handleAction} mobile={this.props.mobile} diff --git a/components/core/ApplicationHeader.js b/components/core/ApplicationHeader.js index 33356168..1917c737 100644 --- a/components/core/ApplicationHeader.js +++ b/components/core/ApplicationHeader.js @@ -10,25 +10,39 @@ import { Boundary } from "~/components/system/components/fragments/Boundary"; import { PopoverNavigation } from "~/components/system"; const IconMap = { - HOME: , + // ACTIVITY: , ENCRYPTED: , NETWORK: , DIRECTORY: , - FOLDER: , + // DATA: , + DATA: , WALLET: , DEALS: , - MAKE_DEAL: , + STORAGE_DEAL: , SLATES: , SLATE: , LOCAL_DATA: , PROFILE_PAGE: , - SETTINGS_DEVELOPER: , + API: , SETTINGS: , DIRECTORY: , FILECOIN: , MINERS: , }; +const STYLES_SHORTCUTS = css` + background-color: ${Constants.system.white}; + border-radius: 2px; + height: 24px; + width: 24px; + margin-left: 4px; + font-size: 15px; + display: flex; + align-items: center; + justify-content: center; + color: ${Constants.system.textGray}; +`; + const STYLES_ICON_ELEMENT = css` height: 40px; width: 40px; @@ -112,27 +126,6 @@ const STYLES_STATIC = css` transition: 200ms ease all; `; -const STYLES_MARGIN_LEFT = css` - margin-left: 32px; - height: 40px; - width: 40px; - display: inline-flex; - align-items: center; - justify-content: center; - color: ${Constants.system.textGray}; - user-select: none; - cursor: pointer; - pointer-events: auto; - - :hover { - color: ${Constants.system.brand}; - } - - @media (max-width: ${Constants.sizes.mobile}px) { - margin-left: 16px; - } -`; - export default class ApplicationHeader extends React.Component { keysPressed = {}; @@ -179,10 +172,10 @@ export default class ApplicationHeader extends React.Component { }; render() { - const isBackDisabled = this.props.currentIndex === 0 || this.props.history.length < 2; + // const isBackDisabled = this.props.currentIndex === 0 || this.props.history.length < 2; - const isForwardDisabled = - this.props.currentIndex === this.props.history.length - 1 || this.props.history.length < 2; + // const isForwardDisabled = + // this.props.currentIndex === this.props.history.length - 1 || this.props.history.length < 2; return ( @@ -232,7 +225,7 @@ export default class ApplicationHeader extends React.Component { ) : null} - + {/* - - + */} + {/* */} + - - + - CMD+F - + + + + F + {/* */} diff --git a/components/core/ApplicationUserControls.js b/components/core/ApplicationUserControls.js index cc849883..596f29ab 100644 --- a/components/core/ApplicationUserControls.js +++ b/components/core/ApplicationUserControls.js @@ -157,7 +157,7 @@ export default class ApplicationUserControls extends React.Component { onClick: (e) => this._handleAction(e, { type: "NAVIGATE", - value: "V1_NAVIGATION_PROFILE", + value: "NAV_PROFILE", data: this.props.viewer, }), }, @@ -166,7 +166,7 @@ export default class ApplicationUserControls extends React.Component { onClick: (e) => this._handleAction(e, { type: "NAVIGATE", - value: "V1_NAVIGATION_PROFILE_EDIT", + value: "NAV_SETTINGS", }), }, { diff --git a/components/core/Profile.js b/components/core/Profile.js index 6be7f922..b56aa3b2 100644 --- a/components/core/Profile.js +++ b/components/core/Profile.js @@ -181,7 +181,7 @@ export default class Profile extends React.Component { onClose={() => this.setState({ visible: false })} viewer={this.props.viewer} open={this.state.visible} - redirectURL={`/_?scene=V1_NAVIGATION_PROFILE&user=${data.username}`} + redirectURL={`/_?scene=NAV_PROFILE&user=${data.username}`} /> )} diff --git a/components/core/SearchModal.js b/components/core/SearchModal.js index 9e6197ba..f2bee35b 100644 --- a/components/core/SearchModal.js +++ b/components/core/SearchModal.js @@ -359,7 +359,7 @@ const STYLES_INPUT = css` border: 0; box-sizing: border-box; transition: 200ms ease all; - padding: 0 16px 0 0; + padding: 0 40px 0 0; text-overflow: ellipsis; white-space: nowrap; border-radius: 0 2px 2px 0; @@ -882,21 +882,21 @@ export class SearchModal extends React.Component { if (value.type === "SLATE") { this.props.onAction({ type: "NAVIGATE", - value: "V1_NAVIGATION_SLATE", + value: "NAV_SLATE", data: value.data, }); } if (value.type === "USER") { this.props.onAction({ type: "NAVIGATE", - value: "V1_NAVIGATION_PROFILE", + value: "NAV_PROFILE", data: value.data, }); } if (value.type === "DATA_FILE") { await this.props.onAction({ type: "NAVIGATE", - value: "data", + value: "NAV_DATA", }); Events.dispatchCustomEvent({ name: "slate-global-open-carousel", @@ -906,7 +906,7 @@ export class SearchModal extends React.Component { if (value.type === "FILE") { await this.props.onAction({ type: "NAVIGATE", - value: "V1_NAVIGATION_SLATE", + value: "NAV_SLATE", data: { ...value.data.data.slate, pageState: { id: value.data.data.file.id } }, }); } diff --git a/components/core/SlateLayout.js b/components/core/SlateLayout.js index 1a7deb2a..cfdb0823 100644 --- a/components/core/SlateLayout.js +++ b/components/core/SlateLayout.js @@ -1858,7 +1858,7 @@ export class SlateLayout extends React.Component { onClose={() => this.setState({ signInModal: false })} viewer={this.props.viewer} open={this.state.signInModal} - redirectURL={`/_?scene=V1_NAVIGATION_SLATE&user=${this.props.creator.username}&slate=${this.props.slate.slatename}`} + redirectURL={`/_?scene=NAV_SLATE&user=${this.props.creator.username}&slate=${this.props.slate.slatename}`} /> )} diff --git a/components/core/SlatePreviewBlock.js b/components/core/SlatePreviewBlock.js index 490be2e5..24a1c272 100644 --- a/components/core/SlatePreviewBlock.js +++ b/components/core/SlatePreviewBlock.js @@ -429,10 +429,10 @@ export class SlatePreviewBlock extends React.Component { {this.props.slate.data.name} - + {this.props.isOwner && !this.props.slate.data.public ? ( ) : null} @@ -592,7 +592,7 @@ export default class SlatePreviewBlocks extends React.Component { onClick={() => this.props.onAction({ type: "NAVIGATE", - value: "V1_NAVIGATION_SLATE", + value: "NAV_SLATE", data: { decorator: "SLATE", ...slate }, }) } diff --git a/components/core/TabGroup.js b/components/core/TabGroup.js index e4bd8cb2..50f8f0ee 100644 --- a/components/core/TabGroup.js +++ b/components/core/TabGroup.js @@ -57,7 +57,7 @@ export class SecondaryTabGroup extends React.Component { {this.props.tabs.map((tab, i) => ( {} : () => this.props.onChange(i)} + onClick={ + this.props.disabled || this.props.value === i + ? () => {} + : this.props.onAction + ? () => this.props.onAction({ type: "NAVIGATE", value: tab.value }) + : () => this.props.onChange(i) + } > - {tab} + {this.props.onAction ? tab.title : tab} ))} @@ -84,7 +90,7 @@ export class PrimaryTabGroup extends React.Component { {this.props.tabs.map((tab, i) => ( {} : () => this.props.onChange(i)} + onClick={ + this.props.disabled || this.props.value === i + ? () => {} + : this.props.onAction + ? () => this.props.onAction({ type: "NAVIGATE", value: tab.value }) + : () => this.props.onChange(i) + } > - {tab} + {this.props.onAction ? tab.title : tab} ))} diff --git a/components/sidebars/SidebarCreateSlate.js b/components/sidebars/SidebarCreateSlate.js index 8feb2abe..bd651442 100644 --- a/components/sidebars/SidebarCreateSlate.js +++ b/components/sidebars/SidebarCreateSlate.js @@ -88,7 +88,7 @@ export default class SidebarCreateSlate extends React.Component { () => this.props.onAction({ type: "NAVIGATE", - value: "V1_NAVIGATION_SLATE", + value: "NAV_SLATE", data: { id: response.slate.id, }, diff --git a/components/sidebars/SidebarSingleSlateSettings.js b/components/sidebars/SidebarSingleSlateSettings.js index baae0811..07402612 100644 --- a/components/sidebars/SidebarSingleSlateSettings.js +++ b/components/sidebars/SidebarSingleSlateSettings.js @@ -105,7 +105,7 @@ export default class SidebarSingleSlateSettings extends React.Component { this.props.onAction({ type: "NAVIGATE", - value: "V1_NAVIGATION_SLATES", + value: "NAV_SLATES", }); const response = await Actions.deleteSlate({ diff --git a/components/system/components/GlobalCarousel.js b/components/system/components/GlobalCarousel.js index 51c3eda2..970bdf6f 100644 --- a/components/system/components/GlobalCarousel.js +++ b/components/system/components/GlobalCarousel.js @@ -97,10 +97,6 @@ const STYLES_DISMISS_BOX = css` :hover { color: ${Constants.system.white}; } - - ${"" /* @media (min-width: ${Constants.sizes.mobile}px) { - display: none; - } */} `; const STYLES_MOBILE_HIDDEN = css` @@ -168,7 +164,7 @@ export class GlobalCarousel extends React.Component { let carouselType = !this.props.current || (this.props.current && - (this.props.current.decorator === "FOLDER" || this.props.current.decorator === "HOME")) + (this.props.current.decorator === "FOLDER" || this.props.current.decorator === "ACTIVITY")) ? "data" : "slate"; this.setState({ @@ -177,22 +173,18 @@ export class GlobalCarousel extends React.Component { index: e.detail.index || 0, loading: false, saving: false, - baseURL: e.detail.baseURL, + baseURL: window.location.pathname, }); - - if ( - carouselType === "slate" && - e.detail.baseURL && - this.props.current.data && - this.props.current.data.objects - ) { - const data = this.props.current.data.objects[e.detail.index]; - window.history.replaceState( - { index: e.detail.index }, - "", - `/${e.detail.baseURL}/cid:${Strings.urlToCid(data.url)}` - ); - } + // if (carouselType === "slate" && this.props.current.data && this.props.current.data.objects) { + // const data = this.props.current.data.objects[e.detail.index]; + // console.log("WINDOW STATE"); + // console.log(window.history.state); + // window.history.pushState( + // { ...window.history.state, cid: data.cid }, + // null, + // `${window.location.pathname}/cid:${data.cid}` + // ); + // } }; _handleClose = (e) => { @@ -202,9 +194,11 @@ export class GlobalCarousel extends React.Component { } this.setState({ visible: false, index: 0, loading: false, saving: false }); - if (this.state.baseURL) { - window.history.replaceState({}, "", `/${this.state.baseURL}`); - } + // if (this.state.baseURL) { + // console.log("WINDOW STATE"); + // console.log(window.history.state); + // window.history.pushState({ ...window.history.state, cid: null }, "", this.state.baseURL); + // } }; _handleNext = () => { @@ -228,19 +222,21 @@ export class GlobalCarousel extends React.Component { } this.setState({ index, loading: false, saving: false }); - if ( - this.state.carouselType === "slate" && - this.state.baseURL && - this.props.current.data && - this.props.current.data.objects - ) { - const data = this.props.current.data.objects[index]; - window.history.replaceState( - { index }, - "", - `/${this.state.baseURL}/cid:${Strings.urlToCid(data.url)}` - ); - } + // if ( + // this.state.carouselType === "slate" && + // this.state.baseURL && + // this.props.current.data && + // this.props.current.data.objects + // ) { + // const data = this.props.current.data.objects[index]; + // console.log("WINDOW STATE"); + // console.log(window.history.state); + // window.history.pushState( + // { ...window.history.state, cid: data.cid }, + // "", + // `${this.state.baseURL}/cid:${data.cid}` + // ); + // } }; _handlePrevious = () => { @@ -262,19 +258,21 @@ export class GlobalCarousel extends React.Component { } this.setState({ index, loading: false, saving: false }); - if ( - this.state.carouselType === "slate" && - this.state.baseURL && - this.props.current.data && - this.props.current.data.objects - ) { - const data = this.props.current.data.objects[index]; - window.history.replaceState( - { index }, - "", - `/${this.state.baseURL}/cid:${Strings.urlToCid(data.url)}` - ); - } + // if ( + // this.state.carouselType === "slate" && + // this.state.baseURL && + // this.props.current.data && + // this.props.current.data.objects + // ) { + // const data = this.props.current.data.objects[index]; + // console.log("WINDOW STATE"); + // console.log(window.history.state); + // window.history.pushState( + // { ...window.history.state, cid: data.cid }, + // "", + // `${this.state.baseURL}/cid:${data.cid}` + // ); + // } }; _handleSave = async (details, index) => { diff --git a/components/system/components/fragments/TableComponents.js b/components/system/components/fragments/TableComponents.js index 86fb1814..8f2e4a83 100644 --- a/components/system/components/fragments/TableComponents.js +++ b/components/system/components/fragments/TableComponents.js @@ -289,9 +289,7 @@ export const TableContent = ({ type, text, action, data = {}, onAction }) => { } return ( - onAction({ type: "NAVIGATE", value: "V1_NAVIGATION_FILE", data })}> - {text} - + onAction({ type: "NAVIGATE", value: "NAV_FILE", data })}>{text} ); default: return text; diff --git a/pages/_/profile.js b/pages/_/profile.js index a5f16930..f222cfaf 100644 --- a/pages/_/profile.js +++ b/pages/_/profile.js @@ -60,7 +60,7 @@ export default class ProfilePage extends React.Component { viewer={this.props.viewer} open={this.state.visible} redirectURL={`/_${Strings.createQueryParams({ - scene: "V1_NAVIGATION_PROFILE", + scene: "NAV_PROFILE", user: this.props.creator.username, })}`} /> diff --git a/pages/_/slate.js b/pages/_/slate.js index 8dbce748..0a74fe34 100644 --- a/pages/_/slate.js +++ b/pages/_/slate.js @@ -344,7 +344,7 @@ export default class SlatePage extends React.Component { viewer={this.props.viewer} open={this.state.visible} redirectURL={`/_${Strings.createQueryParams({ - scene: "V1_NAVIGATION_SLATE", + scene: "NAV_SLATE", user: this.props.creator.username, slate: this.props.slate.slatename, })}`} diff --git a/scenes/SceneActivity.js b/scenes/SceneActivity.js index eafe3fdf..27b6b96c 100644 --- a/scenes/SceneActivity.js +++ b/scenes/SceneActivity.js @@ -1,16 +1,327 @@ import * as React from "react"; +import * as Constants from "~/common/constants"; +import * as Validations from "~/common/validations"; +import * as Window from "~/common/window"; +import * as SVG from "~/common/svg"; +import * as Actions from "~/common/actions"; +import * as Events from "~/common/custom-events"; +import * as System from "~/components/system"; + +import { css } from "@emotion/react"; +import { PrimaryTabGroup } from "~/components/core/TabGroup"; import ScenePage from "~/components/core/ScenePage"; +import SlateMediaObjectPreview from "~/components/core/SlateMediaObjectPreview"; import ScenePageHeader from "~/components/core/ScenePageHeader"; -// TODO(jim): Figure out the activity story. -export default class SceneActivity extends React.Component { +const STYLES_VIDEO_BIG = css` + display: block; + background-color: ${Constants.system.moonstone}; + padding: 0; + outline: 0; + margin: 48px auto 88px auto; + border-radius: 4px; + width: 100%; + box-shadow: 0px 10px 50px 20px rgba(0, 0, 0, 0.1); + + @media (max-width: ${Constants.sizes.tablet}px) { + margin: 32px auto 64px auto; + } + + @media (max-width: ${Constants.sizes.mobile}px) { + margin: 24px auto 48px auto; + } +`; + +const STYLES_IMAGE_BOX = css` + cursor: pointer; + position: relative; + box-shadow: ${Constants.shadow.light}; + margin: 10px; + + :hover { + box-shadow: ${Constants.shadow.medium}; + } +`; + +const STYLES_TEXT_AREA = css` + position: absolute; + bottom: 0px; + left: 0px; +`; + +const STYLES_TITLE = css` + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: ${Constants.system.white}; + font-family: ${Constants.font.medium}; + margin-bottom: 4px; + width: calc(100% - 32px); + padding: 0px 16px; + box-sizing: content-box; +`; + +const STYLES_SECONDARY = css` + ${STYLES_TITLE} + font-size: ${Constants.typescale.lvlN1}; + margin-bottom: 16px; + width: 100%; +`; + +const STYLES_GRADIENT = css` + background: linear-gradient( + 180deg, + rgba(0, 0, 0, 0) 0%, + rgba(0, 0, 0, 0.2) 26.56%, + rgba(0, 0, 0, 0.3) 100% + ); + backdrop-filter: blur(2px); + width: 100%; + height: 72px; + position: absolute; + bottom: 0px; + left: 0px; +`; + +const STYLES_ACTIVITY_GRID = css` + margin: -10px; + display: flex; + flex-direction: row; + flex-wrap: wrap; +`; + +class ActivitySquare extends React.Component { + state = { + showText: false, + }; + render() { + const item = this.props.item; + const size = this.props.size; + const isImage = Validations.isPreviewableImage(item.file.type); + return ( + this.setState({ showText: true }) : () => {}} + onMouseLeave={isImage ? () => this.setState({ showText: false }) : () => {}} + > + + {isImage && this.state.showText ? : null} + {this.state.showText || !isImage ? ( + + {isImage ? null : ( + + {item.file.title || item.file.name} + + )} + + {isImage ? ( + + ) : null} + {item.slate.data.name || item.slate.slatename} + + + ) : null} + + ); + } +} + +const ActivityRectangle = ({ item, size }) => { + let file; + for (let obj of item.slate?.data?.objects || []) { + if (Validations.isPreviewableImage(obj.type) || obj.coverImage) { + file = obj; + } + } + let numObjects = item.slate?.data?.objects?.length || 0; + return ( + + {file ? ( + + ) : null} + + + + {item.slate.data.name || item.slate.slatename} + + + {numObjects} File{numObjects == 1 ? "" : "s"} + + + + ); +}; + +export default class SceneActivity extends React.Component { + state = { + imageSize: 200, + tab: 0, + }; + + async componentDidMount() { + this.calculateWidth(); + this.debounceInstance = Window.debounce(this.calculateWidth, 200); + window.addEventListener("resize", this.debounceInstance); + //slates with no previewable images in them? + //filter to remove ones you no longer follow + } + + componentWillUnmount() { + window.removeEventListener("resize", this.debounceInstance); + } + + _handleCreateSlate = () => { + this.props.onAction({ + type: "NAVIGATE", + value: "NAV_SLATES", + data: null, + }); + }; + + calculateWidth = () => { + let windowWidth = window.innerWidth; + let imageSize; + if (windowWidth < Constants.sizes.mobile) { + imageSize = (windowWidth - 2 * 24 - 20) / 2; + } else { + imageSize = (windowWidth - 2 * 56 - 5 * 20) / 6; + } + this.setState({ imageSize }); + }; + + render() { + let activity = this.props.viewer.activity; return ( - - This scene is currently a work in progress. - + + } + /> + {activity.length ? ( + + {activity.map((item) => { + if (item.data.type === "SUBSCRIBED_CREATE_SLATE") { + return ( + + this.props.onAction({ + type: "NAVIGATE", + value: "NAV_SLATE", + data: { decorator: "SLATE", ...item.data.context.slate }, + }) + } + > + + + ); + } else if (item.data.type === "SUBSCRIBED_ADD_TO_SLATE") { + return ( + { + this.props.onAction({ + type: "NAVIGATE", + value: "NAV_SLATE", + data: { + decorator: "SLATE", + ...item.data.context.slate, + pageState: { + cid: item.data.context.file.cid, + }, + }, + }); + }} + > + + + ); + } else { + return null; + } + })} + + ) : ( + + When you're ready, create a slate! + + + Create a slate + + + + )} ); } diff --git a/scenes/SceneDirectory.js b/scenes/SceneDirectory.js index 359d725b..760ff142 100644 --- a/scenes/SceneDirectory.js +++ b/scenes/SceneDirectory.js @@ -474,15 +474,12 @@ export default class SceneDirectory extends React.Component { { - if (value === 0) { - this.props.onAction({ type: "NAVIGATE", value: "V1_NAVIGATION_DIRECTORY" }); - } else { - this.props.onAction({ type: "NAVIGATE", value: "V1_NAVIGATION_DIRECTORY_FOLLOWERS" }); - } - }} + onAction={this.props.onAction} /> {/* {this.props.tab === 0 ? ( requests && requests.length ? ( diff --git a/scenes/SceneFile.js b/scenes/SceneFile.js index ec7e69ef..8730d39c 100644 --- a/scenes/SceneFile.js +++ b/scenes/SceneFile.js @@ -81,7 +81,7 @@ export default class SceneFile extends React.Component { {fileURL} - this.props.onBack()}> + diff --git a/scenes/SceneFilesFolder.js b/scenes/SceneFilesFolder.js index e74d1687..4a386cd2 100644 --- a/scenes/SceneFilesFolder.js +++ b/scenes/SceneFilesFolder.js @@ -25,15 +25,13 @@ export default class SceneFilesFolder extends React.Component { { - if (value === 2) { - this.props.onAction({ type: "NAVIGATE", value: "V1_NAVIGATION_SLATES" }); - } else if (value === 0) { - this.props.onAction({ type: "NAVIGATE", value: "V1_NAVIGATION_HOME" }); - } - }} + tabs={[ + { title: "Files", value: "NAV_DATA" }, + { title: "Slates", value: "NAV_SLATES" }, + { title: "Activity", value: "NAV_ACTIVITY" }, + ]} + value={0} + onAction={this.props.onAction} /> } actions={ diff --git a/scenes/SceneHome.js b/scenes/SceneHome.js deleted file mode 100644 index e3c47dce..00000000 --- a/scenes/SceneHome.js +++ /dev/null @@ -1,340 +0,0 @@ -import * as React from "react"; -import * as Constants from "~/common/constants"; -import * as Validations from "~/common/validations"; -import * as Window from "~/common/window"; -import * as SVG from "~/common/svg"; -import * as Actions from "~/common/actions"; -import * as Events from "~/common/custom-events"; -import * as System from "~/components/system"; - -import { css } from "@emotion/react"; -import { PrimaryTabGroup } from "~/components/core/TabGroup"; - -import ScenePage from "~/components/core/ScenePage"; -import SlateMediaObjectPreview from "~/components/core/SlateMediaObjectPreview"; -import ScenePageHeader from "~/components/core/ScenePageHeader"; - -const STYLES_VIDEO_BIG = css` - display: block; - background-color: ${Constants.system.moonstone}; - padding: 0; - outline: 0; - margin: 48px auto 88px auto; - border-radius: 4px; - width: 100%; - box-shadow: 0px 10px 50px 20px rgba(0, 0, 0, 0.1); - - @media (max-width: ${Constants.sizes.tablet}px) { - margin: 32px auto 64px auto; - } - - @media (max-width: ${Constants.sizes.mobile}px) { - margin: 24px auto 48px auto; - } -`; - -const STYLES_IMAGE_BOX = css` - cursor: pointer; - position: relative; - box-shadow: ${Constants.shadow.light}; - margin: 10px; - - :hover { - box-shadow: ${Constants.shadow.medium}; - } -`; - -const STYLES_PROFILE_IMAGE_BOX = css` - background-size: cover; - background-position: 50% 50%; - position: relative; - border-radius: 4px; - position: absolute; - top: 16px; - left: 16px; - width: 24px; - height: 24px; -`; - -const STYLES_TEXT_AREA = css` - position: absolute; - bottom: 16px; - left: 16px; -`; - -const STYLES_TITLE = css` - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - color: ${Constants.system.white}; - font-family: ${Constants.font.medium}; - margin-bottom: 4px; -`; - -const STYLES_SECONDARY = css` - ${STYLES_TITLE} - font-size: ${Constants.typescale.lvlN1}; - margin-bottom: 0px; -`; - -const STYLES_GRADIENT = css` - background: linear-gradient( - 180deg, - rgba(0, 0, 0, 0) 0%, - rgba(0, 0, 0, 0.2) 26.56%, - rgba(0, 0, 0, 0.3) 100% - ); - backdrop-filter: blur(2px); - width: 100%; - height: 72px; - position: absolute; - bottom: 0px; - left: 0px; -`; - -const STYLES_ACTIVITY_GRID = css` - margin: -10px; - display: flex; - flex-direction: row; - flex-wrap: wrap; -`; - -class ActivitySquare extends React.Component { - state = { - showText: false, - }; - - render() { - const item = this.props.item; - const size = this.props.size; - const isImage = Validations.isPreviewableImage(item.file.type); - return ( - this.setState({ showText: true })} - onMouseLeave={() => this.setState({ showText: false })} - > - - {isImage && this.state.showText ? : null} - {this.state.showText ? ( - - {isImage ? null : ( - - {item.file.title || item.file.name} - - )} - - {isImage ? ( - - ) : null} - {item.slate.data.name || item.slate.slatename} - - - ) : null} - - ); - } -} - -const ActivityRectangle = ({ item, size }) => { - let file; - for (let obj of item.slate?.data?.objects || []) { - if (Validations.isPreviewableImage(obj.type) || obj.coverImage) { - file = obj; - } - } - let numObjects = item.slate?.data?.objects?.length || 0; - return ( - - {file ? ( - - ) : null} - - - - {item.slate.data.name || item.slate.slatename} - - - {numObjects} File{numObjects == 1 ? "" : "s"} - - - - ); -}; - -export default class SceneHome extends React.Component { - state = { - imageSize: 200, - tab: 0, - }; - - async componentDidMount() { - this.calculateWidth(); - this.debounceInstance = Window.debounce(this.calculateWidth, 200); - window.addEventListener("resize", this.debounceInstance); - //slates with no previewable images in them? - //filter to remove ones you no longer follow - } - - componentWillUnmount() { - window.removeEventListener("resize", this.debounceInstance); - } - - _handleCreateSlate = () => { - this.props.onAction({ - type: "NAVIGATE", - value: "V1_NAVIGATION_SLATES", - data: null, - }); - }; - - calculateWidth = () => { - let windowWidth = window.innerWidth; - let imageSize; - if (windowWidth < Constants.sizes.mobile) { - imageSize = (windowWidth - 2 * 24 - 20) / 2; - } else { - imageSize = (windowWidth - 2 * 56 - 5 * 20) / 6; - } - this.setState({ imageSize }); - }; - - render() { - let activity = this.props.viewer.activity; - return ( - - { - if (value === 1) { - this.props.onAction({ type: "NAVIGATE", value: "data" }); - } else if (value === 2) { - this.props.onAction({ type: "NAVIGATE", value: "V1_NAVIGATION_SLATES" }); - } - }} - /> - } - /> - {activity.length ? ( - - {activity.map((item) => { - if (item.data.type === "SUBSCRIBED_CREATE_SLATE") { - return ( - - this.props.onAction({ - type: "NAVIGATE", - value: "V1_NAVIGATION_SLATE", - data: { decorator: "SLATE", ...item.data.context.slate }, - }) - } - > - - - ); - } else if (item.data.type === "SUBSCRIBED_ADD_TO_SLATE") { - return ( - { - this.props.onAction({ - type: "NAVIGATE", - value: "V1_NAVIGATION_SLATE", - data: { - decorator: "SLATE", - ...item.data.context.slate, - pageState: { - cid: item.data.context.file.cid, - }, - }, - }); - }} - > - - - ); - } else { - return null; - } - })} - - ) : ( - - When you're ready, create a slate! - - - Create a slate - - - - )} - - ); - } -} diff --git a/scenes/SceneMakeFilecoinDeal.js b/scenes/SceneMakeFilecoinDeal.js index 66820527..436499a0 100644 --- a/scenes/SceneMakeFilecoinDeal.js +++ b/scenes/SceneMakeFilecoinDeal.js @@ -204,7 +204,7 @@ export default class SceneMakeFilecoinDeal extends React.Component { "Your storage deal was put in the queue. This can take up to 36 hours, check back later." ); - this.props.onAction({ type: "NAVIGATE", value: "V1_NAVIGATION_ARCHIVE" }); + this.props.onAction({ type: "NAVIGATE", value: "NAV_FILECOIN" }); }; _handleRemove = async (cid) => { diff --git a/scenes/ScenePublicProfile.js b/scenes/ScenePublicProfile.js index e8240379..167f3830 100644 --- a/scenes/ScenePublicProfile.js +++ b/scenes/ScenePublicProfile.js @@ -41,7 +41,7 @@ export default class ScenePublicProfile extends React.Component { }; fetchProfile = async () => { - const username = Window.getQueryParameterByName("user"); + const { user: username } = window.history.state; let query; if (username) { query = { username: username }; diff --git a/scenes/ScenePublicSlate.js b/scenes/ScenePublicSlate.js index a8c87ee6..907b84bd 100644 --- a/scenes/ScenePublicSlate.js +++ b/scenes/ScenePublicSlate.js @@ -43,21 +43,11 @@ export default class ScenePublicSlate extends React.Component { }; fetchSlate = async () => { + const { user: username, slate: slatename, cid } = window.history.state; + const pageState = this.props.data?.pageState; - const username = Window.getQueryParameterByName("user"); - const slatename = Window.getQueryParameterByName("slate"); - const cid = Window.getQueryParameterByName("cid"); - if ( - !this.props.data && - !username && - !slatename && - this.props.viewer.slates && - this.props.viewer.slates.length - ) { - this.props.onAction({ - type: "NAVIGATE", - value: this.props.viewer.slates[0].id, - }); + if (!this.props.data && (!username || !slatename)) { + this.setState({ notFound: true }); return; } @@ -83,9 +73,10 @@ export default class ScenePublicSlate extends React.Component { return; } } + if (slate) { window.history.replaceState( - window.history.state, + { ...window.history.state, data: slate }, "Slate", `/${this.props.viewer.username}/${slate.slatename}` ); @@ -108,60 +99,12 @@ export default class ScenePublicSlate extends React.Component { } slate = response.data; window.history.replaceState( - window.history.state, + { ...window.history.state, data: slate }, "Slate", `/${response.data.user.username}/${response.data.slatename}` ); } - // let slateIds = this.props.viewer.slates.map((slate) => slate.id); - // if (this.props.data && this.props.data.id && slateIds.includes(this.props.data.id)) { - // this.props.onAction({ - // type: "NAVIGATE", - // value: this.props.data.id, - // redirect: true, - // }); - // return; - // } - - // if (username === this.props.viewer.username) { - // for (let slate of this.props.viewer.slates) { - // if (slate.slatename === slatename) { - // this.props.onAction({ - // type: "NAVIGATE", - // value: slate.id, - // redirect: true, - // }); - // return; - // } - // } - // Events.dispatchMessage({ message: "We're having trouble fetching that slate right now." }); - // this.setState({ notFound: true }); - // return; - // } - - // let query; - // if (username && slatename) { - // query = { username, slatename }; - // } else if (this.props.data && this.props.data.id) { - // query = { id: this.props.data.id }; - // } - // let response; - // if (query) { - // response = await Actions.getSerializedSlate(query); - // } - - // if (Events.hasError(response)) { - // this.setState({ notFound: true }); - // return; - // } - - // window.history.replaceState( - // window.history.state, - // "Slate", - // `/${response.data.user.username}/${response.data.slatename}` - // ); - this.props.onUpdateData({ data: slate }); await this.setState({ slate }); diff --git a/scenes/SceneSlate.js b/scenes/SceneSlate.js index 0004dbb6..6469f8cd 100644 --- a/scenes/SceneSlate.js +++ b/scenes/SceneSlate.js @@ -213,7 +213,7 @@ export default class SceneSlate extends React.Component { - {isPublic ? ( + {/* {isPublic ? ( @@ -231,7 +231,7 @@ export default class SceneSlate extends React.Component { > {this.state.copying ? : } - ) : null} + ) : null} */} diff --git a/scenes/SceneSlates.js b/scenes/SceneSlates.js index 25ec8a54..f3ad7dda 100644 --- a/scenes/SceneSlates.js +++ b/scenes/SceneSlates.js @@ -42,31 +42,23 @@ export default class SceneSlates extends React.Component { { - if (value === 1) { - this.props.onAction({ type: "NAVIGATE", value: "data" }); - } else if (value === 0) { - this.props.onAction({ type: "NAVIGATE", value: "V1_NAVIGATION_HOME" }); - } - }} + tabs={[ + { title: "Files", value: "NAV_DATA" }, + { title: "Slates", value: "NAV_SLATES" }, + { title: "Activity", value: "NAV_ACTIVITY" }, + ]} + value={1} + onAction={this.props.onAction} /> } actions={ { - if (value === 0) { - this.props.onAction({ type: "NAVIGATE", value: "V1_NAVIGATION_SLATES" }); - } else { - this.props.onAction({ - type: "NAVIGATE", - value: "V1_NAVIGATION_SLATES_FOLLOWING", - }); - } - }} + onAction={this.props.onAction} style={{ margin: "0 0 24px 0" }} /> } diff --git a/server.js b/server.js index 23c25600..bdbb4ef7 100644 --- a/server.js +++ b/server.js @@ -211,7 +211,7 @@ app.prepare().then(async () => { if (shouldViewerRedirect) { return res.redirect( `/_${Strings.createQueryParams({ - scene: "V1_NAVIGATION_PROFILE", + scene: "NAV_PROFILE", user: req.params.username, })}` ); @@ -304,7 +304,7 @@ app.prepare().then(async () => { if (shouldViewerRedirect) { return res.redirect( `/_${Strings.createQueryParams({ - scene: "V1_NAVIGATION_SLATE", + scene: "NAV_SLATE", user: req.params.username, slate: req.params.slatename, })}` @@ -370,7 +370,7 @@ app.prepare().then(async () => { if (shouldViewerRedirect) { return res.redirect( `/_${Strings.createQueryParams({ - scene: "V1_NAVIGATION_SLATE", + scene: "NAV_SLATE", user: req.params.username, slate: req.params.slatename, cid: req.params.cid,
CMD+F