2021-02-02 22:23:42 +00:00
|
|
|
import { autoBindMethodsForReact } from 'class-autobind-decorator';
|
2021-07-22 23:04:56 +00:00
|
|
|
import React, { PureComponent, ReactNode } from 'react';
|
2022-02-25 13:21:35 +00:00
|
|
|
import { connect } from 'react-redux';
|
2021-07-22 23:04:56 +00:00
|
|
|
|
2021-02-02 22:23:42 +00:00
|
|
|
import { AUTOBIND_CFG } from '../../common/constants';
|
2021-06-14 13:28:44 +00:00
|
|
|
import { VCS } from '../../sync/vcs/vcs';
|
2022-02-25 13:21:35 +00:00
|
|
|
import { RootState } from '../redux/modules';
|
|
|
|
import { selectActiveProject } from '../redux/selectors';
|
2019-04-18 00:50:03 +00:00
|
|
|
import { showError } from './modals';
|
|
|
|
|
2022-02-25 13:21:35 +00:00
|
|
|
type ReduxProps = ReturnType<typeof mapStateToProps>;
|
|
|
|
|
|
|
|
interface Props extends ReduxProps {
|
2021-05-12 06:35:00 +00:00
|
|
|
vcs: VCS;
|
|
|
|
branch: string;
|
2021-05-18 20:32:18 +00:00
|
|
|
onPull: (...args: any[]) => any;
|
2021-05-12 06:35:00 +00:00
|
|
|
disabled?: boolean;
|
|
|
|
className?: string;
|
|
|
|
children?: ReactNode;
|
|
|
|
}
|
2019-04-18 00:50:03 +00:00
|
|
|
|
2021-05-12 06:35:00 +00:00
|
|
|
interface State {
|
|
|
|
loading: boolean;
|
|
|
|
}
|
2019-04-18 00:50:03 +00:00
|
|
|
|
2021-02-02 22:23:42 +00:00
|
|
|
@autoBindMethodsForReact(AUTOBIND_CFG)
|
2022-02-25 13:21:35 +00:00
|
|
|
export class UnconnectedSyncPullButton extends PureComponent<Props, State> {
|
2021-05-12 06:35:00 +00:00
|
|
|
_timeout: NodeJS.Timeout | null = null;
|
|
|
|
|
|
|
|
state: State = {
|
2019-04-18 00:50:03 +00:00
|
|
|
loading: false,
|
|
|
|
};
|
|
|
|
|
|
|
|
async _handleClick() {
|
2021-08-20 15:12:36 +00:00
|
|
|
const { vcs, onPull, branch, project } = this.props;
|
2021-05-12 06:35:00 +00:00
|
|
|
this.setState({
|
|
|
|
loading: true,
|
|
|
|
});
|
2019-04-18 00:50:03 +00:00
|
|
|
const newVCS = vcs.newInstance();
|
|
|
|
const oldBranch = await newVCS.getBranch();
|
|
|
|
let failed = false;
|
2021-05-12 06:35:00 +00:00
|
|
|
|
2019-04-18 00:50:03 +00:00
|
|
|
try {
|
|
|
|
// Clone old VCS so we don't mess anything up while working on other projects
|
|
|
|
await newVCS.checkout([], branch);
|
2021-08-20 15:12:36 +00:00
|
|
|
await newVCS.pull([], project.remoteId);
|
2019-04-18 00:50:03 +00:00
|
|
|
} catch (err) {
|
|
|
|
showError({
|
|
|
|
title: 'Pull Error',
|
|
|
|
message: 'Failed to pull ' + branch,
|
|
|
|
error: err,
|
|
|
|
});
|
|
|
|
failed = true;
|
|
|
|
} finally {
|
|
|
|
// We actually need to checkout the old branch again because the VCS
|
|
|
|
// stores it on the filesystem. We should probably have a way to not
|
|
|
|
// have to do this hack
|
|
|
|
await newVCS.checkout([], oldBranch);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do this a bit later so the loading doesn't seem to stop too early
|
|
|
|
this._timeout = setTimeout(() => {
|
2021-05-12 06:35:00 +00:00
|
|
|
this.setState({
|
|
|
|
loading: false,
|
|
|
|
});
|
2019-04-18 00:50:03 +00:00
|
|
|
}, 400);
|
|
|
|
|
|
|
|
if (!failed) {
|
2021-07-30 03:32:08 +00:00
|
|
|
onPull?.();
|
2019-04-18 00:50:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-18 17:44:08 +00:00
|
|
|
componentWillUnmount() {
|
2021-05-12 06:35:00 +00:00
|
|
|
if (this._timeout !== null) {
|
|
|
|
clearTimeout(this._timeout);
|
|
|
|
}
|
2019-04-18 00:50:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const { className, children, disabled } = this.props;
|
|
|
|
const { loading } = this.state;
|
|
|
|
return (
|
|
|
|
<button className={className} onClick={this._handleClick} disabled={disabled}>
|
|
|
|
{loading && <i className="fa fa-spin fa-refresh space-right" />}
|
|
|
|
{children || 'Pull'}
|
|
|
|
</button>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2022-02-25 13:21:35 +00:00
|
|
|
|
|
|
|
const mapStateToProps = (state: RootState) => ({
|
|
|
|
project: selectActiveProject(state),
|
|
|
|
});
|
|
|
|
|
|
|
|
export const SyncPullButton = connect(
|
|
|
|
mapStateToProps,
|
|
|
|
null,
|
|
|
|
null,
|
|
|
|
{ forwardRef: true },
|
|
|
|
)(UnconnectedSyncPullButton);
|