| 
									
										
										
										
											2025-08-22 11:24:27 +03:00
										 |  |  | import { useCallback, useEffect, useMemo, useState } from "preact/hooks"; | 
					
						
							| 
									
										
										
										
											2025-08-21 20:16:06 +03:00
										 |  |  | import Dropdown from "../react/Dropdown"; | 
					
						
							|  |  |  | import { NOTE_TYPES } from "../../services/note_types"; | 
					
						
							| 
									
										
										
										
											2025-08-22 12:34:21 +03:00
										 |  |  | import { FormDropdownDivider, FormListBadge, FormListItem } from "../react/FormList"; | 
					
						
							|  |  |  | import { getAvailableLocales, t } from "../../services/i18n"; | 
					
						
							| 
									
										
										
										
											2025-08-25 17:17:56 +03:00
										 |  |  | import { useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumEvent, useTriliumOption } from "../react/hooks"; | 
					
						
							| 
									
										
										
										
											2025-08-21 20:30:12 +03:00
										 |  |  | import mime_types from "../../services/mime_types"; | 
					
						
							| 
									
										
										
										
											2025-10-14 18:42:20 +03:00
										 |  |  | import { Locale, LOCALES, NoteType, ToggleInParentResponse } from "@triliumnext/commons"; | 
					
						
							| 
									
										
										
										
											2025-08-21 20:56:37 +03:00
										 |  |  | import server from "../../services/server"; | 
					
						
							|  |  |  | import dialog from "../../services/dialog"; | 
					
						
							| 
									
										
										
										
											2025-08-21 21:24:01 +03:00
										 |  |  | import FormToggle from "../react/FormToggle"; | 
					
						
							|  |  |  | import FNote from "../../entities/fnote"; | 
					
						
							|  |  |  | import protected_session from "../../services/protected_session"; | 
					
						
							| 
									
										
										
										
											2025-08-21 22:19:26 +03:00
										 |  |  | import FormDropdownList from "../react/FormDropdownList"; | 
					
						
							| 
									
										
										
										
											2025-08-22 11:24:27 +03:00
										 |  |  | import toast from "../../services/toast"; | 
					
						
							| 
									
										
										
										
											2025-08-22 11:57:45 +03:00
										 |  |  | import branches from "../../services/branches"; | 
					
						
							|  |  |  | import sync from "../../services/sync"; | 
					
						
							| 
									
										
										
										
											2025-08-22 15:40:15 +03:00
										 |  |  | import HelpButton from "../react/HelpButton"; | 
					
						
							| 
									
										
										
										
											2025-08-22 15:53:52 +03:00
										 |  |  | import { TabContext } from "./ribbon-interface"; | 
					
						
							| 
									
										
										
										
											2025-08-27 19:42:20 +03:00
										 |  |  | import Modal from "../react/Modal"; | 
					
						
							|  |  |  | import { CodeMimeTypesList } from "../type_widgets/options/code_notes"; | 
					
						
							| 
									
										
										
										
											2025-08-27 19:56:14 +03:00
										 |  |  | import { ContentLanguagesList } from "../type_widgets/options/i18n"; | 
					
						
							| 
									
										
										
										
											2025-10-14 18:42:20 +03:00
										 |  |  | import { LocaleSelector } from "../type_widgets/options/components/LocaleSelector"; | 
					
						
							| 
									
										
										
										
											2025-08-21 20:16:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-22 15:53:52 +03:00
										 |  |  | export default function BasicPropertiesTab({ note }: TabContext) { | 
					
						
							| 
									
										
										
										
											2025-08-21 20:16:06 +03:00
										 |  |  |     return ( | 
					
						
							| 
									
										
										
										
											2025-09-14 10:16:52 +03:00
										 |  |  |         <div className="basic-properties-widget"> | 
					
						
							| 
									
										
										
										
											2025-08-21 21:24:01 +03:00
										 |  |  |             <NoteTypeWidget note={note} /> | 
					
						
							|  |  |  |             <ProtectedNoteSwitch note={note} /> | 
					
						
							| 
									
										
										
										
											2025-08-21 22:19:26 +03:00
										 |  |  |             <EditabilitySelect note={note} /> | 
					
						
							| 
									
										
										
										
											2025-08-22 11:24:27 +03:00
										 |  |  |             <BookmarkSwitch note={note} /> | 
					
						
							| 
									
										
										
										
											2025-08-22 11:57:45 +03:00
										 |  |  |             <SharedSwitch note={note} /> | 
					
						
							| 
									
										
										
										
											2025-08-22 12:14:53 +03:00
										 |  |  |             <TemplateSwitch note={note} /> | 
					
						
							| 
									
										
										
										
											2025-08-22 12:34:21 +03:00
										 |  |  |             <NoteLanguageSwitch note={note} /> | 
					
						
							| 
									
										
										
										
											2025-08-21 20:16:06 +03:00
										 |  |  |         </div> | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-21 21:24:01 +03:00
										 |  |  | function NoteTypeWidget({ note }: { note?: FNote | null }) { | 
					
						
							| 
									
										
										
										
											2025-08-21 20:16:06 +03:00
										 |  |  |     const noteTypes = useMemo(() => NOTE_TYPES.filter((nt) => !nt.reserved && !nt.static), []); | 
					
						
							| 
									
										
										
										
											2025-08-21 20:30:12 +03:00
										 |  |  |     const [ codeNotesMimeTypes ] = useTriliumOption("codeNotesMimeTypes"); | 
					
						
							| 
									
										
										
										
											2025-08-27 19:49:22 +03:00
										 |  |  |     const mimeTypes = useMemo(() => { | 
					
						
							|  |  |  |         mime_types.loadMimeTypes(); | 
					
						
							|  |  |  |         return mime_types.getMimeTypes().filter(mimeType => mimeType.enabled) | 
					
						
							|  |  |  |     }, [ codeNotesMimeTypes ]); | 
					
						
							| 
									
										
										
										
											2025-08-21 21:01:57 +03:00
										 |  |  |     const notSelectableNoteTypes = useMemo(() => NOTE_TYPES.filter((nt) => nt.reserved || nt.static).map((nt) => nt.type), []); | 
					
						
							| 
									
										
										
										
											2025-09-14 10:16:52 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-21 20:56:37 +03:00
										 |  |  |     const currentNoteType = useNoteProperty(note, "type") ?? undefined; | 
					
						
							|  |  |  |     const currentNoteMime = useNoteProperty(note, "mime"); | 
					
						
							| 
									
										
										
										
											2025-08-27 19:42:20 +03:00
										 |  |  |     const [ modalShown, setModalShown ] = useState(false); | 
					
						
							| 
									
										
										
										
											2025-08-21 20:56:37 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const changeNoteType = useCallback(async (type: NoteType, mime?: string) => { | 
					
						
							|  |  |  |         if (!note || (type === currentNoteType && mime === currentNoteMime)) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Confirm change if the note already has a content.
 | 
					
						
							|  |  |  |         if (type !== currentNoteType) { | 
					
						
							|  |  |  |             const blob = await note.getBlob(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (blob?.content && blob.content.trim().length && | 
					
						
							|  |  |  |                 !await (dialog.confirm(t("note_types.confirm-change")))) { | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await server.put(`notes/${note.noteId}/type`, { type, mime }); | 
					
						
							|  |  |  |     }, [ note, currentNoteType, currentNoteMime ]); | 
					
						
							| 
									
										
										
										
											2025-08-21 20:16:06 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return ( | 
					
						
							| 
									
										
										
										
											2025-08-21 20:56:37 +03:00
										 |  |  |         <div className="note-type-container"> | 
					
						
							| 
									
										
										
										
											2025-08-21 20:38:19 +03:00
										 |  |  |             <span>{t("basic_properties.note_type")}:</span>   | 
					
						
							|  |  |  |             <Dropdown | 
					
						
							|  |  |  |                 dropdownContainerClassName="note-type-dropdown" | 
					
						
							| 
									
										
										
										
											2025-08-21 20:56:37 +03:00
										 |  |  |                 text={<span className="note-type-desc">{findTypeTitle(currentNoteType, currentNoteMime)}</span>} | 
					
						
							| 
									
										
										
										
											2025-08-21 21:01:57 +03:00
										 |  |  |                 disabled={notSelectableNoteTypes.includes(currentNoteType ?? "text")} | 
					
						
							| 
									
										
										
										
											2025-08-21 20:38:19 +03:00
										 |  |  |             > | 
					
						
							| 
									
										
										
										
											2025-08-21 20:56:37 +03:00
										 |  |  |                 {noteTypes.map(({ isNew, isBeta, type, mime, title }) => { | 
					
						
							| 
									
										
										
										
											2025-08-21 20:38:19 +03:00
										 |  |  |                     const badges: FormListBadge[] = []; | 
					
						
							| 
									
										
										
										
											2025-08-21 20:56:37 +03:00
										 |  |  |                     if (isNew) { | 
					
						
							| 
									
										
										
										
											2025-08-21 20:38:19 +03:00
										 |  |  |                         badges.push({ | 
					
						
							|  |  |  |                             className: "new-note-type-badge", | 
					
						
							|  |  |  |                             text: t("note_types.new-feature") | 
					
						
							|  |  |  |                         }); | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2025-08-21 20:56:37 +03:00
										 |  |  |                     if (isBeta) { | 
					
						
							| 
									
										
										
										
											2025-08-21 20:38:19 +03:00
										 |  |  |                         badges.push({ | 
					
						
							|  |  |  |                             text: t("note_types.beta-feature") | 
					
						
							|  |  |  |                         }); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-21 20:56:37 +03:00
										 |  |  |                     const checked = (type === currentNoteType); | 
					
						
							|  |  |  |                     if (type !== "code") { | 
					
						
							| 
									
										
										
										
											2025-08-21 20:38:19 +03:00
										 |  |  |                         return ( | 
					
						
							|  |  |  |                             <FormListItem | 
					
						
							| 
									
										
										
										
											2025-08-21 20:56:37 +03:00
										 |  |  |                                 checked={checked} | 
					
						
							| 
									
										
										
										
											2025-08-21 20:38:19 +03:00
										 |  |  |                                 badges={badges} | 
					
						
							| 
									
										
										
										
											2025-08-21 20:56:37 +03:00
										 |  |  |                                 onClick={() => changeNoteType(type, mime)} | 
					
						
							| 
									
										
										
										
											2025-09-14 10:16:52 +03:00
										 |  |  |                             >{title}</FormListItem> | 
					
						
							| 
									
										
										
										
											2025-08-21 20:38:19 +03:00
										 |  |  |                         ); | 
					
						
							|  |  |  |                     } else { | 
					
						
							|  |  |  |                         return ( | 
					
						
							|  |  |  |                             <> | 
					
						
							| 
									
										
										
										
											2025-08-22 12:34:21 +03:00
										 |  |  |                                 <FormDropdownDivider /> | 
					
						
							| 
									
										
										
										
											2025-08-21 20:56:37 +03:00
										 |  |  |                                 <FormListItem | 
					
						
							|  |  |  |                                     checked={checked} | 
					
						
							| 
									
										
										
										
											2025-09-14 10:16:52 +03:00
										 |  |  |                                     disabled | 
					
						
							| 
									
										
										
										
											2025-08-21 20:56:37 +03:00
										 |  |  |                                 > | 
					
						
							|  |  |  |                                     <strong>{title}</strong> | 
					
						
							| 
									
										
										
										
											2025-08-21 20:38:19 +03:00
										 |  |  |                                 </FormListItem> | 
					
						
							|  |  |  |                             </> | 
					
						
							|  |  |  |                         ) | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 })} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-21 20:56:37 +03:00
										 |  |  |                 {mimeTypes.map(({ title, mime }) => ( | 
					
						
							|  |  |  |                     <FormListItem onClick={() => changeNoteType("code", mime)}> | 
					
						
							|  |  |  |                         {title} | 
					
						
							|  |  |  |                     </FormListItem> | 
					
						
							| 
									
										
										
										
											2025-08-21 20:38:19 +03:00
										 |  |  |                 ))} | 
					
						
							| 
									
										
										
										
											2025-08-27 19:42:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 <FormDropdownDivider /> | 
					
						
							|  |  |  |                 <FormListItem icon="bx bx-cog" onClick={() => setModalShown(true)}>{t("basic_properties.configure_code_notes")}</FormListItem> | 
					
						
							| 
									
										
										
										
											2025-08-21 20:38:19 +03:00
										 |  |  |             </Dropdown> | 
					
						
							| 
									
										
										
										
											2025-08-27 19:42:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |             <Modal | 
					
						
							|  |  |  |                 className="code-mime-types-modal" | 
					
						
							|  |  |  |                 title={t("code_mime_types.title")} | 
					
						
							|  |  |  |                 show={modalShown} onHidden={() => setModalShown(false)} | 
					
						
							|  |  |  |                 size="xl" scrollable | 
					
						
							|  |  |  |             > | 
					
						
							|  |  |  |                 <CodeMimeTypesList /> | 
					
						
							|  |  |  |             </Modal> | 
					
						
							| 
									
										
										
										
											2025-08-21 20:56:37 +03:00
										 |  |  |         </div> | 
					
						
							| 
									
										
										
										
											2025-09-14 10:16:52 +03:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2025-08-21 20:38:19 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-21 21:24:01 +03:00
										 |  |  | function ProtectedNoteSwitch({ note }: { note?: FNote | null }) { | 
					
						
							|  |  |  |     const isProtected = useNoteProperty(note, "isProtected"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ( | 
					
						
							|  |  |  |         <div className="protected-note-switch-container"> | 
					
						
							|  |  |  |             <FormToggle | 
					
						
							|  |  |  |                 switchOnName={t("protect_note.toggle-on")} switchOnTooltip={t("protect_note.toggle-on-hint")} | 
					
						
							|  |  |  |                 switchOffName={t("protect_note.toggle-off")} switchOffTooltip={t("protect_note.toggle-off-hint")} | 
					
						
							| 
									
										
										
										
											2025-08-27 16:16:25 +03:00
										 |  |  |                 currentValue={!!isProtected} | 
					
						
							| 
									
										
										
										
											2025-08-22 11:24:27 +03:00
										 |  |  |                 onChange={(shouldProtect) => note && protected_session.protectNote(note.noteId, shouldProtect, false)} | 
					
						
							| 
									
										
										
										
											2025-08-21 21:24:01 +03:00
										 |  |  |             /> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-21 22:19:26 +03:00
										 |  |  | function EditabilitySelect({ note }: { note?: FNote | null }) { | 
					
						
							|  |  |  |     const [ readOnly, setReadOnly ] = useNoteLabelBoolean(note, "readOnly"); | 
					
						
							| 
									
										
										
										
											2025-09-14 10:16:52 +03:00
										 |  |  |     const [ autoReadOnlyDisabled, setAutoReadOnlyDisabled ] = useNoteLabelBoolean(note, "autoReadOnlyDisabled"); | 
					
						
							| 
									
										
										
										
											2025-08-21 22:19:26 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const options = useMemo(() => ([ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             value: "auto", | 
					
						
							|  |  |  |             label: t("editability_select.auto"), | 
					
						
							|  |  |  |             description: t("editability_select.note_is_editable"), | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             value: "readOnly", | 
					
						
							|  |  |  |             label: t("editability_select.read_only"), | 
					
						
							|  |  |  |             description: t("editability_select.note_is_read_only") | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             value: "autoReadOnlyDisabled", | 
					
						
							|  |  |  |             label: t("editability_select.always_editable"), | 
					
						
							|  |  |  |             description: t("editability_select.note_is_always_editable") | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ]), []); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ( | 
					
						
							|  |  |  |         <div class="editability-select-container"> | 
					
						
							|  |  |  |             <span>{t("basic_properties.editable")}:</span>   | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             <FormDropdownList | 
					
						
							| 
									
										
										
										
											2025-08-22 11:42:07 +03:00
										 |  |  |                 dropdownContainerClassName="editability-dropdown" | 
					
						
							| 
									
										
										
										
											2025-08-21 22:19:26 +03:00
										 |  |  |                 values={options} | 
					
						
							|  |  |  |                 currentValue={ readOnly ? "readOnly" : autoReadOnlyDisabled ? "autoReadOnlyDisabled" : "auto" } | 
					
						
							|  |  |  |                 keyProperty="value" titleProperty="label" descriptionProperty="description" | 
					
						
							|  |  |  |                 onChange={(editability: string) => { | 
					
						
							|  |  |  |                     setReadOnly(editability === "readOnly"); | 
					
						
							|  |  |  |                     setAutoReadOnlyDisabled(editability === "autoReadOnlyDisabled"); | 
					
						
							|  |  |  |                 }} | 
					
						
							|  |  |  |             /> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-22 11:24:27 +03:00
										 |  |  | function BookmarkSwitch({ note }: { note?: FNote | null }) { | 
					
						
							|  |  |  |     const [ isBookmarked, setIsBookmarked ] = useState<boolean>(false); | 
					
						
							|  |  |  |     const refreshState = useCallback(() => { | 
					
						
							|  |  |  |         const isBookmarked = note && !!note.getParentBranches().find((b) => b.parentNoteId === "_lbBookmarks"); | 
					
						
							|  |  |  |         setIsBookmarked(!!isBookmarked); | 
					
						
							|  |  |  |     }, [ note ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     useEffect(() => refreshState(), [ note ]); | 
					
						
							| 
									
										
										
										
											2025-08-24 21:18:48 +03:00
										 |  |  |     useTriliumEvent("entitiesReloaded", ({ loadResults }) => { | 
					
						
							| 
									
										
										
										
											2025-08-22 11:24:27 +03:00
										 |  |  |         if (note && loadResults.getBranchRows().find((b) => b.noteId === note.noteId)) { | 
					
						
							|  |  |  |             refreshState(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ( | 
					
						
							|  |  |  |         <div className="bookmark-switch-container"> | 
					
						
							|  |  |  |             <FormToggle | 
					
						
							|  |  |  |                 switchOnName={t("bookmark_switch.bookmark")} switchOnTooltip={t("bookmark_switch.bookmark_this_note")} | 
					
						
							|  |  |  |                 switchOffName={t("bookmark_switch.bookmark")} switchOffTooltip={t("bookmark_switch.remove_bookmark")} | 
					
						
							| 
									
										
										
										
											2025-09-14 10:16:52 +03:00
										 |  |  |                 currentValue={isBookmarked} | 
					
						
							| 
									
										
										
										
											2025-08-22 11:24:27 +03:00
										 |  |  |                 onChange={async (shouldBookmark) => { | 
					
						
							|  |  |  |                     if (!note) return; | 
					
						
							|  |  |  |                     const resp = await server.put<ToggleInParentResponse>(`notes/${note.noteId}/toggle-in-parent/_lbBookmarks/${shouldBookmark}`); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (!resp.success && "message" in resp) { | 
					
						
							|  |  |  |                         toast.showError(resp.message); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 }} | 
					
						
							|  |  |  |                 disabled={["root", "_hidden"].includes(note?.noteId ?? "")} | 
					
						
							|  |  |  |             /> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-22 12:14:53 +03:00
										 |  |  | function TemplateSwitch({ note }: { note?: FNote | null }) { | 
					
						
							|  |  |  |     const [ isTemplate, setIsTemplate ] = useNoteLabelBoolean(note, "template"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ( | 
					
						
							|  |  |  |         <div className="template-switch-container"> | 
					
						
							|  |  |  |             <FormToggle | 
					
						
							|  |  |  |                 switchOnName={t("template_switch.template")} switchOnTooltip={t("template_switch.toggle-on-hint")} | 
					
						
							|  |  |  |                 switchOffName={t("template_switch.template")} switchOffTooltip={t("template_switch.toggle-off-hint")} | 
					
						
							|  |  |  |                 helpPage="KC1HB96bqqHX" | 
					
						
							|  |  |  |                 disabled={note?.noteId.startsWith("_options")} | 
					
						
							|  |  |  |                 currentValue={isTemplate} onChange={setIsTemplate} | 
					
						
							|  |  |  |             /> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-22 11:57:45 +03:00
										 |  |  | function SharedSwitch({ note }: { note?: FNote | null }) { | 
					
						
							|  |  |  |     const [ isShared, setIsShared ] = useState(false); | 
					
						
							|  |  |  |     const refreshState = useCallback(() => { | 
					
						
							|  |  |  |         setIsShared(!!note?.hasAncestor("_share")); | 
					
						
							|  |  |  |     }, [ note ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     useEffect(() => refreshState(), [ note ]); | 
					
						
							| 
									
										
										
										
											2025-08-24 21:18:48 +03:00
										 |  |  |     useTriliumEvent("entitiesReloaded", ({ loadResults }) => { | 
					
						
							| 
									
										
										
										
											2025-08-22 11:57:45 +03:00
										 |  |  |         if (note && loadResults.getBranchRows().find((b) => b.noteId === note.noteId)) { | 
					
						
							|  |  |  |             refreshState(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const switchShareState = useCallback(async (shouldShare: boolean) => { | 
					
						
							|  |  |  |         if (!note) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (shouldShare) { | 
					
						
							|  |  |  |             await branches.cloneNoteToParentNote(note.noteId, "_share"); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             if (note?.getParentBranches().length === 1 && !(await dialog.confirm(t("shared_switch.shared-branch")))) { | 
					
						
							|  |  |  |                 return; | 
					
						
							| 
									
										
										
										
											2025-09-14 10:16:52 +03:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-08-22 11:57:45 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |             const shareBranch = note?.getParentBranches().find((b) => b.parentNoteId === "_share"); | 
					
						
							|  |  |  |             if (!shareBranch?.branchId) return; | 
					
						
							| 
									
										
										
										
											2025-09-14 10:16:52 +03:00
										 |  |  |             await server.remove(`branches/${shareBranch.branchId}?taskId=no-progress-reporting`); | 
					
						
							| 
									
										
										
										
											2025-08-22 11:57:45 +03:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         sync.syncNow(true); | 
					
						
							|  |  |  |     }, [ note ]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ( | 
					
						
							|  |  |  |         <div className="shared-switch-container"> | 
					
						
							|  |  |  |             <FormToggle | 
					
						
							|  |  |  |                 currentValue={isShared} | 
					
						
							|  |  |  |                 onChange={switchShareState} | 
					
						
							|  |  |  |                 switchOnName={t("shared_switch.shared")} switchOnTooltip={t("shared_switch.toggle-on-title")} | 
					
						
							|  |  |  |                 switchOffName={t("shared_switch.shared")} switchOffTooltip={t("shared_switch.toggle-off-title")} | 
					
						
							|  |  |  |                 helpPage="R9pX4DGra2Vt" | 
					
						
							|  |  |  |                 disabled={["root", "_share", "_hidden"].includes(note?.noteId ?? "") || note?.noteId.startsWith("_options")} | 
					
						
							|  |  |  |             /> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-22 12:34:21 +03:00
										 |  |  | function NoteLanguageSwitch({ note }: { note?: FNote | null }) { | 
					
						
							| 
									
										
										
										
											2025-08-25 10:32:11 +03:00
										 |  |  |     const [ languages ] = useTriliumOption("languages"); | 
					
						
							| 
									
										
										
										
											2025-08-22 12:34:21 +03:00
										 |  |  |     const DEFAULT_LOCALE = { | 
					
						
							|  |  |  |         id: "", | 
					
						
							|  |  |  |         name: t("note_language.not_set") | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2025-08-22 15:11:12 +03:00
										 |  |  |     const [ currentNoteLanguage, setCurrentNoteLanguage ] = useNoteLabel(note, "language"); | 
					
						
							| 
									
										
										
										
											2025-08-27 19:56:14 +03:00
										 |  |  |     const [ modalShown, setModalShown ] = useState(false); | 
					
						
							| 
									
										
										
										
											2025-08-22 12:34:21 +03:00
										 |  |  |     const locales = useMemo(() => { | 
					
						
							|  |  |  |         const enabledLanguages = JSON.parse(languages ?? "[]") as string[]; | 
					
						
							|  |  |  |         const filteredLanguages = getAvailableLocales().filter((l) => typeof l !== "object" || enabledLanguages.includes(l.id)); | 
					
						
							| 
									
										
										
										
											2025-10-14 18:42:20 +03:00
										 |  |  |         return filteredLanguages; | 
					
						
							| 
									
										
										
										
											2025-08-22 12:34:21 +03:00
										 |  |  |     }, [ languages ]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-14 10:16:52 +03:00
										 |  |  |     return ( | 
					
						
							| 
									
										
										
										
											2025-08-22 12:34:21 +03:00
										 |  |  |         <div className="note-language-container"> | 
					
						
							| 
									
										
										
										
											2025-08-22 15:40:15 +03:00
										 |  |  |             <span>{t("basic_properties.language")}:</span> | 
					
						
							|  |  |  |               | 
					
						
							| 
									
										
										
										
											2025-10-14 18:42:20 +03:00
										 |  |  |             <LocaleSelector | 
					
						
							|  |  |  |                 locales={locales} | 
					
						
							|  |  |  |                 defaultLocale={DEFAULT_LOCALE} | 
					
						
							|  |  |  |                 currentValue={currentNoteLanguage ?? ""} onChange={setCurrentNoteLanguage} | 
					
						
							|  |  |  |                 extraChildren={( | 
					
						
							|  |  |  |                     <FormListItem | 
					
						
							|  |  |  |                         onClick={() => setModalShown(true)} | 
					
						
							| 
									
										
										
										
											2025-10-14 18:43:56 +03:00
										 |  |  |                         icon="bx bx-cog" | 
					
						
							| 
									
										
										
										
											2025-10-14 18:42:20 +03:00
										 |  |  |                     >{t("note_language.configure-languages")}</FormListItem> | 
					
						
							|  |  |  |                 )} | 
					
						
							|  |  |  |             > | 
					
						
							| 
									
										
										
										
											2025-08-22 12:34:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-10-14 18:42:20 +03:00
										 |  |  |             </LocaleSelector> | 
					
						
							| 
									
										
										
										
											2025-08-22 15:40:15 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-10-08 17:44:17 +03:00
										 |  |  |             <HelpButton helpPage="B0lcI9xz1r8K" style={{ marginInlineStart: "4px" }} /> | 
					
						
							| 
									
										
										
										
											2025-08-27 19:56:14 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |             <Modal | 
					
						
							|  |  |  |                 className="content-languages-modal" | 
					
						
							|  |  |  |                 title={t("content_language.title")} | 
					
						
							|  |  |  |                 show={modalShown} onHidden={() => setModalShown(false)} | 
					
						
							|  |  |  |                 size="lg" scrollable | 
					
						
							|  |  |  |             > | 
					
						
							|  |  |  |                 <ContentLanguagesList /> | 
					
						
							|  |  |  |             </Modal> | 
					
						
							| 
									
										
										
										
											2025-08-22 12:34:21 +03:00
										 |  |  |         </div> | 
					
						
							| 
									
										
										
										
											2025-10-14 18:42:20 +03:00
										 |  |  |     ); | 
					
						
							| 
									
										
										
										
											2025-08-22 12:34:21 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-21 21:01:57 +03:00
										 |  |  | function findTypeTitle(type?: NoteType, mime?: string | null) { | 
					
						
							| 
									
										
										
										
											2025-08-21 20:38:19 +03:00
										 |  |  |     if (type === "code") { | 
					
						
							|  |  |  |         const mimeTypes = mime_types.getMimeTypes(); | 
					
						
							|  |  |  |         const found = mimeTypes.find((mt) => mt.mime === mime); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return found ? found.title : mime; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         const noteType = NOTE_TYPES.find((nt) => nt.type === type); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return noteType ? noteType.title : type; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-09-14 10:16:52 +03:00
										 |  |  | } |