mirror of
https://github.com/laurent22/joplin.git
synced 2025-01-11 18:24:43 +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.onApplyClick = this.onApplyClick.bind(this);
|
||||||
this.renderLabel = this.renderLabel.bind(this);
|
this.renderLabel = this.renderLabel.bind(this);
|
||||||
this.renderDescription = this.renderDescription.bind(this);
|
this.renderDescription = this.renderDescription.bind(this);
|
||||||
|
this.renderHeader = this.renderHeader.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkSyncConfig_() {
|
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) {
|
private renderDescription(themeId: number, description: string) {
|
||||||
return description ? <div style={this.descriptionStyle(themeId)}>{description}</div> : null;
|
return description ? <div style={this.descriptionStyle(themeId)}>{description}</div> : null;
|
||||||
}
|
}
|
||||||
@ -384,6 +403,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
|||||||
}}
|
}}
|
||||||
renderLabel={this.renderLabel}
|
renderLabel={this.renderLabel}
|
||||||
renderDescription={this.renderDescription}
|
renderDescription={this.renderDescription}
|
||||||
|
renderHeader={this.renderHeader}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -43,6 +43,7 @@ export interface PluginItem {
|
|||||||
|
|
||||||
const CellRoot = styled.div`
|
const CellRoot = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
box-sizing: border-box;
|
||||||
background-color: ${props => props.theme.backgroundColor};
|
background-color: ${props => props.theme.backgroundColor};
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
@ -5,13 +5,15 @@ import { _ } from '@joplin/lib/locale';
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import SearchPlugins from './SearchPlugins';
|
import SearchPlugins from './SearchPlugins';
|
||||||
import PluginBox from './PluginBox';
|
import PluginBox from './PluginBox';
|
||||||
// import Button, { ButtonLevel } from '../../../Button/Button';
|
import Button, { ButtonLevel } from '../../../Button/Button';
|
||||||
import bridge from '../../../../services/bridge';
|
import bridge from '../../../../services/bridge';
|
||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import { OnChangeEvent } from '../../../lib/SearchInput/SearchInput';
|
import { OnChangeEvent } from '../../../lib/SearchInput/SearchInput';
|
||||||
import { PluginItem } from './PluginBox';
|
import { PluginItem } from './PluginBox';
|
||||||
const { space } = require('styled-system');
|
const { space } = require('styled-system');
|
||||||
|
|
||||||
|
const maxWidth: number = 250;
|
||||||
|
|
||||||
const Root = styled.div`
|
const Root = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -23,7 +25,9 @@ const UserPluginsRoot = styled.div`
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// const InstallButton = styled(Button)``;
|
const ToolsButton = styled(Button)`
|
||||||
|
margin-right: 2px;
|
||||||
|
`;
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
value: any;
|
value: any;
|
||||||
@ -31,6 +35,7 @@ interface Props {
|
|||||||
onChange: Function;
|
onChange: Function;
|
||||||
renderLabel: Function;
|
renderLabel: Function;
|
||||||
renderDescription: Function;
|
renderDescription: Function;
|
||||||
|
renderHeader: Function;
|
||||||
}
|
}
|
||||||
|
|
||||||
function usePluginItems(plugins: Plugins, settings: PluginSettings): PluginItem[] {
|
function usePluginItems(plugins: Plugins, settings: PluginSettings): PluginItem[] {
|
||||||
@ -96,22 +101,34 @@ export default function(props: Props) {
|
|||||||
props.onChange({ value: pluginService.serializePluginSettings(newSettings) });
|
props.onChange({ value: pluginService.serializePluginSettings(newSettings) });
|
||||||
}, [pluginSettings, props.onChange]);
|
}, [pluginSettings, props.onChange]);
|
||||||
|
|
||||||
// const onInstall = useCallback(async () => {
|
const onInstall = useCallback(async () => {
|
||||||
// const result = bridge().showOpenDialog({
|
const result = bridge().showOpenDialog({
|
||||||
// filters: [{ name: 'Joplin Plugin Archive', extensions: ['jpl'] }],
|
filters: [{ name: 'Joplin Plugin Archive', extensions: ['jpl'] }],
|
||||||
// });
|
});
|
||||||
|
|
||||||
// const filePath = result && result.length ? result[0] : null;
|
const filePath = result && result.length ? result[0] : null;
|
||||||
// if (!filePath) return;
|
if (!filePath) return;
|
||||||
|
|
||||||
// const plugin = await pluginService.installPlugin(filePath);
|
const plugin = await pluginService.installPlugin(filePath);
|
||||||
|
|
||||||
// const newSettings = produce(pluginSettings, (draft: PluginSettings) => {
|
const newSettings = produce(pluginSettings, (draft: PluginSettings) => {
|
||||||
// draft[plugin.manifest.id] = defaultPluginSetting();
|
draft[plugin.manifest.id] = defaultPluginSetting();
|
||||||
// });
|
});
|
||||||
|
|
||||||
// props.onChange({ value: pluginService.serializePluginSettings(newSettings) });
|
props.onChange({ value: pluginService.serializePluginSettings(newSettings) });
|
||||||
// }, [pluginSettings, props.onChange]);
|
}, [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) => {
|
const onSearchQueryChange = useCallback((event: OnChangeEvent) => {
|
||||||
setSearchQuery(event.value);
|
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);
|
const pluginItems = usePluginItems(pluginService.plugins, pluginSettings);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Root>
|
<Root>
|
||||||
<div style={{ marginBottom: 20 }}>
|
<div style={{ marginBottom: 20 }}>
|
||||||
{props.renderLabel(props.themeId, _('Search for plugins'))}
|
{props.renderHeader(props.themeId, _('Search for plugins'))}
|
||||||
<SearchPlugins
|
<SearchPlugins
|
||||||
|
maxWidth={maxWidth}
|
||||||
themeId={props.themeId}
|
themeId={props.themeId}
|
||||||
searchQuery={searchQuery}
|
searchQuery={searchQuery}
|
||||||
pluginSettings={pluginSettings}
|
pluginSettings={pluginSettings}
|
||||||
@ -188,10 +191,15 @@ export default function(props: Props) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{props.renderLabel(props.themeId, _('Manage your plugins'))}
|
<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)}
|
{renderUserPlugins(pluginItems)}
|
||||||
|
</div>
|
||||||
{renderInstallFromFile()}
|
|
||||||
</Root>
|
</Root>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ interface Props {
|
|||||||
pluginSettings: PluginSettings;
|
pluginSettings: PluginSettings;
|
||||||
onPluginSettingsChange(event: any): void;
|
onPluginSettingsChange(event: any): void;
|
||||||
renderDescription: Function;
|
renderDescription: Function;
|
||||||
|
maxWidth: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
let repoApi_: RepositoryApi = null;
|
let repoApi_: RepositoryApi = null;
|
||||||
@ -99,7 +100,7 @@ export default function(props: Props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Root>
|
<Root>
|
||||||
<div style={{ marginBottom: 10, width: 250 }}>
|
<div style={{ marginBottom: 10, width: props.maxWidth }}>
|
||||||
<SearchInput
|
<SearchInput
|
||||||
inputRef={null}
|
inputRef={null}
|
||||||
value={props.searchQuery}
|
value={props.searchQuery}
|
||||||
|
Loading…
Reference in New Issue
Block a user