1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-01-23 18:53:36 +02:00
This commit is contained in:
Laurent Cozic 2023-09-18 12:51:21 +01:00
parent fc8e54319d
commit 831a0480c9
4 changed files with 135 additions and 2 deletions

View File

@ -728,6 +728,7 @@ function useMenu(props: Props) {
{ {
label: _('Note list style'), label: _('Note list style'),
submenu: noteListMenuItems, submenu: noteListMenuItems,
visible: noteListMenuItems.length > 1,
}, },
separator(), separator(),
{ {

View File

@ -1,11 +1,11 @@
import { ListRenderer } from '../plugins/api/noteListType'; import { ListRenderer } from '../plugins/api/noteListType';
import defaultLeftToRightItemRenderer from '../noteList/defaultLeftToRightListRenderer'; // import defaultLeftToRightItemRenderer from '../noteList/defaultLeftToRightListRenderer';
import defaultListRenderer from '../noteList/defaultListRenderer'; import defaultListRenderer from '../noteList/defaultListRenderer';
import { Store } from 'redux'; import { Store } from 'redux';
const renderers_: ListRenderer[] = [ const renderers_: ListRenderer[] = [
defaultListRenderer, defaultListRenderer,
defaultLeftToRightItemRenderer, // defaultLeftToRightItemRenderer,
]; ];
export const getListRendererIds = () => { export const getListRendererIds = () => {

View File

@ -5,6 +5,21 @@ import { registerRenderer } from '../../noteList/renderers';
import Plugin from '../Plugin'; import Plugin from '../Plugin';
import { ListRenderer } from './noteListType'; import { ListRenderer } from './noteListType';
/**
* This API allows you to customise how each note in the note list is rendered.
* The renderer you implement follows a unidirectional data flow.
*
* The app provides the required dependencies whenever a note is updated - you
* process these dependencies, and return some props, which are then passed to
* your template and rendered. See [[[ListRenderer]]] for a detailed description
* of each property of the renderer.
*
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/note_list_renderer)
*
* The default list renderer is implemented using the same API, so it worth checking it too:
*
* [Default list renderer](https://github.com/laurent22/joplin/tree/dev/packages/lib/services/noteList/defaultListRenderer.ts)
*/
export default class JoplinViewsNoteList { export default class JoplinViewsNoteList {
private plugin_: Plugin; private plugin_: Plugin;

View File

@ -20,6 +20,24 @@ export interface OnChangeEvent {
export type OnRenderNoteHandler = (props: any)=> Promise<RenderNoteView>; export type OnRenderNoteHandler = (props: any)=> Promise<RenderNoteView>;
export type OnChangeHandler = (event: OnChangeEvent)=> Promise<void>; export type OnChangeHandler = (event: OnChangeEvent)=> Promise<void>;
// Most of these are the built-in note properties, such as `note.title`,
// `note.todo_completed`, etc.
//
// Additionally, the `item.*` properties are specific to the rendered item. The
// most important being `item.selected`, which you can use to display the
// selected note in a different way.
//
// Finally some special properties are provided to make it easier to render
// notes. In particular, if possible prefer `note.titleHtml` to `note.title`
// since some important processing has already been done on the string, such as
// handling the search highlighter and escaping. Since it's HTML and already
// escaped you would insert it using `{{{titleHtml}}}` (triple-mustache syntax,
// which disables escaping).
//
// `notes.tag` gives you the list of tags associated with the note.
//
// `note.isWatched` tells you if the note is currently opened in an external
// editor. In which case you would generally display some indicator.
export type ListRendererDepependency = export type ListRendererDepependency =
ListRendererDatabaseDependency | ListRendererDatabaseDependency |
'item.size.width' | 'item.size.width' |
@ -30,13 +48,112 @@ export type ListRendererDepependency =
'note.tags'; 'note.tags';
export interface ListRenderer { export interface ListRenderer {
// It must be unique to your plugin.
id: string; id: string;
// Can be top to bottom or left to right. Left to right gives you more
// option to set the size of the items since you set both its width and
// height.
flow: ItemFlow; flow: ItemFlow;
// The size of each item must be specified in advance for performance
// reasons, and cannot be changed afterwards. If the item flow is top to
// bottom, you only need to specificy the item height (the width will be
// ignored).
itemSize: Size; itemSize: Size;
// The CSS is relative to the list item container. What will appear in the
// page is essentially `.note-list-item { YOUR_CSS; }`. It means you can use
// child combinator with guarantee it will only apply to your own items. In
// this example, the styling will apply to `.note-list-item > .content`:
//
// ```css
// > .content {
// padding: 10px;
// }
// ```
//
// In order to get syntax highlighting working here, it's recommended
// installing an editor extension such as [es6-string-html VSCode
// extension](https://marketplace.visualstudio.com/items?itemName=Tobermory.es6-string-html)
itemCss?: string; itemCss?: string;
// List the dependencies that your plugin needs to render the note list
// items. Only these will be passed to your `onRenderNote` handler. Ensure
// that you do not add more than what you need since there is a performance
// penalty for each property.
dependencies: ListRendererDepependency[]; dependencies: ListRendererDepependency[];
// This is the HTML template that will be used to render the note list item.
// This is a [Mustache template](https://github.com/janl/mustache.js) and it
// will receive the variable you return from `onRenderNote` as tags. For
// example, if you return a property named `formattedDate` from
// `onRenderNote`, you can insert it in the template using `Created date:
// {{formattedDate}}`.
//
// In order to get syntax highlighting working here, it's recommended
// installing an editor extension such as [es6-string-html VSCode
// extension](https://marketplace.visualstudio.com/items?itemName=Tobermory.es6-string-html)
itemTemplate: string; itemTemplate: string;
// This user-facing text is used for example in the View menu, so that your
// renderer can be selected.
label: ()=> Promise<string>; label: ()=> Promise<string>;
// This is where most of the real-time processing will happen. When a note
// is rendered for the first time and every time it changes, this handler
// receives the properties specified in the `dependencies` property. You can
// then process them, load any additional data you need, and once done you
// need to return the properties that are needed in the `itemTemplate` HTML.
// Again, to use the formatted date example, you could have such a renderer:
//
// ```typescript
// dependencies: [
// 'note.title',
// 'note.created_time',
// ],
//
// itemTemplate: // html
// `
// <div>
// Title: {{note.title}}<br/>
// Date: {{formattedDate}}
// </div>
// `,
//
// onRenderNote: async (props: any) => {
// const formattedDate = dayjs(props.note.created_time).format();
// return {
// // Also return the props, so that note.title is available from the
// // template
// ...props,
// formattedDate,
// }
// },
// ```
onRenderNote: OnRenderNoteHandler; onRenderNote: OnRenderNoteHandler;
// This handler allows adding some interacivity to the note renderer -
// whenever an input element within the item is changed (for example, when a
// checkbox is clicked, or a text input is changed), this `onChange` handler
// is going to be called.
//
// You can inspect `event.elementId` to know which element had some changes,
// and `event.value` to know the new value. `event.noteId` also tells you
// what note is affected, so that you can potentially apply changes to it.
//
// You specify the element ID, by setting a `data-id` attribute on the
// input.
//
// For example, if you have such a template:
//
// ```html
// <div>
// <input type="text" value="{{note.title}}" data-id="noteTitleInput"/>
// </div>
// ```
//
// The event handler will receive an event with `elementId` set to
// `noteTitleInput`.
onChange?: OnChangeHandler; onChange?: OnChangeHandler;
} }