// @flow import React, {PureComponent} from 'react'; import autobind from 'autobind-decorator'; import {Dropdown, DropdownDivider, DropdownItem, DropdownButton} from '../base/dropdown'; import {showModal} from '../modals'; import * as syncStorage from '../../../sync/storage'; import * as session from '../../../sync/session'; import * as sync from '../../../sync'; import {trackEvent} from '../../../analytics'; import WorkspaceShareSettingsModal from '../modals/workspace-share-settings-modal'; import SetupSyncModal from '../modals/setup-sync-modal'; import type {Workspace} from '../../../models/workspace'; type Props = { workspace: Workspace, // Optional className?: string }; @autobind class SyncDropdown extends PureComponent { props: Props; state: { loggedIn: boolean | null, loading: boolean, resourceGroupId: string | null, syncMode: string | null, syncPercent: number, workspaceName: string }; _hasPrompted: boolean; _isMounted: boolean; constructor (props: Props) { super(props); this._hasPrompted = false; this._isMounted = false; this.state = { loggedIn: null, loading: false, resourceGroupId: null, syncMode: null, syncPercent: 0, workspaceName: '' }; } _trackShowMenu () { trackEvent('Sync', 'Show Menu', 'Authenticated'); } _handleShowShareSettings () { showModal(WorkspaceShareSettingsModal, {workspace: this.props.workspace}); } async _handleSyncResourceGroupId () { const {resourceGroupId} = this.state; // Set loading state this.setState({loading: true}); await sync.getOrCreateConfig(resourceGroupId); await sync.pull(resourceGroupId); await sync.push(resourceGroupId); await this._reloadData(); // Unset loading state this.setState({loading: false}); trackEvent('Sync', 'Manual Sync'); } async _reloadData () { const loggedIn = session.isLoggedIn(); if (loggedIn !== this.state.loggedIn) { this.setState({loggedIn}); } if (!loggedIn) { return; } // Get or create any related sync data const {workspace} = this.props; const {resourceGroupId} = await sync.getOrCreateResourceForDoc(workspace); const config = await sync.getOrCreateConfig(resourceGroupId); // Analyze it const dirty = await syncStorage.findDirtyResourcesForResourceGroup(resourceGroupId); const all = await syncStorage.findResourcesForResourceGroup(resourceGroupId); const numClean = all.length - dirty.length; const syncPercent = all.length === 0 ? 100 : parseInt(numClean / all.length * 1000) / 10; if (this._isMounted) { this.setState({ resourceGroupId, syncPercent, syncMode: config.syncMode, workspaceName: workspace.name }); } } async _handleShowSyncModePrompt () { await showModal(SetupSyncModal); await this._reloadData(); } componentDidMount () { this._isMounted = true; syncStorage.onChange(this._reloadData); this._reloadData(); } componentWillUnmount () { syncStorage.offChange(this._reloadData); this._isMounted = false; } componentDidUpdate () { const {resourceGroupId, syncMode} = this.state; if (!resourceGroupId) { return; } // Sync has not yet been configured for this workspace, so prompt the user to do so const isModeUnset = !syncMode || syncMode === syncStorage.SYNC_MODE_UNSET; if (isModeUnset && !this._hasPrompted) { this._hasPrompted = true; this._handleShowSyncModePrompt(); } } _getSyncDescription (syncMode: string | null, syncPercentage: number) { let el = null; if (syncMode === syncStorage.SYNC_MODE_NEVER) { el = Sync Disabled; } else if (syncPercentage === 100) { el = Sync Up To Date; } else if (syncMode === syncStorage.SYNC_MODE_OFF) { el = Sync Required; } else if (syncMode === syncStorage.SYNC_MODE_ON) { el = Sync Pending; } else if (!syncMode || syncMode === syncStorage.SYNC_MODE_UNSET) { el = Configure Sync; } return el; } render () { const {className} = this.props; const {resourceGroupId, loading, loggedIn} = this.state; // Don't show the sync menu unless we're logged in if (!loggedIn) { return null; } if (!resourceGroupId) { return (