Spring cleaning: Remove the (disabled) plugins package, will be web page

This commit is contained in:
Ben Gotow 2019-06-11 00:53:50 -05:00
parent 5c31fea79f
commit f79d850a0c
13 changed files with 0 additions and 972 deletions

View file

@ -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);
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -1,12 +0,0 @@
import TabInstalled from './tab-installed';
const Tabs = [
{
key: 'installed',
name: 'Installed',
icon: 'tbd',
component: TabInstalled,
},
];
export default Tabs;

View file

@ -1,11 +0,0 @@
{
"name": "plugins",
"version": "0.1.0",
"main": "./lib/main",
"description": "Plugins",
"license": "GPL-3.0",
"private": true,
"engines": {
"mailspring": "*"
}
}

View file

@ -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;
}
}
}
}