You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-07-16 00:14:34 +02:00
Desktop: Sort plugin results according to recommended property, and display Recommended tag
This commit is contained in:
@ -873,6 +873,16 @@ class Application extends BaseApplication {
|
|||||||
// });
|
// });
|
||||||
// }, 2000);
|
// }, 2000);
|
||||||
|
|
||||||
|
// setTimeout(() => {
|
||||||
|
// this.dispatch({
|
||||||
|
// type: 'NAV_GO',
|
||||||
|
// routeName: 'Config',
|
||||||
|
// props: {
|
||||||
|
// defaultSection: 'plugins',
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// }, 2000);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +133,21 @@ const StyledDescription = styled.div`
|
|||||||
line-height: 1.6em;
|
line-height: 1.6em;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const RecommendedBadge = styled.a`
|
||||||
|
font-family: ${props => props.theme.fontFamily};
|
||||||
|
color: ${props => props.theme.colorWarn};
|
||||||
|
font-size: ${props => props.theme.fontSize}px;
|
||||||
|
border: 1px solid ${props => props.theme.colorWarn};
|
||||||
|
padding: 5px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border-radius: 50px;
|
||||||
|
opacity: 0.8;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export default function(props: Props) {
|
export default function(props: Props) {
|
||||||
const item = useMemo(() => {
|
const item = useMemo(() => {
|
||||||
return props.item ? props.item : manifestToItem(props.manifest);
|
return props.item ? props.item : manifestToItem(props.manifest);
|
||||||
@ -144,6 +159,10 @@ export default function(props: Props) {
|
|||||||
bridge().openExternal(manifest.homepage_url);
|
bridge().openExternal(manifest.homepage_url);
|
||||||
}, [item]);
|
}, [item]);
|
||||||
|
|
||||||
|
const onRecommendedClick = useCallback(() => {
|
||||||
|
bridge().openExternal('https://github.com/joplin/plugins/blob/master/readme/recommended.md#recommended-plugins');
|
||||||
|
}, []);
|
||||||
|
|
||||||
// For plugins in dev mode things like enabling/disabling or
|
// For plugins in dev mode things like enabling/disabling or
|
||||||
// uninstalling them doesn't make sense, as that should be done by
|
// uninstalling them doesn't make sense, as that should be done by
|
||||||
// adding/removing them from wherever they were loaded from.
|
// adding/removing them from wherever they were loaded from.
|
||||||
@ -222,11 +241,18 @@ export default function(props: Props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderRecommendedBadge() {
|
||||||
|
if (props.onToggle) return null;
|
||||||
|
if (!item.manifest._recommended) return null;
|
||||||
|
return <RecommendedBadge href="#" title={_('The Joplin team has vetted this plugin and it meets our standards for security and performance.')} onClick={onRecommendedClick}><i className="fas fa-crown"></i></RecommendedBadge>;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CellRoot isCompatible={props.isCompatible}>
|
<CellRoot isCompatible={props.isCompatible}>
|
||||||
<CellTop>
|
<CellTop>
|
||||||
<StyledNameAndVersion mb={'5px'}><StyledName onClick={onNameClick} href="#" style={{ marginRight: 5 }}>{item.manifest.name} {item.deleted ? _('(%s)', 'Deleted') : ''}</StyledName><StyledVersion>v{item.manifest.version}</StyledVersion></StyledNameAndVersion>
|
<StyledNameAndVersion mb={'5px'}><StyledName onClick={onNameClick} href="#" style={{ marginRight: 5 }}>{item.manifest.name} {item.deleted ? _('(%s)', 'Deleted') : ''}</StyledName><StyledVersion>v{item.manifest.version}</StyledVersion></StyledNameAndVersion>
|
||||||
{renderToggleButton()}
|
{renderToggleButton()}
|
||||||
|
{renderRecommendedBadge()}
|
||||||
</CellTop>
|
</CellTop>
|
||||||
<CellContent>
|
<CellContent>
|
||||||
<StyledDescription>{item.manifest.description}</StyledDescription>
|
<StyledDescription>{item.manifest.description}</StyledDescription>
|
||||||
|
@ -30,6 +30,14 @@ interface Props {
|
|||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sortManifestResults(results: PluginManifest[]): PluginManifest[] {
|
||||||
|
return results.sort((m1, m2) => {
|
||||||
|
if (m1._recommended && !m2._recommended) return -1;
|
||||||
|
if (!m1._recommended && m2._recommended) return +1;
|
||||||
|
return m1.name.toLowerCase() < m2.name.toLowerCase() ? -1 : +1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export default function(props: Props) {
|
export default function(props: Props) {
|
||||||
const [searchStarted, setSearchStarted] = useState(false);
|
const [searchStarted, setSearchStarted] = useState(false);
|
||||||
const [manifests, setManifests] = useState<PluginManifest[]>([]);
|
const [manifests, setManifests] = useState<PluginManifest[]>([]);
|
||||||
@ -47,7 +55,7 @@ export default function(props: Props) {
|
|||||||
setSearchResultCount(null);
|
setSearchResultCount(null);
|
||||||
} else {
|
} else {
|
||||||
const r = await props.repoApi().search(props.searchQuery);
|
const r = await props.repoApi().search(props.searchQuery);
|
||||||
setManifests(r);
|
setManifests(sortManifestResults(r));
|
||||||
setSearchResultCount(r.length);
|
setSearchResultCount(r.length);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -24,6 +24,13 @@ export default function manifestFromObject(o: any): PluginManifest {
|
|||||||
return o[name];
|
return o[name];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getBoolean = (name: string, required: boolean = true, defaultValue: boolean = false): boolean => {
|
||||||
|
if (required && !o[name]) throw new Error(`Missing required field: ${name}`);
|
||||||
|
if (!o[name]) return defaultValue;
|
||||||
|
if (typeof o[name] !== 'boolean') throw new Error(`Field must be a boolean: ${name}`);
|
||||||
|
return o[name];
|
||||||
|
};
|
||||||
|
|
||||||
const permissions: PluginPermission[] = [];
|
const permissions: PluginPermission[] = [];
|
||||||
|
|
||||||
const manifest: PluginManifest = {
|
const manifest: PluginManifest = {
|
||||||
@ -39,6 +46,8 @@ export default function manifestFromObject(o: any): PluginManifest {
|
|||||||
repository_url: getString('repository_url', false),
|
repository_url: getString('repository_url', false),
|
||||||
keywords: getStrings('keywords', false),
|
keywords: getStrings('keywords', false),
|
||||||
permissions: permissions,
|
permissions: permissions,
|
||||||
|
|
||||||
|
_recommended: getBoolean('_recommended', false, false),
|
||||||
};
|
};
|
||||||
|
|
||||||
validatePluginId(manifest.id);
|
validatePluginId(manifest.id);
|
||||||
|
@ -20,4 +20,6 @@ export interface PluginManifest {
|
|||||||
_publish_hash?: string;
|
_publish_hash?: string;
|
||||||
_publish_commit?: string;
|
_publish_commit?: string;
|
||||||
_npm_package_name?: string;
|
_npm_package_name?: string;
|
||||||
|
_obsolete?: boolean;
|
||||||
|
_recommended?: boolean;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user