mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-03-03 11:36:08 +08:00
Spring cleaning: Remove the (disabled) plugins package, will be web page
This commit is contained in:
parent
5c31fea79f
commit
f79d850a0c
13 changed files with 0 additions and 972 deletions
|
@ -1,16 +0,0 @@
|
|||
import { PreferencesUIStore } from 'mailspring-exports';
|
||||
import PluginsView from './preferences-plugins';
|
||||
|
||||
export function activate() {
|
||||
this.preferencesTab = new PreferencesUIStore.TabItem({
|
||||
tabId: 'Plugins',
|
||||
displayName: 'Plugins',
|
||||
componentClassFn: () => PluginsView,
|
||||
});
|
||||
|
||||
PreferencesUIStore.registerPreferencesTab(this.preferencesTab);
|
||||
}
|
||||
|
||||
export function deactivate() {
|
||||
PreferencesUIStore.unregisterPreferencesTab(this.preferencesTab.sectionId);
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Package from './package';
|
||||
|
||||
class PackageSet extends React.Component {
|
||||
static propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
packages: PropTypes.array,
|
||||
emptyText: PropTypes.element,
|
||||
showVersions: PropTypes.bool,
|
||||
};
|
||||
|
||||
render() {
|
||||
if (!this.props.packages) return false;
|
||||
|
||||
const packages = this.props.packages.map(pkg => (
|
||||
<Package key={pkg.name} package={pkg} showVersions={this.props.showVersions} />
|
||||
));
|
||||
let count = <span>({this.props.packages.length})</span>;
|
||||
|
||||
if (packages.length === 0) {
|
||||
count = [];
|
||||
packages.push(
|
||||
<div key="empty" className="empty">
|
||||
{this.props.emptyText || 'No plugins to display.'}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="package-set">
|
||||
<h6>
|
||||
{this.props.title} {count}
|
||||
</h6>
|
||||
{packages}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PackageSet;
|
|
@ -1,140 +0,0 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { Flexbox, RetinaImg, Switch } from 'mailspring-component-kit';
|
||||
import PluginsActions from './plugins-actions';
|
||||
|
||||
class Package extends React.Component {
|
||||
static displayName = 'Package';
|
||||
|
||||
static propTypes = {
|
||||
package: PropTypes.object.isRequired,
|
||||
showVersions: PropTypes.bool,
|
||||
};
|
||||
|
||||
_onDisablePackage = () => {
|
||||
PluginsActions.disablePackage(this.props.package);
|
||||
};
|
||||
|
||||
_onEnablePackage = () => {
|
||||
PluginsActions.enablePackage(this.props.package);
|
||||
};
|
||||
|
||||
_onUninstallPackage = () => {
|
||||
PluginsActions.uninstallPackage(this.props.package);
|
||||
};
|
||||
|
||||
_onUpdatePackage = () => {
|
||||
PluginsActions.updatePackage(this.props.package);
|
||||
};
|
||||
|
||||
_onInstallPackage = () => {
|
||||
PluginsActions.installPackage(this.props.package);
|
||||
};
|
||||
|
||||
_onShowPackage = () => {
|
||||
PluginsActions.showPackage(this.props.package);
|
||||
};
|
||||
|
||||
render() {
|
||||
const actions = [];
|
||||
const extras = [];
|
||||
let icon = <RetinaImg name="plugin-icon-default.png" mode="ContentPreserve" />;
|
||||
let uninstallButton = null;
|
||||
|
||||
if (this.props.package.icon) {
|
||||
icon = (
|
||||
<img
|
||||
src={`mailspring://${this.props.package.name}/${this.props.package.icon}`}
|
||||
alt=""
|
||||
style={{ width: 27, alignContent: 'center', objectFit: 'scale-down' }}
|
||||
/>
|
||||
);
|
||||
} else if (this.props.package.theme) {
|
||||
icon = <RetinaImg name="theme-icon-default.png" mode="ContentPreserve" />;
|
||||
}
|
||||
|
||||
if (this.props.package.installed) {
|
||||
if (
|
||||
['user', 'dev', 'example'].indexOf(this.props.package.category) !== -1 &&
|
||||
!this.props.package.theme
|
||||
) {
|
||||
if (this.props.package.enabled) {
|
||||
actions.push(
|
||||
<Switch key="disable" checked onChange={this._onDisablePackage}>
|
||||
Disable
|
||||
</Switch>
|
||||
);
|
||||
} else {
|
||||
actions.push(
|
||||
<Switch key="enable" onChange={this._onEnablePackage}>
|
||||
Enable
|
||||
</Switch>
|
||||
);
|
||||
}
|
||||
}
|
||||
if (this.props.package.category === 'user') {
|
||||
uninstallButton = (
|
||||
<div className="uninstall-plugin" onClick={this._onUninstallPackage}>
|
||||
Uninstall
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (this.props.package.category === 'dev') {
|
||||
actions.push(
|
||||
<div key="show-package" className="btn" onClick={this._onShowPackage}>
|
||||
Show...
|
||||
</div>
|
||||
);
|
||||
}
|
||||
} else if (this.props.package.installing) {
|
||||
actions.push(
|
||||
<div key="installing" className="btn">
|
||||
Installing...
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
actions.push(
|
||||
<div key="install" className="btn" onClick={this._onInstallPackage}>
|
||||
Install
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const { name, description, title, version } = this.props.package;
|
||||
|
||||
if (this.props.package.newerVersionAvailable) {
|
||||
extras.push(
|
||||
<div className="padded update-info">
|
||||
A newer version is available: {this.props.package.newerVersion}
|
||||
<div className="btn btn-emphasis" onClick={this._onUpdatePackage}>
|
||||
Update
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const versionLabel = this.props.showVersions ? `v${version}` : null;
|
||||
|
||||
return (
|
||||
<Flexbox className="package" direction="row">
|
||||
<div className="icon-container">
|
||||
<div className="icon">{icon}</div>
|
||||
</div>
|
||||
<div className="info">
|
||||
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||
<div className="title">
|
||||
{title || name} <span className="version">{versionLabel}</span>
|
||||
</div>
|
||||
{uninstallButton}
|
||||
</div>
|
||||
<div className="description">{description}</div>
|
||||
</div>
|
||||
<div className="actions">{actions}</div>
|
||||
{extras}
|
||||
</Flexbox>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Package;
|
|
@ -1,240 +0,0 @@
|
|||
import _ from 'underscore';
|
||||
import Reflux from 'reflux';
|
||||
import path from 'path';
|
||||
import fs from 'fs-plus';
|
||||
import { ipcRenderer, shell, remote } from 'electron';
|
||||
|
||||
import PluginsActions from './plugins-actions';
|
||||
|
||||
const dialog = remote.dialog;
|
||||
|
||||
const PackagesStore = Reflux.createStore({
|
||||
init: function init() {
|
||||
// this._globalSearch = "";
|
||||
// this._installedSearch = "";
|
||||
// this._installing = {};
|
||||
// this._featured = {
|
||||
// themes: [],
|
||||
// packages: [],
|
||||
// };
|
||||
// this._newerVersions = [];
|
||||
// this._searchResults = null;
|
||||
// this._refreshFeatured();
|
||||
// this.listenTo(PluginsActions.refreshFeaturedPackages, this._refreshFeatured);
|
||||
// this.listenTo(PluginsActions.refreshInstalledPackages, this._refreshInstalled);
|
||||
// this.listenTo(PluginsActions.installNewPackage, this._onInstallPackage);
|
||||
// this.listenTo(PluginsActions.createPackage, this._onCreatePackage);
|
||||
// this.listenTo(PluginsActions.updatePackage, this._onUpdatePackage);
|
||||
// this.listenTo(PluginsActions.setGlobalSearchValue, this._onGlobalSearchChange);
|
||||
// this.listenTo(PluginsActions.setInstalledSearchValue, this._onInstalledSearchChange);
|
||||
// this.listenTo(PluginsActions.showPackage, (pkg) => {
|
||||
// const dir = AppEnv.packages.resolvePackagePath(pkg.name);
|
||||
// if (dir) shell.showItemInFolder(dir);
|
||||
// });
|
||||
// this.listenTo(PluginsActions.installPackage, (pkg) => {
|
||||
// this._installing[pkg.name] = true;
|
||||
// this.trigger(this);
|
||||
// this._apm.install(pkg, (err) => {
|
||||
// if (err) {
|
||||
// delete this._installing[pkg.name];
|
||||
// this._displayMessage("Sorry, an error occurred", err.toString());
|
||||
// } else {
|
||||
// if (AppEnv.packages.isPackageDisabled(pkg.name)) {
|
||||
// AppEnv.packages.enablePackage(pkg.name);
|
||||
// }
|
||||
// }
|
||||
// this._onPackagesChanged();
|
||||
// });
|
||||
// });
|
||||
// this.listenTo(PluginsActions.uninstallPackage, (pkg) => {
|
||||
// if (AppEnv.packages.isPackageLoaded(pkg.name)) {
|
||||
// AppEnv.packages.disablePackage(pkg.name);
|
||||
// AppEnv.packages.unloadPackage(pkg.name);
|
||||
// }
|
||||
// this._apm.uninstall(pkg, (err) => {
|
||||
// if (err) this._displayMessage("Sorry, an error occurred", err.toString())
|
||||
// this._onPackagesChanged();
|
||||
// })
|
||||
// });
|
||||
// this.listenTo(PluginsActions.enablePackage, (pkg) => {
|
||||
// if (AppEnv.packages.isPackageDisabled(pkg.name)) {
|
||||
// AppEnv.packages.enablePackage(pkg.name);
|
||||
// this._onPackagesChanged();
|
||||
// }
|
||||
// });
|
||||
// this.listenTo(PluginsActions.disablePackage, (pkg) => {
|
||||
// if (!AppEnv.packages.isPackageDisabled(pkg.name)) {
|
||||
// AppEnv.packages.disablePackage(pkg.name);
|
||||
// this._onPackagesChanged();
|
||||
// }
|
||||
// });
|
||||
// this._hasPrepared = false;
|
||||
},
|
||||
|
||||
// Getters
|
||||
|
||||
installed: function installed() {
|
||||
this._prepareIfFresh();
|
||||
return this._addPackageStates(this._filter(this._installed, this._installedSearch));
|
||||
},
|
||||
|
||||
installedSearchValue: function installedSearchValue() {
|
||||
return this._installedSearch;
|
||||
},
|
||||
|
||||
featured: function featured() {
|
||||
this._prepareIfFresh();
|
||||
return this._addPackageStates(this._featured);
|
||||
},
|
||||
|
||||
searchResults: function searchResults() {
|
||||
return this._addPackageStates(this._searchResults);
|
||||
},
|
||||
|
||||
globalSearchValue: function globalSearchValue() {
|
||||
return this._globalSearch;
|
||||
},
|
||||
|
||||
// Action Handlers
|
||||
|
||||
_prepareIfFresh: function _prepareIfFresh() {
|
||||
if (this._hasPrepared) return;
|
||||
AppEnv.packages.onDidActivatePackage(() => this._onPackagesChangedDebounced());
|
||||
AppEnv.packages.onDidDeactivatePackage(() => this._onPackagesChangedDebounced());
|
||||
AppEnv.packages.onDidLoadPackage(() => this._onPackagesChangedDebounced());
|
||||
AppEnv.packages.onDidUnloadPackage(() => this._onPackagesChangedDebounced());
|
||||
this._onPackagesChanged();
|
||||
this._hasPrepared = true;
|
||||
},
|
||||
|
||||
_filter: function _filter(hash, search) {
|
||||
const result = {};
|
||||
const query = search.toLowerCase();
|
||||
if (hash) {
|
||||
Object.keys(hash).forEach(key => {
|
||||
result[key] = _.filter(
|
||||
hash[key],
|
||||
p => query.length === 0 || p.name.toLowerCase().indexOf(query) !== -1
|
||||
);
|
||||
});
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
_refreshFeatured: function _refreshFeatured() {
|
||||
this._apm
|
||||
.getFeatured({ themes: false })
|
||||
.then(results => {
|
||||
this._featured.packages = results;
|
||||
this.trigger();
|
||||
})
|
||||
.catch(() => {
|
||||
// We may be offline
|
||||
});
|
||||
this._apm
|
||||
.getFeatured({ themes: true })
|
||||
.then(results => {
|
||||
this._featured.themes = results;
|
||||
this.trigger();
|
||||
})
|
||||
.catch(() => {
|
||||
// We may be offline
|
||||
});
|
||||
},
|
||||
|
||||
_refreshInstalled: function _refreshInstalled() {
|
||||
this._onPackagesChanged();
|
||||
},
|
||||
|
||||
_refreshSearch: function _refreshSearch() {
|
||||
if (!this._globalSearch || this._globalSearch.length <= 0) return;
|
||||
|
||||
this._apm
|
||||
.search(this._globalSearch)
|
||||
.then(results => {
|
||||
this._searchResults = {
|
||||
packages: results.filter(({ theme }) => !theme),
|
||||
themes: results.filter(({ theme }) => theme),
|
||||
};
|
||||
this.trigger();
|
||||
})
|
||||
.catch(() => {
|
||||
// We may be offline
|
||||
});
|
||||
},
|
||||
|
||||
_refreshSearchThrottled: function _refreshSearchThrottled() {
|
||||
_.debounce(this._refreshSearch, 400);
|
||||
},
|
||||
|
||||
_onPackagesChanged: function _onPackagesChanged() {
|
||||
this._apm.getInstalled().then(packages => {
|
||||
for (const category of ['dev', 'user']) {
|
||||
packages[category].forEach(pkg => {
|
||||
pkg.category = category;
|
||||
delete this._installing[pkg.name];
|
||||
});
|
||||
}
|
||||
|
||||
const available = AppEnv.packages.getAvailablePackageMetadata();
|
||||
const examples = available.filter(
|
||||
({ isOptional, isHiddenOnPluginsPage }) => isOptional && !isHiddenOnPluginsPage
|
||||
);
|
||||
packages.example = examples.map(pkg =>
|
||||
Object.assign({}, pkg, { installed: true, category: 'example' })
|
||||
);
|
||||
this._installed = packages;
|
||||
this.trigger();
|
||||
});
|
||||
},
|
||||
|
||||
_onPackagesChangedDebounced: function _onPackagesChangedDebounced() {
|
||||
_.debounce(this._onPackagesChanged, 200);
|
||||
},
|
||||
|
||||
_onInstalledSearchChange: function _onInstalledSearchChange(val) {
|
||||
this._installedSearch = val;
|
||||
this.trigger();
|
||||
},
|
||||
|
||||
_onUpdatePackage: function _onUpdatePackage(pkg) {
|
||||
this._apm.update(pkg, pkg.newerVersion);
|
||||
},
|
||||
|
||||
_onGlobalSearchChange: function _onGlobalSearchChange(val) {
|
||||
// Clear previous search results data if this is a new
|
||||
// search beginning from "".
|
||||
if (this._globalSearch.length === 0 && val.length > 0) {
|
||||
this._searchResults = null;
|
||||
}
|
||||
|
||||
this._globalSearch = val;
|
||||
this._refreshSearchThrottled();
|
||||
this.trigger();
|
||||
},
|
||||
|
||||
_addPackageStates: function _addPackageStates(pkgs) {
|
||||
const installedNames = _.flatten(Object.values(this._installed)).map(pkg => pkg.name);
|
||||
|
||||
_.flatten(Object.values(pkgs)).forEach(pkg => {
|
||||
pkg.enabled = !AppEnv.packages.isPackageDisabled(pkg.name);
|
||||
pkg.installed = installedNames.indexOf(pkg.name) !== -1;
|
||||
pkg.installing = this._installing[pkg.name];
|
||||
pkg.newerVersionAvailable = this._newerVersions[pkg.name];
|
||||
pkg.newerVersion = this._newerVersions[pkg.name];
|
||||
});
|
||||
|
||||
return pkgs;
|
||||
},
|
||||
|
||||
_displayMessage: function _displayMessage(title, message) {
|
||||
dialog.showMessageBox({
|
||||
type: 'warning',
|
||||
message: title,
|
||||
detail: message,
|
||||
buttons: ['OK'],
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export default PackagesStore;
|
|
@ -1,26 +0,0 @@
|
|||
import Reflux from 'reflux';
|
||||
|
||||
const Actions = Reflux.createActions([
|
||||
'selectTabIndex',
|
||||
'setInstalledSearchValue',
|
||||
'setGlobalSearchValue',
|
||||
|
||||
'disablePackage',
|
||||
'enablePackage',
|
||||
'installPackage',
|
||||
'installNewPackage',
|
||||
'uninstallPackage',
|
||||
'createPackage',
|
||||
'reloadPackage',
|
||||
'showPackage',
|
||||
'updatePackage',
|
||||
|
||||
'refreshFeaturedPackages',
|
||||
'refreshInstalledPackages',
|
||||
]);
|
||||
|
||||
for (const key of Object.keys(Actions)) {
|
||||
Actions[key].sync = true;
|
||||
}
|
||||
|
||||
export default Actions;
|
|
@ -1,66 +0,0 @@
|
|||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Tabs from './tabs';
|
||||
import TabsStore from './tabs-store';
|
||||
import PluginsActions from './plugins-actions';
|
||||
|
||||
class PluginsTabs extends React.Component {
|
||||
static displayName = 'PluginsTabs';
|
||||
|
||||
static propTypes = {
|
||||
onChange: PropTypes.Func,
|
||||
};
|
||||
|
||||
static containerRequired = false;
|
||||
|
||||
static containerStyles = {
|
||||
minWidth: 200,
|
||||
maxWidth: 290,
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.state = this._getStateFromStores();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this._unsubscribers = [];
|
||||
this._unsubscribers.push(TabsStore.listen(this._onChange));
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._unsubscribers.forEach(unsubscribe => unsubscribe());
|
||||
}
|
||||
|
||||
_getStateFromStores() {
|
||||
return {
|
||||
tabIndex: TabsStore.tabIndex(),
|
||||
};
|
||||
}
|
||||
|
||||
_onChange = () => {
|
||||
this.setState(this._getStateFromStores());
|
||||
};
|
||||
|
||||
_renderItems() {
|
||||
return Tabs.map(({ name, key, icon }, idx) => {
|
||||
const classes = classNames({
|
||||
tab: true,
|
||||
active: idx === this.state.tabIndex,
|
||||
});
|
||||
return (
|
||||
<li key={key} className={classes} onClick={() => PluginsActions.selectTabIndex(idx)}>
|
||||
{name}
|
||||
</li>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return <ul className="plugins-view-tabs">{this._renderItems()}</ul>;
|
||||
}
|
||||
}
|
||||
|
||||
export default PluginsTabs;
|
|
@ -1,46 +0,0 @@
|
|||
import React from 'react';
|
||||
|
||||
import TabsStore from './tabs-store';
|
||||
import Tabs from './tabs';
|
||||
|
||||
class PluginsView extends React.Component {
|
||||
static displayName = 'PluginsView';
|
||||
|
||||
static containerStyles = {
|
||||
minWidth: 500,
|
||||
maxWidth: 99999,
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.state = this._getStateFromStores();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this._unsubscribers = [];
|
||||
this._unsubscribers.push(TabsStore.listen(this._onChange));
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._unsubscribers.forEach(unsubscribe => unsubscribe());
|
||||
}
|
||||
|
||||
_getStateFromStores() {
|
||||
return { tabIndex: TabsStore.tabIndex() };
|
||||
}
|
||||
|
||||
_onChange = () => {
|
||||
this.setState(this._getStateFromStores());
|
||||
};
|
||||
|
||||
render() {
|
||||
const PluginsTabComponent = Tabs[this.state.tabIndex].component;
|
||||
return (
|
||||
<div className="plugins-view">
|
||||
<PluginsTabComponent />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PluginsView;
|
|
@ -1,87 +0,0 @@
|
|||
import React from 'react';
|
||||
|
||||
import PackageSet from './package-set';
|
||||
import PackagesStore from './packages-store';
|
||||
import PluginsActions from './plugins-actions';
|
||||
|
||||
class TabExplore extends React.Component {
|
||||
static displayName = 'TabExplore';
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.state = this._getStateFromStores();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this._unsubscribers = [];
|
||||
this._unsubscribers.push(PackagesStore.listen(this._onChange));
|
||||
|
||||
// Trigger a refresh of the featured packages
|
||||
PluginsActions.refreshFeaturedPackages();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._unsubscribers.forEach(unsubscribe => unsubscribe());
|
||||
}
|
||||
|
||||
_getStateFromStores() {
|
||||
return {
|
||||
featured: PackagesStore.featured(),
|
||||
search: PackagesStore.globalSearchValue(),
|
||||
searchResults: PackagesStore.searchResults(),
|
||||
};
|
||||
}
|
||||
|
||||
_onChange = () => {
|
||||
this.setState(this._getStateFromStores());
|
||||
};
|
||||
|
||||
_onSearchChange = event => {
|
||||
PluginsActions.setGlobalSearchValue(event.target.value);
|
||||
};
|
||||
|
||||
render() {
|
||||
let collection = this.state.featured;
|
||||
let collectionPrefix = 'Featured ';
|
||||
let emptyText = null;
|
||||
if (this.state.search.length > 0) {
|
||||
collectionPrefix = 'Matching ';
|
||||
if (this.state.searchResults) {
|
||||
collection = this.state.searchResults;
|
||||
emptyText = 'No results found.';
|
||||
} else {
|
||||
collection = {
|
||||
packages: [],
|
||||
themes: [],
|
||||
};
|
||||
emptyText = 'Loading results...';
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="explore">
|
||||
<div className="inner">
|
||||
<input
|
||||
type="text"
|
||||
className="search"
|
||||
value={this.state.search}
|
||||
onChange={this._onSearchChange}
|
||||
placeholder="Search Packages and Themes"
|
||||
/>
|
||||
<PackageSet
|
||||
title={`${collectionPrefix} Themes`}
|
||||
emptyText={emptyText || 'There are no featured themes yet.'}
|
||||
packages={collection.themes}
|
||||
/>
|
||||
<PackageSet
|
||||
title={`${collectionPrefix} Packages`}
|
||||
emptyText={emptyText || 'There are no featured packages yet.'}
|
||||
packages={collection.packages}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TabExplore;
|
|
@ -1,129 +0,0 @@
|
|||
import React from 'react';
|
||||
import { ipcRenderer } from 'electron';
|
||||
import { Flexbox } from 'mailspring-component-kit';
|
||||
|
||||
import PackageSet from './package-set';
|
||||
import PackagesStore from './packages-store';
|
||||
import PluginsActions from './plugins-actions';
|
||||
|
||||
class TabInstalled extends React.Component {
|
||||
static displayName = 'TabInstalled';
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.state = this._getStateFromStores();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this._unsubscribers = [];
|
||||
this._unsubscribers.push(PackagesStore.listen(this._onChange));
|
||||
|
||||
PluginsActions.refreshInstalledPackages();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._unsubscribers.forEach(unsubscribe => unsubscribe());
|
||||
}
|
||||
|
||||
_getStateFromStores() {
|
||||
return {
|
||||
packages: PackagesStore.installed(),
|
||||
search: PackagesStore.installedSearchValue(),
|
||||
};
|
||||
}
|
||||
|
||||
_onChange = () => {
|
||||
this.setState(this._getStateFromStores());
|
||||
};
|
||||
|
||||
_onInstallPackage() {
|
||||
PluginsActions.installNewPackage();
|
||||
}
|
||||
|
||||
_onCreatePackage() {
|
||||
PluginsActions.createPackage();
|
||||
}
|
||||
|
||||
_onSearchChange = event => {
|
||||
PluginsActions.setInstalledSearchValue(event.target.value);
|
||||
};
|
||||
|
||||
_onEnableDevMode() {
|
||||
ipcRenderer.send('command', 'application:toggle-dev');
|
||||
}
|
||||
|
||||
render() {
|
||||
let searchEmpty = null;
|
||||
if (this.state.search.length > 0) {
|
||||
searchEmpty = 'No matching packages.';
|
||||
}
|
||||
|
||||
let devPackages = [];
|
||||
let devEmpty = (
|
||||
<span
|
||||
>{`Run with debug flags enabled to load ${AppEnv.getConfigDirPath()}/dev/packages.`}</span>
|
||||
);
|
||||
let devCTA = (
|
||||
<div className="btn btn-small" onClick={this._onEnableDevMode}>
|
||||
Enable Debug Flags
|
||||
</div>
|
||||
);
|
||||
|
||||
if (AppEnv.inDevMode()) {
|
||||
devPackages = this.state.packages.dev || [];
|
||||
devEmpty = (
|
||||
<span>
|
||||
{`You don't have any packages installed in ${AppEnv.getConfigDirPath()}/dev/packages. `}
|
||||
These plugins are only loaded when you run the app with debug flags enabled (via the
|
||||
Developer menu).<br />
|
||||
<br />Learn more about building plugins with{' '}
|
||||
<a href="http://Foundry376.github.io/Mailspring/">our docs</a>.
|
||||
</span>
|
||||
);
|
||||
devCTA = (
|
||||
<div className="btn btn-small" onClick={this._onCreatePackage}>
|
||||
Create New Plugin...
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="installed">
|
||||
<div className="inner">
|
||||
<Flexbox className="search-container">
|
||||
<div className="btn btn-small" onClick={this._onInstallPackage}>
|
||||
Install Plugin...
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
className="search"
|
||||
value={this.state.search}
|
||||
onChange={this._onSearchChange}
|
||||
placeholder="Search Installed Plugins"
|
||||
/>
|
||||
</Flexbox>
|
||||
<PackageSet
|
||||
packages={this.state.packages.user}
|
||||
showVersions
|
||||
title="Installed plugins"
|
||||
emptyText={
|
||||
searchEmpty || (
|
||||
<span
|
||||
>{`You don't have any plugins installed in ${AppEnv.getConfigDirPath()}/packages.`}</span>
|
||||
)
|
||||
}
|
||||
/>
|
||||
<PackageSet title="Built-in plugins" packages={this.state.packages.example} />
|
||||
<PackageSet
|
||||
title="Development plugins"
|
||||
packages={devPackages}
|
||||
emptyText={searchEmpty || devEmpty}
|
||||
/>
|
||||
<div className="new-package">{devCTA}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TabInstalled;
|
|
@ -1,25 +0,0 @@
|
|||
import Reflux from 'reflux';
|
||||
|
||||
import PluginsActions from './plugins-actions';
|
||||
|
||||
const TabsStore = Reflux.createStore({
|
||||
init: function init() {
|
||||
this._tabIndex = 0;
|
||||
this.listenTo(PluginsActions.selectTabIndex, this._onTabIndexChanged);
|
||||
},
|
||||
|
||||
// Getters
|
||||
|
||||
tabIndex: function tabIndex() {
|
||||
return this._tabIndex;
|
||||
},
|
||||
|
||||
// Action Handlers
|
||||
|
||||
_onTabIndexChanged: function _onTabIndexChanged(idx) {
|
||||
this._tabIndex = idx;
|
||||
this.trigger(this);
|
||||
},
|
||||
});
|
||||
|
||||
export default TabsStore;
|
|
@ -1,12 +0,0 @@
|
|||
import TabInstalled from './tab-installed';
|
||||
|
||||
const Tabs = [
|
||||
{
|
||||
key: 'installed',
|
||||
name: 'Installed',
|
||||
icon: 'tbd',
|
||||
component: TabInstalled,
|
||||
},
|
||||
];
|
||||
|
||||
export default Tabs;
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"name": "plugins",
|
||||
"version": "0.1.0",
|
||||
"main": "./lib/main",
|
||||
"description": "Plugins",
|
||||
"license": "GPL-3.0",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"mailspring": "*"
|
||||
}
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
@import 'ui-variables';
|
||||
@import 'ui-mixins';
|
||||
|
||||
.plugins-view-tabs {
|
||||
color: @text-color-subtle;
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
cursor: default;
|
||||
|
||||
li {
|
||||
padding: @padding-large-vertical @padding-large-horizontal;
|
||||
border-bottom: 1px solid @border-color-divider;
|
||||
|
||||
&.active {
|
||||
background: @source-list-active-bg;
|
||||
color: @source-list-active-color;
|
||||
img.colorfill {
|
||||
background: @source-list-active-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.plugins-view {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
.new-package {
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
.installed,
|
||||
.explore {
|
||||
overflow-y: scroll;
|
||||
padding-left: @padding-large-horizontal;
|
||||
height: 100%;
|
||||
|
||||
.inner {
|
||||
max-width: 800px;
|
||||
.search-container {
|
||||
margin: @padding-large-vertical 2px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
box-sizing: border-box;
|
||||
width: 30%;
|
||||
}
|
||||
.search {
|
||||
padding-left: 0;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url('../static/images/search/searchloupe@2x.png');
|
||||
background-size: 15px 15px;
|
||||
background-position: 7px 4px;
|
||||
text-indent: 31px;
|
||||
}
|
||||
.empty {
|
||||
color: @text-color-very-subtle;
|
||||
margin-bottom: @padding-large-vertical * 2;
|
||||
}
|
||||
}
|
||||
|
||||
.package-set {
|
||||
margin-top: 35px;
|
||||
}
|
||||
.package {
|
||||
align-items: center;
|
||||
background: @background-primary;
|
||||
border: 1px solid @border-color-divider;
|
||||
border-radius: @border-radius-large;
|
||||
margin-top: @padding-large-vertical;
|
||||
margin-bottom: @padding-large-vertical;
|
||||
padding: @padding-large-vertical @padding-large-horizontal;
|
||||
|
||||
.icon-container {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
border-radius: 6px;
|
||||
background: linear-gradient(to bottom, @background-primary 0%, @background-secondary 100%);
|
||||
box-shadow: 0 0.5px 0 rgba(0, 0, 0, 0.15), 0 -0.5px 0 rgba(0, 0, 0, 0.15),
|
||||
0.5px 0 0 rgba(0, 0, 0, 0.15), -0.5px 0 0 rgba(0, 0, 0, 0.15),
|
||||
0 0.5px 1px rgba(0, 0, 0, 0.15);
|
||||
flex-shrink: 0;
|
||||
margin-right: @padding-large-horizontal;
|
||||
text-align: center;
|
||||
line-height: 50px;
|
||||
}
|
||||
.info {
|
||||
max-width: 380px;
|
||||
cursor: default;
|
||||
|
||||
.title {
|
||||
color: @text-color-heading;
|
||||
font-size: @font-size-h4;
|
||||
font-weight: @font-weight-normal;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.version {
|
||||
font-size: @font-size-small;
|
||||
font-weight: @font-weight-normal;
|
||||
margin-left: 10px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.uninstall-plugin {
|
||||
color: @text-color-link;
|
||||
margin-left: 10px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.description {
|
||||
padding-top: @padding-base-vertical;
|
||||
color: @text-color-very-subtle;
|
||||
font-size: @font-size-small;
|
||||
}
|
||||
}
|
||||
.actions {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
.btn {
|
||||
margin-left: @padding-small-horizontal;
|
||||
}
|
||||
}
|
||||
.update-info {
|
||||
background: fade(@accent-primary, 10%);
|
||||
line-height: @line-height-computed * 1.1;
|
||||
.btn {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue