mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Desktop: Add way to install plugin from file
This commit is contained in:
parent
fca8f71f4a
commit
d434723244
@ -50,6 +50,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
this.onApplyClick = this.onApplyClick.bind(this);
|
||||
this.renderLabel = this.renderLabel.bind(this);
|
||||
this.renderDescription = this.renderDescription.bind(this);
|
||||
this.renderHeader = this.renderHeader.bind(this);
|
||||
}
|
||||
|
||||
async checkSyncConfig_() {
|
||||
@ -304,6 +305,24 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
);
|
||||
}
|
||||
|
||||
private renderHeader(themeId: number, label: string) {
|
||||
const theme = themeStyle(themeId);
|
||||
|
||||
const labelStyle = Object.assign({}, theme.textStyle, {
|
||||
display: 'block',
|
||||
color: theme.color,
|
||||
fontSize: theme.fontSize * 1.25,
|
||||
fontWeight: 500,
|
||||
marginBottom: theme.mainPadding,
|
||||
});
|
||||
|
||||
return (
|
||||
<div style={labelStyle}>
|
||||
<label>{label}</label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private renderDescription(themeId: number, description: string) {
|
||||
return description ? <div style={this.descriptionStyle(themeId)}>{description}</div> : null;
|
||||
}
|
||||
@ -384,6 +403,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
}}
|
||||
renderLabel={this.renderLabel}
|
||||
renderDescription={this.renderDescription}
|
||||
renderHeader={this.renderHeader}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -43,6 +43,7 @@ export interface PluginItem {
|
||||
|
||||
const CellRoot = styled.div`
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
background-color: ${props => props.theme.backgroundColor};
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
|
@ -5,13 +5,15 @@ import { _ } from '@joplin/lib/locale';
|
||||
import styled from 'styled-components';
|
||||
import SearchPlugins from './SearchPlugins';
|
||||
import PluginBox from './PluginBox';
|
||||
// import Button, { ButtonLevel } from '../../../Button/Button';
|
||||
import Button, { ButtonLevel } from '../../../Button/Button';
|
||||
import bridge from '../../../../services/bridge';
|
||||
import produce from 'immer';
|
||||
import { OnChangeEvent } from '../../../lib/SearchInput/SearchInput';
|
||||
import { PluginItem } from './PluginBox';
|
||||
const { space } = require('styled-system');
|
||||
|
||||
const maxWidth: number = 250;
|
||||
|
||||
const Root = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -23,7 +25,9 @@ const UserPluginsRoot = styled.div`
|
||||
flex-wrap: wrap;
|
||||
`;
|
||||
|
||||
// const InstallButton = styled(Button)``;
|
||||
const ToolsButton = styled(Button)`
|
||||
margin-right: 2px;
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
value: any;
|
||||
@ -31,6 +35,7 @@ interface Props {
|
||||
onChange: Function;
|
||||
renderLabel: Function;
|
||||
renderDescription: Function;
|
||||
renderHeader: Function;
|
||||
}
|
||||
|
||||
function usePluginItems(plugins: Plugins, settings: PluginSettings): PluginItem[] {
|
||||
@ -96,22 +101,34 @@ export default function(props: Props) {
|
||||
props.onChange({ value: pluginService.serializePluginSettings(newSettings) });
|
||||
}, [pluginSettings, props.onChange]);
|
||||
|
||||
// const onInstall = useCallback(async () => {
|
||||
// const result = bridge().showOpenDialog({
|
||||
// filters: [{ name: 'Joplin Plugin Archive', extensions: ['jpl'] }],
|
||||
// });
|
||||
const onInstall = useCallback(async () => {
|
||||
const result = bridge().showOpenDialog({
|
||||
filters: [{ name: 'Joplin Plugin Archive', extensions: ['jpl'] }],
|
||||
});
|
||||
|
||||
// const filePath = result && result.length ? result[0] : null;
|
||||
// if (!filePath) return;
|
||||
const filePath = result && result.length ? result[0] : null;
|
||||
if (!filePath) return;
|
||||
|
||||
// const plugin = await pluginService.installPlugin(filePath);
|
||||
const plugin = await pluginService.installPlugin(filePath);
|
||||
|
||||
// const newSettings = produce(pluginSettings, (draft: PluginSettings) => {
|
||||
// draft[plugin.manifest.id] = defaultPluginSetting();
|
||||
// });
|
||||
const newSettings = produce(pluginSettings, (draft: PluginSettings) => {
|
||||
draft[plugin.manifest.id] = defaultPluginSetting();
|
||||
});
|
||||
|
||||
// props.onChange({ value: pluginService.serializePluginSettings(newSettings) });
|
||||
// }, [pluginSettings, props.onChange]);
|
||||
props.onChange({ value: pluginService.serializePluginSettings(newSettings) });
|
||||
}, [pluginSettings, props.onChange]);
|
||||
|
||||
const onToolsClick = useCallback(async () => {
|
||||
const template = [];
|
||||
|
||||
template.push({
|
||||
label: _('Install from file'),
|
||||
click: onInstall,
|
||||
});
|
||||
|
||||
const menu = bridge().Menu.buildFromTemplate(template);
|
||||
menu.popup(bridge().window());
|
||||
}, [onInstall]);
|
||||
|
||||
const onSearchQueryChange = useCallback((event: OnChangeEvent) => {
|
||||
setSearchQuery(event.value);
|
||||
@ -157,28 +174,14 @@ export default function(props: Props) {
|
||||
}
|
||||
}
|
||||
|
||||
function renderInstallFromFile(): any {
|
||||
return null;
|
||||
|
||||
// Disabled for now since there are already options for developments,
|
||||
// and installing from file can be done by dropping the file in /plugins
|
||||
|
||||
// return (
|
||||
// <div>
|
||||
// {props.renderLabel(props.themeId, _('Install plugin from file'))}
|
||||
// <InstallButton level={ButtonLevel.Primary} onClick={onInstall} title={_('Install plugin')}/>
|
||||
// <div style={{ display: 'flex', flex: 1 }}/>
|
||||
// </div>
|
||||
// );
|
||||
}
|
||||
|
||||
const pluginItems = usePluginItems(pluginService.plugins, pluginSettings);
|
||||
|
||||
return (
|
||||
<Root>
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
{props.renderLabel(props.themeId, _('Search for plugins'))}
|
||||
{props.renderHeader(props.themeId, _('Search for plugins'))}
|
||||
<SearchPlugins
|
||||
maxWidth={maxWidth}
|
||||
themeId={props.themeId}
|
||||
searchQuery={searchQuery}
|
||||
pluginSettings={pluginSettings}
|
||||
@ -188,10 +191,15 @@ export default function(props: Props) {
|
||||
/>
|
||||
</div>
|
||||
|
||||
{props.renderLabel(props.themeId, _('Manage your plugins'))}
|
||||
{renderUserPlugins(pluginItems)}
|
||||
|
||||
{renderInstallFromFile()}
|
||||
<div>
|
||||
<div style={{ display: 'flex', flexDirection: 'row', maxWidth }}>
|
||||
<div style={{ display: 'flex', flex: 1 }}>
|
||||
{props.renderHeader(props.themeId, _('Manage your plugins'))}
|
||||
</div>
|
||||
<ToolsButton tooltip={_('Plugin tools')} iconName="fas fa-cog" level={ButtonLevel.Primary} onClick={onToolsClick}/>
|
||||
</div>
|
||||
{renderUserPlugins(pluginItems)}
|
||||
</div>
|
||||
</Root>
|
||||
);
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ interface Props {
|
||||
pluginSettings: PluginSettings;
|
||||
onPluginSettingsChange(event: any): void;
|
||||
renderDescription: Function;
|
||||
maxWidth: number;
|
||||
}
|
||||
|
||||
let repoApi_: RepositoryApi = null;
|
||||
@ -99,7 +100,7 @@ export default function(props: Props) {
|
||||
|
||||
return (
|
||||
<Root>
|
||||
<div style={{ marginBottom: 10, width: 250 }}>
|
||||
<div style={{ marginBottom: 10, width: props.maxWidth }}>
|
||||
<SearchInput
|
||||
inputRef={null}
|
||||
value={props.searchQuery}
|
||||
|
Loading…
Reference in New Issue
Block a user