2020-07-29 19:07:13 +03:00
import * as React from "react" ;
import * as NavigationData from "~/common/navigation-data" ;
import * as Actions from "~/common/actions" ;
2020-09-12 09:13:10 +03:00
import * as Strings from "~/common/strings" ;
2020-07-29 19:07:13 +03:00
import * as State from "~/common/state" ;
import * as Credentials from "~/common/credentials" ;
2020-08-02 09:00:04 +03:00
import * as Validations from "~/common/validations" ;
2020-08-20 08:20:18 +03:00
import * as FileUtilities from "~/common/file-utilities" ;
2020-08-09 11:38:16 +03:00
import * as System from "~/components/system" ;
2020-09-12 08:54:54 +03:00
import * as Window from "~/common/window" ;
2020-07-29 19:07:13 +03:00
// NOTE(jim):
// Scenes each have an ID and can be navigated to with _handleAction
import SceneDeals from "~/scenes/SceneDeals" ;
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 SceneWallet from "~/scenes/SceneWallet" ;
import SceneSlates from "~/scenes/SceneSlates" ;
import SceneLocalData from "~/scenes/SceneLocalData" ;
import SceneSettingsDeveloper from "~/scenes/SceneSettingsDeveloper" ;
import SceneSignIn from "~/scenes/SceneSignIn" ;
import SceneSlate from "~/scenes/SceneSlate" ;
2020-08-08 03:17:54 +03:00
import SceneActivity from "~/scenes/SceneActivity" ;
2020-08-18 22:41:41 +03:00
import SceneDirectory from "~/scenes/SceneDirectory" ;
2020-08-31 21:19:46 +03:00
import SceneProfile from "~/scenes/SceneProfile" ;
2020-09-03 10:33:43 +03:00
import SceneSentinel from "~/scenes/SceneSentinel" ;
2020-09-03 06:26:56 +03:00
import ScenePublicProfile from "~/scenes/ScenePublicProfile" ;
import ScenePublicSlate from "~/scenes/ScenePublicSlate" ;
2020-09-10 02:52:45 +03:00
import SceneArchive from "~/scenes/SceneArchive" ;
2020-09-23 01:01:36 +03:00
import SceneMakeFilecoinDeal from "~/scenes/SceneMakeFilecoinDeal" ;
2020-09-25 08:14:19 +03:00
import SceneEncryptedData from "~/scenes/SceneEncryptedData" ;
2020-09-27 19:38:20 +03:00
import SceneMiners from "~/scenes/SceneMiners" ;
2020-07-29 19:07:13 +03:00
// NOTE(jim):
// Sidebars each have a decorator and can be shown to with _handleAction
import SidebarCreateSlate from "~/components/sidebars/SidebarCreateSlate" ;
import SidebarCreateWalletAddress from "~/components/sidebars/SidebarCreateWalletAddress" ;
import SidebarWalletSendFunds from "~/components/sidebars/SidebarWalletSendFunds" ;
import SidebarFileStorageDeal from "~/components/sidebars/SidebarFileStorageDeal" ;
import SidebarAddFileToBucket from "~/components/sidebars/SidebarAddFileToBucket" ;
2020-09-23 23:52:00 +03:00
import SidebarAddFileToSlate from "~/components/sidebars/SidebarAddFileToSlate" ;
2020-08-02 10:55:55 +03:00
import SidebarDragDropNotice from "~/components/sidebars/SidebarDragDropNotice" ;
2020-08-09 11:08:46 +03:00
import SidebarSingleSlateSettings from "~/components/sidebars/SidebarSingleSlateSettings" ;
2020-08-28 09:57:04 +03:00
import SidebarFilecoinArchive from "~/components/sidebars/SidebarFilecoinArchive" ;
2020-09-17 02:26:15 +03:00
import SidebarHelp from "~/components/sidebars/SidebarHelp" ;
2020-07-29 19:07:13 +03:00
// NOTE(jim):
// Core components to the application structure.
import ApplicationNavigation from "~/components/core/ApplicationNavigation" ;
import ApplicationHeader from "~/components/core/ApplicationHeader" ;
import ApplicationLayout from "~/components/core/ApplicationLayout" ;
import WebsitePrototypeWrapper from "~/components/core/WebsitePrototypeWrapper" ;
import Cookies from "universal-cookie" ;
2020-09-13 03:53:36 +03:00
import { GlobalViewerCID } from "~/components/core/viewers/GlobalViewerCID" ;
2020-09-03 09:00:02 +03:00
import { dispatchCustomEvent } from "~/common/custom-events" ;
2020-09-25 06:16:10 +03:00
import { Alert , UploadingAlert } from "~/components/core/Alert" ;
2020-09-03 09:00:02 +03:00
2020-07-29 19:07:13 +03:00
const cookies = new Cookies ( ) ;
2020-08-14 12:17:19 +03:00
const SIDEBARS = {
2020-08-28 09:57:04 +03:00
SIDEBAR _FILECOIN _ARCHIVE : < SidebarFilecoinArchive / > ,
2020-08-14 12:17:19 +03:00
SIDEBAR _FILE _STORAGE _DEAL : < SidebarFileStorageDeal / > ,
SIDEBAR _WALLET _SEND _FUNDS : < SidebarWalletSendFunds / > ,
SIDEBAR _CREATE _WALLET _ADDRESS : < SidebarCreateWalletAddress / > ,
SIDEBAR _ADD _FILE _TO _BUCKET : < SidebarAddFileToBucket / > ,
2020-09-23 23:52:00 +03:00
SIDEBAR _ADD _FILE _TO _SLATE : < SidebarAddFileToSlate / > ,
2020-08-14 12:17:19 +03:00
SIDEBAR _CREATE _SLATE : < SidebarCreateSlate / > ,
SIDEBAR _DRAG _DROP _NOTICE : < SidebarDragDropNotice / > ,
SIDEBAR _SINGLE _SLATE _SETTINGS : < SidebarSingleSlateSettings / > ,
2020-09-17 02:26:15 +03:00
SIDEBAR _HELP : < SidebarHelp / > ,
2020-08-14 12:17:19 +03:00
} ;
const SCENES = {
HOME : < SceneHome / > ,
2020-08-31 21:19:46 +03:00
DIRECTORY : < SceneDirectory / > ,
2020-09-03 06:26:56 +03:00
PUBLIC _PROFILE : < ScenePublicProfile / > ,
2020-09-04 01:42:08 +03:00
PROFILE : < SceneProfile / > ,
2020-08-14 12:17:19 +03:00
WALLET : < SceneWallet / > ,
FOLDER : < SceneFilesFolder / > ,
FILE : < SceneFile / > ,
2020-09-04 01:42:08 +03:00
PUBLIC _SLATE : < ScenePublicSlate / > ,
2020-08-14 12:17:19 +03:00
SLATE : < SceneSlate / > ,
DEALS : < SceneDeals / > ,
SETTINGS : < SceneSettings / > ,
SETTINGS _DEVELOPER : < SceneSettingsDeveloper / > ,
EDIT _ACCOUNT : < SceneEditAccount / > ,
SLATES : < SceneSlates / > ,
LOCAL _DATA : < SceneLocalData / > ,
2020-09-03 10:33:43 +03:00
NETWORK : < SceneSentinel / > ,
2020-08-18 22:41:41 +03:00
DIRECTORY : < SceneDirectory / > ,
2020-09-09 20:56:35 +03:00
FILECOIN : < SceneArchive / > ,
2020-09-23 01:01:36 +03:00
MAKE _DEAL : < SceneMakeFilecoinDeal / > ,
2020-09-25 08:14:19 +03:00
ENCRYPTED : < SceneEncryptedData / > ,
2020-09-27 19:38:20 +03:00
MINERS : < SceneMiners / > ,
2020-08-14 12:17:19 +03:00
} ;
2020-07-29 19:07:13 +03:00
export default class ApplicationPage extends React . Component {
2020-08-31 21:19:46 +03:00
_body ;
2020-07-29 19:07:13 +03:00
state = {
2020-08-25 09:46:02 +03:00
selected : { } ,
viewer : this . props . viewer ,
2020-08-18 22:28:33 +03:00
history : [ { id : "V1_NAVIGATION_HOME" , scrollTop : 0 , data : null } ] ,
2020-07-29 19:07:13 +03:00
currentIndex : 0 ,
data : null ,
sidebar : null ,
sidebarLoading : false ,
2020-08-03 00:09:55 +03:00
online : null ,
2020-09-27 00:15:37 +03:00
sidebar : null ,
2020-07-29 19:07:13 +03:00
} ;
async componentDidMount ( ) {
window . addEventListener ( "dragenter" , this . _handleDragEnter ) ;
window . addEventListener ( "dragleave" , this . _handleDragLeave ) ;
window . addEventListener ( "dragover" , this . _handleDragOver ) ;
window . addEventListener ( "drop" , this . _handleDrop ) ;
2020-08-03 00:09:55 +03:00
window . addEventListener ( "online" , this . _handleOnlineStatus ) ;
window . addEventListener ( "offline" , this . _handleOnlineStatus ) ;
2020-09-12 08:54:54 +03:00
const id = Window . getQueryParameterByName ( "scene" ) ;
2020-09-12 09:13:10 +03:00
if ( ! Strings . isEmpty ( id ) && this . state . viewer ) {
2020-09-12 08:54:54 +03:00
return this . _handleNavigateTo ( { id } ) ;
}
2020-07-29 19:07:13 +03:00
}
componentWillUnmount ( ) {
window . removeEventListener ( "dragenter" , this . _handleDragEnter ) ;
window . removeEventListener ( "dragleave" , this . _handleDragLeave ) ;
window . removeEventListener ( "dragover" , this . _handleDragOver ) ;
window . removeEventListener ( "drop" , this . _handleDrop ) ;
}
2020-08-03 00:09:55 +03:00
_handleOnlineStatus = async ( ) => {
2020-09-12 01:25:33 +03:00
if ( navigator . onLine ) {
dispatchCustomEvent ( {
name : "create-alert" ,
detail : { alert : { message : "Back online!" , status : "INFO" } } ,
} ) ;
} else {
dispatchCustomEvent ( {
name : "create-alert" ,
detail : { alert : { message : "Offline. Trying to reconnect" } } ,
} ) ;
}
2020-08-03 00:09:55 +03:00
this . setState ( { online : navigator . onLine } ) ;
} ;
2020-09-21 00:34:31 +03:00
_handleDrop = async ( e ) => {
2020-09-25 06:16:10 +03:00
this . _handleDismissSidebar ( ) ;
2020-09-21 00:34:31 +03:00
// NOTE(jim): If this is true, then drag and drop came from a slate object.
const data = e . dataTransfer . getData ( "slate-object-drag-data" ) ;
if ( data ) {
return ;
}
e . preventDefault ( ) ;
// TODO(jim): Refactor later
const navigation = NavigationData . generate ( this . state . viewer ) ;
const next = this . state . history [ this . state . currentIndex ] ;
const current = NavigationData . getCurrentById ( navigation , next . id ) ;
let slate = null ;
if ( current . target && current . target . slateId ) {
slate = { id : current . target . slateId } ;
}
const files = [ ] ;
let fileLoading = { } ;
2020-09-25 06:16:10 +03:00
// let sidebarOpen = false;
2020-09-21 00:34:31 +03:00
if ( e . dataTransfer . items && e . dataTransfer . items . length ) {
for ( var i = 0 ; i < e . dataTransfer . items . length ; i ++ ) {
if ( e . dataTransfer . items [ i ] . kind === "file" ) {
var file = e . dataTransfer . items [ i ] . getAsFile ( ) ;
2020-09-25 06:16:10 +03:00
// if (!sidebarOpen) {
// this._handleAction({
// type: "SIDEBAR",
// value: "SIDEBAR_ADD_FILE_TO_BUCKET",
// data: slate,
// });
// sidebarOpen = true;
// }
2020-09-20 21:31:08 +03:00
2020-09-21 00:34:31 +03:00
files . push ( file ) ;
fileLoading [ ` ${ file . lastModified } - ${ file . name } ` ] = {
name : file . name ,
loaded : 0 ,
total : file . size ,
} ;
}
}
}
if ( ! files . length ) {
2020-09-20 21:31:08 +03:00
dispatchCustomEvent ( {
name : "create-alert" ,
detail : {
alert : {
2020-09-21 00:34:31 +03:00
message : "File type not supported. Please try a different file" ,
2020-09-20 21:31:08 +03:00
} ,
} ,
} ) ;
2020-09-21 00:34:31 +03:00
return ;
2020-09-20 21:31:08 +03:00
}
2020-09-21 00:34:31 +03:00
// NOTE(jim): Stages each file.
this . _handleRegisterFileLoading ( { fileLoading } ) ;
2020-09-25 06:16:10 +03:00
this . _handleUpload ( { files , slate , keys : Object . keys ( fileLoading ) } ) ;
2020-09-20 21:31:08 +03:00
} ;
2020-09-25 09:42:21 +03:00
_handleUploadFiles = async ( { files , slate } ) => {
2020-09-20 21:31:08 +03:00
let toUpload = [ ] ;
let fileLoading = { } ;
let someFailed = false ;
for ( let i = 0 ; i < files . length ; i ++ ) {
let file = files [ i ] ;
if ( ! file ) {
someFailed = true ;
continue ;
}
toUpload . push ( file ) ;
fileLoading [ ` ${ file . lastModified } - ${ file . name } ` ] = {
name : file . name ,
loaded : 0 ,
total : file . size ,
} ;
}
if ( ! toUpload . length ) {
dispatchCustomEvent ( {
name : "create-alert" ,
detail : {
alert : { message : "We could not find any files to upload." } ,
} ,
} ) ;
return false ;
}
2020-09-20 23:38:27 +03:00
if ( someFailed ) {
dispatchCustomEvent ( {
name : "create-alert" ,
detail : {
alert : { message : "Some of your files could not be uploaded" } ,
} ,
} ) ;
}
2020-09-20 21:31:08 +03:00
this . _handleRegisterFileLoading ( { fileLoading } ) ;
2020-09-25 06:16:10 +03:00
this . _handleUpload ( {
files : toUpload ,
slate ,
keys : Object . keys ( fileLoading ) ,
} ) ;
2020-09-21 00:34:31 +03:00
} ;
2020-09-25 09:42:21 +03:00
_handleUpload = async ( { files , slate , keys } ) => {
2020-09-23 04:10:27 +03:00
if ( ! files || ! files . length ) {
return null ;
}
// TODO(jim+carson+martina): temporary workaround before we are ready
// to allow parallel downloads again.
const resolvedFiles = [ ] ;
for ( let i = 0 ; i < files . length ; i ++ ) {
const response = await FileUtilities . upload ( {
file : files [ i ] ,
context : this ,
} ) ;
resolvedFiles . push ( response ) ;
}
2020-09-25 06:16:10 +03:00
let responses = await Promise . allSettled ( resolvedFiles ) ;
2020-09-25 09:42:21 +03:00
2020-09-25 06:16:10 +03:00
let succeeded = responses
. filter ( ( res ) => {
return res . status === "fulfilled" && res . value && ! res . value . error ;
2020-09-22 01:21:39 +03:00
} )
2020-09-25 06:16:10 +03:00
. map ( ( res ) => res . value ) ;
2020-09-27 00:15:37 +03:00
if ( slate && slate . id ) {
2020-09-25 06:16:10 +03:00
await FileUtilities . uploadToSlate ( { responses : succeeded , slate } ) ;
}
2020-09-25 09:42:21 +03:00
2020-09-25 06:16:10 +03:00
let processResponse = await Actions . processPendingFiles ( ) ;
if ( ! processResponse ) {
dispatchCustomEvent ( {
name : "create-alert" ,
detail : {
alert : {
message :
"We encountered issues updating your uploaded files. Please try again" ,
} ,
} ,
} ) ;
return ;
}
2020-09-25 09:42:21 +03:00
2020-09-25 06:16:10 +03:00
if ( processResponse . error ) {
dispatchCustomEvent ( {
name : "create-alert" ,
detail : {
alert : {
decorator : processResponse . decorator ,
} ,
} ,
} ) ;
return ;
}
2020-09-25 09:42:21 +03:00
2020-09-25 06:16:10 +03:00
await this . rehydrate ( { resetFiles : true } ) ;
2020-09-22 01:21:39 +03:00
2020-09-25 06:16:10 +03:00
//NOTE(martina): to update the carousel to include the new file if you're on the data view page
dispatchCustomEvent ( {
name : "remote-update-carousel" ,
detail : { } ,
} ) ;
2020-09-22 01:21:39 +03:00
2020-09-25 06:16:10 +03:00
//NOTE(martina): to update the slate to include the new file if you're on a slate page
2020-09-27 00:15:37 +03:00
const navigation = NavigationData . generate ( this . state . viewer ) ;
const next = this . state . history [ this . state . currentIndex ] ;
const current = NavigationData . getCurrentById ( navigation , next . id ) ;
if (
current . target &&
current . target . slateId &&
this . state . viewer . slates
. map ( ( slate ) => slate . id )
. includes ( current . target . slateId )
) {
dispatchCustomEvent ( {
name : "remote-update-slate-screen" ,
detail : { } ,
} ) ;
}
2020-09-22 01:21:39 +03:00
2020-09-25 06:16:10 +03:00
if ( ! slate ) {
const { added , skipped } = processResponse . data ;
let message = ` ${ added || 0 } file ${ added !== 1 ? "s" : "" } uploaded. ` ;
if ( skipped ) {
message += ` ${ skipped || 0 } duplicate / existing file ${
added !== 1 ? "s were" : " was"
} skipped . ` ;
}
dispatchCustomEvent ( {
name : "create-alert" ,
detail : {
alert : { message , status : ! added ? null : "INFO" } ,
} ,
2020-09-20 21:31:08 +03:00
} ) ;
2020-09-25 06:16:10 +03:00
}
2020-09-25 09:42:21 +03:00
2020-09-25 06:16:10 +03:00
this . _handleRegisterLoadingFinished ( { keys } ) ;
2020-09-25 09:42:21 +03:00
return null ;
2020-08-20 08:20:18 +03:00
} ;
_handleRegisterFileLoading = ( { fileLoading } ) => {
2020-09-11 02:06:06 +03:00
if ( this . state . fileLoading ) {
return this . setState ( {
fileLoading : { ... this . state . fileLoading , ... fileLoading } ,
} ) ;
}
2020-08-16 01:38:09 +03:00
return this . setState ( {
fileLoading ,
} ) ;
} ;
2020-09-25 06:16:10 +03:00
_handleRegisterLoadingFinished = ( { keys } ) => {
let fileLoading = this . state . fileLoading ;
for ( let key of keys ) {
delete fileLoading [ key ] ;
}
this . setState ( { fileLoading } ) ;
} ;
2020-07-29 19:07:13 +03:00
_handleDragEnter = ( e ) => {
2020-08-22 12:32:40 +03:00
e . preventDefault ( ) ;
2020-08-02 10:55:55 +03:00
if ( this . state . sidebar ) {
return ;
}
2020-08-22 12:32:40 +03:00
// NOTE(jim): Only allow the sidebar to show with file drag and drop.
2020-08-25 09:46:02 +03:00
if (
e . dataTransfer . items &&
e . dataTransfer . items . length &&
e . dataTransfer . items [ 0 ] . kind !== "file"
) {
2020-08-22 12:32:40 +03:00
return ;
}
2020-08-02 10:55:55 +03:00
this . _handleAction ( {
type : "SIDEBAR" ,
value : "SIDEBAR_DRAG_DROP_NOTICE" ,
} ) ;
2020-07-29 19:07:13 +03:00
} ;
_handleDragLeave = ( e ) => {
2020-08-02 10:55:55 +03:00
e . preventDefault ( ) ;
2020-07-29 19:07:13 +03:00
} ;
_handleDragOver = ( e ) => {
e . preventDefault ( ) ;
} ;
_handleSidebarLoading = ( sidebarLoading ) => this . setState ( { sidebarLoading } ) ;
2020-08-15 05:08:17 +03:00
rehydrate = async ( options ) => {
2020-07-29 19:07:13 +03:00
const response = await Actions . hydrateAuthenticatedUser ( ) ;
if ( ! response || response . error ) {
2020-09-12 01:25:33 +03:00
dispatchCustomEvent ( {
name : "create-alert" ,
detail : {
alert : {
message : "We encountered issues while refreshing. Please try again" ,
} ,
} ,
} ) ;
2020-07-29 19:07:13 +03:00
return null ;
}
2020-08-24 08:59:37 +03:00
console . log ( "REHYDRATION CALL" , response ) ;
2020-08-15 05:08:17 +03:00
const updates = {
2020-09-03 09:00:02 +03:00
viewer : JSON . parse ( JSON . stringify ( response . data ) ) ,
2020-08-15 05:08:17 +03:00
} ;
if ( options && options . resetFiles ) {
2020-08-15 05:18:55 +03:00
updates . sidebar = null ;
2020-08-15 05:08:17 +03:00
}
this . setState ( updates ) ;
2020-07-29 19:07:13 +03:00
2020-08-31 21:19:46 +03:00
return response ;
2020-07-29 19:07:13 +03:00
} ;
_handleSubmit = async ( data ) => {
let response ;
2020-08-09 11:08:46 +03:00
2020-07-29 19:07:13 +03:00
if ( data . type === "CREATE_SLATE" ) {
response = await Actions . createSlate ( {
name : data . name ,
2020-09-14 08:22:19 +03:00
public : data . public ,
body : data . body ,
2020-07-29 19:07:13 +03:00
} ) ;
}
if ( data . type === "CREATE_WALLET_ADDRESS" ) {
response = await Actions . updateViewer ( {
type : "CREATE_FILECOIN_ADDRESS" ,
address : {
name : data . name ,
type : data . wallet _type ,
makeDefault : data . makeDefault ,
} ,
} ) ;
}
if ( data . type === "SEND_WALLET_ADDRESS_FILECOIN" ) {
response = await Actions . sendFilecoin ( {
source : data . source ,
target : data . target ,
amount : data . amount ,
} ) ;
}
await this . rehydrate ( ) ;
this . _handleDismissSidebar ( ) ;
return response ;
} ;
_handleDeleteYourself = async ( ) => {
2020-09-12 01:25:33 +03:00
// TODO(jim): Put this somewhere better for messages.
2020-08-25 09:46:02 +03:00
const message =
"Do you really want to delete your account? It will be permanently removed" ;
2020-07-29 19:07:13 +03:00
if ( ! window . confirm ( message ) ) {
return false ;
}
let response = await Actions . deleteViewer ( ) ;
2020-09-13 05:59:47 +03:00
if ( ! response || response . error ) {
dispatchCustomEvent ( {
name : "create-alert" ,
detail : {
alert : {
message :
"We're having trouble connecting right now. Please try again later" ,
} ,
} ,
} ) ;
return response ;
}
2020-07-29 19:07:13 +03:00
await this . _handleSignOut ( ) ;
2020-09-13 05:59:47 +03:00
return response ;
2020-07-29 19:07:13 +03:00
} ;
2020-09-15 05:58:23 +03:00
_handleCreateUser = async ( state ) => {
// NOTE(jim): Acts as our existing username exists check.
// If the user exists, move on the sign in anyways.
let response = await Actions . createUser ( state ) ;
console . log ( "CREATE_USER" , response ) ;
if ( ! response || response . error ) {
return response ;
}
return this . _handleAuthenticate ( state ) ;
} ;
2020-07-29 19:07:13 +03:00
_handleAuthenticate = async ( state ) => {
// NOTE(jim): Kills existing session cookie if there is one.
const jwt = cookies . get ( Credentials . session . key ) ;
if ( jwt ) {
cookies . remove ( Credentials . session . key ) ;
}
2020-09-15 05:58:23 +03:00
let response = await Actions . signIn ( state ) ;
2020-09-13 01:08:36 +03:00
if ( ! response || response . error ) {
return response ;
2020-07-29 19:07:13 +03:00
}
if ( response . token ) {
// NOTE(jim):
// + One week.
// + Only requests to the same site.
// + Not using sessionStorage so the cookie doesn't leave when the browser dies.
cookies . set ( Credentials . session . key , response . token , true , {
path : "/" ,
maxAge : 3600 * 24 * 7 ,
sameSite : "strict" ,
} ) ;
}
2020-09-15 05:58:23 +03:00
await this . rehydrate ( ) ;
return response ;
2020-07-29 19:07:13 +03:00
} ;
_handleSignOut = ( ) => {
const jwt = cookies . get ( Credentials . session . key ) ;
if ( jwt ) {
cookies . remove ( Credentials . session . key ) ;
window . location . reload ( ) ;
}
} ;
_handleViewerChange = ( e ) => {
this . setState ( {
viewer : { ... this . state . viewer , [ e . target . name ] : e . target . value } ,
} ) ;
} ;
_handleSelectedChange = ( e ) => {
this . setState ( {
selected : { ... this . state . selected , [ e . target . name ] : e . target . value } ,
} ) ;
} ;
_handleDismissSidebar = ( ) => {
2020-08-31 21:19:46 +03:00
this . setState ( { sidebar : null , sidebarLoading : false , sidebarData : null } ) ;
2020-07-29 19:07:13 +03:00
} ;
_handleAction = ( options ) => {
if ( options . type === "NAVIGATE" ) {
2020-08-31 21:19:46 +03:00
// NOTE(martina): The `scene` property is only necessary when you need to display a component different from the one corresponding to the tab it appears in
// + e.g. to display <SceneProfile/> while on the Home tab
// + `scene` should be the decorator of the component you want displayed
return this . _handleNavigateTo (
{ id : options . value , scene : options . scene } ,
options . data
) ;
2020-07-29 19:07:13 +03:00
}
if ( options . type === "NEW_WINDOW" ) {
return window . open ( options . value ) ;
}
if ( options . type === "ACTION" ) {
2020-09-12 01:25:33 +03:00
dispatchCustomEvent ( {
name : "create-alert" ,
detail : { alert : { message : JSON . stringify ( options ) , status : "INFO" } } ,
} ) ;
2020-07-29 19:07:13 +03:00
}
if ( options . type === "DOWNLOAD" ) {
2020-09-12 01:25:33 +03:00
dispatchCustomEvent ( {
name : "create-alert" ,
detail : { alert : { message : JSON . stringify ( options ) , status : "INFO" } } ,
} ) ;
2020-07-29 19:07:13 +03:00
}
if ( options . type === "SIDEBAR" ) {
return this . setState ( {
2020-08-14 12:17:19 +03:00
sidebar : SIDEBARS [ options . value ] ,
2020-08-31 21:19:46 +03:00
sidebarData : options . data ,
2020-07-29 19:07:13 +03:00
} ) ;
}
2020-09-13 01:08:36 +03:00
return alert ( JSON . stringify ( options ) ) ;
2020-07-29 19:07:13 +03:00
} ;
_handleNavigateTo = ( next , data = null ) => {
2020-09-12 08:54:54 +03:00
window . history . replaceState ( { ... next } , "Slate" , ` ?scene= ${ next . id } ` ) ;
2020-09-08 09:05:16 +03:00
let body = document . documentElement || document . body ;
2020-09-12 08:54:54 +03:00
this . state . history [ this . state . currentIndex ] . scrollTop = body . scrollTop ;
this . state . history [ this . state . currentIndex ] . data = this . state . data ;
2020-07-29 19:07:13 +03:00
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 ,
} ,
2020-08-31 21:19:46 +03:00
( ) => body . scrollTo ( 0 , 0 )
2020-07-29 19:07:13 +03:00
) ;
}
this . setState (
{
history : [ ... this . state . history , next ] ,
currentIndex : this . state . currentIndex + 1 ,
data ,
sidebar : null ,
} ,
2020-08-31 21:19:46 +03:00
( ) => body . scrollTo ( 0 , 0 )
2020-07-29 19:07:13 +03:00
) ;
} ;
_handleBack = ( ) => {
2020-09-08 09:05:16 +03:00
let body = document . documentElement || document . body ;
2020-08-31 21:19:46 +03:00
this . state . history [ this . state . currentIndex ] . scrollTop = body . scrollTop ;
2020-09-12 08:54:54 +03:00
this . state . history [ this . state . currentIndex ] . data = this . state . data ;
2020-07-29 19:07:13 +03:00
const next = this . state . history [ this . state . currentIndex - 1 ] ;
2020-09-12 08:54:54 +03:00
window . history . replaceState ( { ... next } , "Slate" , ` ?scene= ${ next . id } ` ) ;
2020-07-29 19:07:13 +03:00
this . setState (
{
currentIndex : this . state . currentIndex - 1 ,
sidebar : null ,
data : { ... next . data } ,
} ,
( ) => {
console . log ( { next } ) ;
2020-08-31 21:19:46 +03:00
body . scrollTo ( 0 , next . scrollTop ) ;
2020-07-29 19:07:13 +03:00
}
) ;
} ;
_handleForward = ( ) => {
2020-09-08 09:05:16 +03:00
let body = document . documentElement || document . body ;
2020-08-31 21:19:46 +03:00
this . state . history [ this . state . currentIndex ] . scrollTop = body . scrollTop ;
2020-07-29 19:07:13 +03:00
const next = this . state . history [ this . state . currentIndex + 1 ] ;
2020-09-12 08:54:54 +03:00
window . history . replaceState ( { ... next } , "Slate" , ` ?scene= ${ next . id } ` ) ;
2020-07-29 19:07:13 +03:00
this . setState (
{
currentIndex : this . state . currentIndex + 1 ,
sidebar : null ,
data : { ... next . data } ,
} ,
( ) => {
console . log ( { next } ) ;
2020-08-31 21:19:46 +03:00
body . scrollTo ( 0 , next . scrollTop ) ;
2020-07-29 19:07:13 +03:00
}
) ;
} ;
render ( ) {
// NOTE(jim): Not authenticated.
if ( ! this . state . viewer ) {
return (
< WebsitePrototypeWrapper
title = "Slate: sign in"
description = "Sign in to your Slate account to manage your assets."
2020-09-08 09:05:16 +03:00
url = "https://slate.host/_"
>
2020-09-25 09:31:56 +03:00
< Alert noWarning style = { { top : 0 , width : "100%" } } / >
2020-08-25 09:46:02 +03:00
< SceneSignIn
2020-09-15 05:58:23 +03:00
onCreateUser = { this . _handleCreateUser }
2020-08-25 09:46:02 +03:00
onAuthenticate = { this . _handleAuthenticate }
2020-10-01 03:41:53 +03:00
onAction = { this . _handleAction }
2020-08-25 09:46:02 +03:00
/ >
2020-07-29 19:07:13 +03:00
< / W e b s i t e P r o t o t y p e W r a p p e r >
) ;
}
// NOTE(jim): Authenticated.
const navigation = NavigationData . generate ( this . state . viewer ) ;
const next = this . state . history [ this . state . currentIndex ] ;
const current = NavigationData . getCurrentById ( navigation , next . id ) ;
const navigationElement = (
< ApplicationNavigation
viewer = { this . state . viewer }
activeId = { current . target . id }
activeIds = { current . activeIds }
navigation = { navigation }
onAction = { this . _handleAction }
2020-08-08 03:10:28 +03:00
onSignOut = { this . _handleSignOut }
2020-07-29 19:07:13 +03:00
/ >
) ;
2020-08-10 13:18:43 +03:00
let headerElement = (
2020-07-29 19:07:13 +03:00
< ApplicationHeader
viewer = { this . state . viewer }
pageTitle = { current . target . pageTitle }
currentIndex = { this . state . currentIndex }
2020-08-20 08:45:43 +03:00
history = { this . state . history }
2020-08-25 02:24:29 +03:00
onAction = { this . _handleAction }
2020-08-31 07:08:07 +03:00
onRehydrate = { this . rehydrate }
2020-07-29 19:07:13 +03:00
onBack = { this . _handleBack }
onForward = { this . _handleForward }
2020-09-29 07:39:05 +03:00
onSignOut = { this . _handleSignOut }
2020-07-29 19:07:13 +03:00
/ >
) ;
2020-08-31 21:19:46 +03:00
const scene = React . cloneElement (
SCENES [ next . scene || current . target . decorator ] ,
{
current : current . target ,
data : this . state . data ,
viewer : this . state . viewer ,
selected : this . state . selected ,
onSelectedChange : this . _handleSelectedChange ,
onViewerChange : this . _handleViewerChange ,
onDeleteYourself : this . _handleDeleteYourself ,
onAction : this . _handleAction ,
2020-09-23 14:17:56 +03:00
onUpload : this . _handleUploadFiles ,
2020-08-31 21:19:46 +03:00
onBack : this . _handleBack ,
onForward : this . _handleForward ,
onRehydrate : this . rehydrate ,
sceneId : current . target . id ,
}
) ;
2020-07-29 19:07:13 +03:00
let sidebarElement ;
if ( this . state . sidebar ) {
sidebarElement = React . cloneElement ( this . state . sidebar , {
2020-09-03 03:35:41 +03:00
current : current . target ,
2020-07-29 19:07:13 +03:00
selected : this . state . selected ,
viewer : this . state . viewer ,
data : this . state . data ,
2020-09-23 23:52:00 +03:00
sidebarData : this . state . sidebarData ,
2020-07-29 19:07:13 +03:00
fileLoading : this . state . fileLoading ,
sidebarLoading : this . state . sidebarLoading ,
onSelectedChange : this . _handleSelectedChange ,
onSubmit : this . _handleSubmit ,
2020-09-17 02:26:15 +03:00
onCancel : this . _handleDismissSidebar ,
2020-08-20 08:20:18 +03:00
onRegisterFileLoading : this . _handleRegisterFileLoading ,
2020-09-21 00:34:31 +03:00
onUpload : this . _handleUploadFiles ,
2020-07-29 19:07:13 +03:00
onSidebarLoading : this . _handleSidebarLoading ,
2020-08-09 11:08:46 +03:00
onAction : this . _handleAction ,
2020-07-29 19:07:13 +03:00
onRehydrate : this . rehydrate ,
} ) ;
}
const title = ` Slate : ${ current . target . pageTitle } ` ;
2020-08-20 08:45:43 +03:00
const description = "" ;
2020-08-07 02:06:54 +03:00
const url = "https://slate.host/_" ;
2020-07-29 19:07:13 +03:00
return (
< React . Fragment >
2020-08-25 09:46:02 +03:00
< WebsitePrototypeWrapper
description = { description }
title = { title }
2020-09-08 09:05:16 +03:00
url = { url }
>
2020-07-29 19:07:13 +03:00
< ApplicationLayout
2020-09-25 06:16:10 +03:00
onAction = { this . _handleAction }
2020-07-29 19:07:13 +03:00
header = { headerElement }
2020-08-20 08:45:43 +03:00
navigation = { navigationElement }
2020-07-29 19:07:13 +03:00
sidebar = { sidebarElement }
2020-09-08 09:05:16 +03:00
onDismissSidebar = { this . _handleDismissSidebar }
2020-09-25 06:16:10 +03:00
fileLoading = { this . state . fileLoading }
2020-09-25 10:08:08 +03:00
filecoin = { current . target . filecoin }
2020-09-08 09:05:16 +03:00
>
2020-07-29 19:07:13 +03:00
{ scene }
< / A p p l i c a t i o n L a y o u t >
2020-09-27 07:43:25 +03:00
< GlobalViewerCID
onRehydrate = { this . rehydrate }
onAction = { this . _handleAction }
/ >
2020-08-09 11:38:16 +03:00
< System . GlobalCarousel / >
2020-08-25 02:24:29 +03:00
< System . GlobalModal / >
2020-07-29 19:07:13 +03:00
< / W e b s i t e P r o t o t y p e W r a p p e r >
< / R e a c t . F r a g m e n t >
) ;
}
}