diff --git a/apps/mobile/src/screens/settings/editor/configuretoolbar.tsx b/apps/mobile/src/screens/settings/editor/configuretoolbar.tsx index e3c5ae2e0..44a4a851e 100644 --- a/apps/mobile/src/screens/settings/editor/configuretoolbar.tsx +++ b/apps/mobile/src/screens/settings/editor/configuretoolbar.tsx @@ -17,7 +17,12 @@ export const ConfigureToolbar = () => { const renderGroups = () => { return data.map((item, index) => - index === 0 ? : + index === 0 ? ( + //@ts-ignore + + ) : ( + + ) ); }; diff --git a/apps/mobile/src/screens/settings/editor/state.ts b/apps/mobile/src/screens/settings/editor/state.ts index f71e4b690..b4d0a81aa 100644 --- a/apps/mobile/src/screens/settings/editor/state.ts +++ b/apps/mobile/src/screens/settings/editor/state.ts @@ -1,6 +1,9 @@ import { ToolbarGroupDefinition } from 'notesnook-editor/dist/toolbar/types'; import create, { State } from 'zustand'; import { persist } from 'zustand/middleware'; +import { useNoteStore } from '../../../stores/use-notes-store'; +import { useSettingStore } from '../../../stores/use-setting-store'; +import { db } from '../../../utils/database'; import { MMKV } from '../../../utils/database/mmkv'; import { presets } from './toolbar-definition'; export type ToolDefinition = string | string[]; @@ -27,6 +30,7 @@ export interface DragState extends State { setData: (data: ToolbarGroupDefinition[]) => void; preset: 'default' | 'minimal' | 'custom'; setPreset: (preset: 'default' | 'minimal' | 'custom') => void; + init: () => Promise; } export const useDragState = create( @@ -40,22 +44,57 @@ export const useDragState = create( data: presets['default'], customPresetData: presets['custom'], setData: data => { - //@ts-ignore presets['custom'] = data; - console.log(presets['custom']); + db.settings?.setToolbarConfig(useSettingStore.getState().deviceMode || 'mobile', { + preset: 'custom', + config: data + }); set({ data: data, preset: 'custom', customPresetData: data }); }, setPreset: preset => { + db.settings?.setToolbarConfig(useSettingStore.getState().deviceMode || 'mobile', { + preset, + config: preset === 'custom' ? get().customPresetData : [] + }); set({ preset, data: preset === 'custom' ? get().customPresetData : presets[preset] }); + }, + init: async () => { + const user = await db.user?.getUser(); + if (!user) return; + const toolbarConfig = db.settings?.getToolbarConfig( + useSettingStore.getState().deviceMode || 'mobile' + ); + if (!toolbarConfig) { + logger.info('DragState', 'No user defined toolbar config was found'); + return; + } + const preset = toolbarConfig?.preset as DragState['preset']; + logger.info('DragState', 'Init user toolbar config', preset, toolbarConfig?.config); + set({ + //@ts-ignore + preset: preset, + data: preset === 'custom' ? toolbarConfig?.config : presets[preset], + customPresetData: preset === 'custom' ? toolbarConfig?.config : presets['custom'] + }); } }), { name: 'drag-state-storage', // unique name //@ts-ignore getStorage: () => MMKV, - onRehydrateStorage: state => { + onRehydrateStorage: () => { return state => { - console.log(state, 'rehydrated drag state'); + logger.info('DragState', 'rehydrated drag state'); + if (!useNoteStore.getState().loading) { + state?.init(); + } else { + const unsub = useNoteStore.subscribe(_state => { + if (!_state.loading) { + state?.init(); + unsub(); + } + }); + } }; } // (optional) by default, 'localStorage' is used } diff --git a/apps/mobile/src/screens/settings/editor/toolbardefinition.ts b/apps/mobile/src/screens/settings/editor/toolbardefinition.ts index 655f48412..2fa3c8ae1 100644 --- a/apps/mobile/src/screens/settings/editor/toolbardefinition.ts +++ b/apps/mobile/src/screens/settings/editor/toolbardefinition.ts @@ -1,60 +1,14 @@ import { Icons } from 'notesnook-editor/dist/toolbar/icons'; -import { useThemeStore } from '../../../stores/use-theme-store'; -import { ToolbarGroupDefinition, ToolDefinition } from 'notesnook-editor/dist/toolbar/types'; +import { DEFAULT_TOOLS, getAllTools } from 'notesnook-editor/dist/toolbar/tooldefinitions'; import { ToolId } from 'notesnook-editor/dist/toolbar/tools'; +import { ToolbarGroupDefinition } from 'notesnook-editor/dist/toolbar/types'; +import { useThemeStore } from '../../../stores/use-theme-store'; +export const tools = getAllTools(); export const presets: { [name: string]: ToolbarGroupDefinition[] } = { - default: [ - [ - 'insertBlock', - 'tableSettings', - 'imageSettings', - 'embedSettings', - 'attachmentSettings', - 'linkSettings', - 'codeRemove' - ], - [ - 'bold', - 'italic', - 'underline', - ['strikethrough', 'code', 'subscript', 'superscript', 'highlight', 'textColor'] - ], - ['fontSize'], - ['headings', 'fontFamily'], - ['numberedList', 'bulletList'], - ['addLink'], - ['alignCenter', ['alignLeft', 'alignRight', 'alignJustify', 'ltr', 'rtl']], - ['clearformatting'] - ], - minimal: [ - [ - 'insertBlock', - 'tableSettings', - 'imageSettings', - 'embedSettings', - 'attachmentSettings', - 'linkSettings', - 'codeRemove' - ], - [ - 'bold', - 'italic', - 'underline', - ['strikethrough', 'subscript', 'superscript', 'highlight', 'textColor'] - ] - ], - custom: [ - [ - 'insertBlock', - 'tableSettings', - 'imageSettings', - 'embedSettings', - 'attachmentSettings', - 'linkSettings', - 'codeRemove' - ] - ] + default: DEFAULT_TOOLS, + minimal: [...DEFAULT_TOOLS.slice(0, 2)], + custom: [DEFAULT_TOOLS.slice(0)] }; export function findToolById(id: keyof typeof tools): { title: string; icon: string } { @@ -85,525 +39,3 @@ export function getUngroupedTools(toolDefinition: (string | string[])[][]): stri console.log(ungrouped); return ungrouped; } - -export const tools: Record = { - bold: { - icon: 'bold', - title: 'Bold' - }, - italic: { - icon: 'italic', - title: 'Italic' - }, - underline: { - icon: 'underline', - title: 'Underline' - }, - strikethrough: { - icon: 'strikethrough', - title: 'Strikethrough' - }, - addLink: { - icon: 'link', - title: 'Link' - }, - editLink: { - icon: 'linkEdit', - title: 'Edit link', - conditional: true - }, - removeLink: { - icon: 'linkRemove', - title: 'Remove link', - conditional: true - }, - openLink: { - icon: 'openLink', - title: 'Open link', - conditional: true - }, - linkSettings: { - icon: 'linkSettings', - title: 'Link settings', - conditional: true - }, - code: { - icon: 'code', - title: 'Code' - }, - codeRemove: { - icon: 'codeRemove', - title: 'Code', - conditional: true - }, - clearformatting: { - icon: 'formatClear', - title: 'Clear all formatting' - }, - subscript: { - icon: 'subscript', - title: 'Subscript' - }, - superscript: { - icon: 'superscript', - title: 'Superscript' - }, - insertBlock: { - icon: 'plus', - title: 'Insert' - }, - bulletList: { - icon: 'bulletList', - title: 'Bullet list' - }, - numberedList: { - icon: 'numberedList', - title: 'Numbered list' - }, - fontFamily: { - icon: 'none', - title: 'Font family' - }, - fontSize: { - icon: 'none', - title: 'Font size' - }, - headings: { - icon: 'none', - title: 'Headings' - }, - alignCenter: { - icon: 'alignCenter', - title: 'Align center' - }, - alignLeft: { - icon: 'alignLeft', - title: 'Align left' - }, - alignRight: { - icon: 'alignRight', - title: 'Align right' - }, - alignJustify: { - icon: 'alignJustify', - title: 'Justify' - }, - ltr: { - icon: 'ltr', - title: 'Left to right' - }, - rtl: { - icon: 'rtl', - title: 'Right to left' - }, - highlight: { - icon: 'highlight', - title: 'Highlight' - }, - textColor: { - icon: 'textColor', - title: 'Text color' - }, - - tableSettings: { - icon: 'tableSettings', - title: 'Table settings', - conditional: true - }, - columnProperties: { - icon: 'columnProperties', - title: 'Column properties', - conditional: true - }, - rowProperties: { - icon: 'rowProperties', - title: 'Row properties', - conditional: true - }, - cellProperties: { - icon: 'cellProperties', - title: 'Cell properties', - conditional: true - }, - insertColumnLeft: { - icon: 'insertColumnLeft', - title: 'Insert column left', - conditional: true - }, - insertColumnRight: { - icon: 'insertColumnRight', - title: 'Insert column right', - conditional: true - }, - moveColumnLeft: { - icon: 'moveColumnLeft', - title: 'Move column left', - conditional: true - }, - moveColumnRight: { - icon: 'moveColumnRight', - title: 'Move column right', - conditional: true - }, - deleteColumn: { - icon: 'deleteColumn', - title: 'Delete column', - conditional: true - }, - splitCells: { - icon: 'splitCells', - title: 'Split cells', - conditional: true - }, - mergeCells: { - icon: 'mergeCells', - title: 'Merge cells', - conditional: true - }, - insertRowAbove: { - icon: 'insertRowAbove', - title: 'Insert row above', - conditional: true - }, - insertRowBelow: { - icon: 'insertRowBelow', - title: 'Insert row below', - conditional: true - }, - moveRowUp: { - icon: 'moveRowUp', - title: 'Move row up', - conditional: true - }, - moveRowDown: { - icon: 'moveRowDown', - title: 'Move row down', - conditional: true - }, - deleteRow: { - icon: 'deleteRow', - title: 'Delete row', - conditional: true - }, - deleteTable: { - icon: 'deleteTable', - title: 'Delete table', - conditional: true - }, - cellBackgroundColor: { - icon: 'backgroundColor', - title: 'Cell background color', - conditional: true - }, - cellBorderColor: { - icon: 'cellBorderColor', - title: 'Cell border color', - conditional: true - }, - cellTextColor: { - icon: 'textColor', - title: 'Cell text color', - conditional: true - }, - cellBorderWidth: { - icon: 'none', - title: 'Cell border width', - conditional: true - }, - - imageSettings: { - icon: 'imageSettings', - title: 'Image settings', - conditional: true - }, - imageAlignCenter: { - icon: 'alignCenter', - title: 'Align center', - conditional: true - }, - imageAlignLeft: { - icon: 'alignLeft', - title: 'Align left', - conditional: true - }, - imageAlignRight: { - icon: 'alignRight', - title: 'Align right', - conditional: true - }, - imageProperties: { - icon: 'more', - title: 'Image properties', - conditional: true - }, - attachmentSettings: { - icon: 'attachmentSettings', - title: 'Attachment settings', - conditional: true - }, - downloadAttachment: { - icon: 'download', - title: 'Download attachment', - conditional: true - }, - removeAttachment: { - icon: 'delete', - title: 'Remove attachment', - conditional: true - }, - embedSettings: { - icon: 'embedSettings', - title: 'Embed settings', - conditional: true - }, - embedAlignCenter: { - icon: 'alignCenter', - title: 'Align center', - conditional: true - }, - embedAlignLeft: { - icon: 'alignLeft', - title: 'Align left', - conditional: true - }, - embedAlignRight: { - icon: 'alignRight', - title: 'Align right', - conditional: true - }, - embedProperties: { - icon: 'more', - title: 'Embed properties', - conditional: true - } -}; -export const toolbarDefinition = presets['default']; - -export type FlattenedToolbarItemType = { - id: string; - type: 'group' | 'tool' | 'subgroup'; - icon?: string; - title: string; - count?: number; - groupId?: string; -}; - -export const getFlattenedToolbarDefinition = ( - toolbar: (string | string[])[][] -): FlattenedToolbarItemType[] => { - const flattenedToolbar: FlattenedToolbarItemType[] = []; - for (let group = 0; group < toolbar.length; group++) { - const groupId = `group-${group + 1}`; - flattenedToolbar.push({ - id: groupId, - type: 'group', - title: `Group ${group + 1}` - }); - for (let i = 0; i < toolbar[group].length; i++) { - let tool = toolbar[group][i]; - if (typeof tool !== 'string') { - let subGroupId = `subgroup-${i + 1}-group`; - flattenedToolbar.push({ - id: subGroupId, - type: 'subgroup', - title: `SubGroup ${group + 1}`, - count: tool.length, - groupId: groupId - }); - for (let it = 0; it < tool.length; it++) { - const toolId = tool[it] as keyof typeof tools; - flattenedToolbar.push({ - type: 'tool', - id: toolId, - groupId: subGroupId, - ...findToolById(toolId) - }); - } - } else { - const toolId = tool as keyof typeof tools; - flattenedToolbar.push({ - type: 'tool', - id: toolId, - groupId: groupId, - ...findToolById(toolId) - }); - } - } - } - return flattenedToolbar; -}; - -export function getGroupIndexes(data: FlattenedToolbarItemType[]) { - return data - .map((item, index) => { - if (item.type === 'group') return index; - return -1; - }) - .filter(item => item !== -1); -} - -export function moveGroup( - data: FlattenedToolbarItemType[], - _data: FlattenedToolbarItemType[], - to: number, - from: number, - prevDraggedItem: FlattenedToolbarItemType, - nextDraggedItem: FlattenedToolbarItemType -) { - const groupIndexes = getGroupIndexes(data); - const nextGroupIndex = groupIndexes.findIndex(index => index === from) + 1; - const prevGroupIndex = groupIndexes.findIndex(index => index === from) - 1; - if ( - (to > groupIndexes[prevGroupIndex] && to < from) || - (to < groupIndexes[nextGroupIndex] && to > from) || - to === from - ) { - console.log('invalid location'); - return data; - } - - const groupItems = data.slice(from + 1, groupIndexes[nextGroupIndex]); - let { after, before } = getGroupBoundary(groupIndexes, to, from); - console.log('group after drop index', after, 'group before drop index', before); - let indexOfMovedGroup = _data.findIndex(item => item.id === prevDraggedItem.id); - _data.splice(indexOfMovedGroup, 1); - if (to < from) { - // move up - _data.splice(after === groupIndexes[0] ? after : before, 0, prevDraggedItem, ...groupItems); - _data.splice(from + (groupItems.length + 1), groupItems.length); - } else { - // move down - if (before === groupIndexes[groupIndexes.length - 1]) { - if (after === before) before = _data.length - 1; - _data.splice(before + 1, 0, prevDraggedItem, ...groupItems); - _data.splice(from, groupItems.length); - } else { - _data.splice(before - 1, 0, prevDraggedItem, ...groupItems); - _data.splice(from === 0 ? from : from - 1, groupItems.length); - } - } - return _data; -} - -export function getGroupBoundary(indexes: number[], to: number, from: number) { - let after = 0; - let before = 0; - for (let i = 0; i < indexes.length; i++) { - before = indexes[i]; - if (to >= after && to <= before) { - if (before === to) { - after = before; - before = indexes[i + 1]; - } - - if (after === to && before === from) { - before = after; - } - break; - } else { - after = before; - } - } - return { after, before }; -} - -export const getToolbarDefinition = ( - flattenedToolbar: FlattenedToolbarItemType[] -): (string | string[])[][] => { - const groupIndexes = flattenedToolbar - .map((item, index) => { - if (item.type === 'group') return index; - return -1; - }) - .filter(item => item !== -1); - const toolbarDefinition = []; - - for (let i = 0; i < groupIndexes.length; i++) { - let groupIndex = groupIndexes[i]; - let nextGroupIndex = - i + 1 === groupIndexes.length ? flattenedToolbar.length : groupIndexes[i + 1]; - - let groupDefinition = []; - for (let i = groupIndex + 1; i < nextGroupIndex; i++) { - let tool = flattenedToolbar[i]; - switch (tool.type) { - case 'tool': - if (!tool.groupId?.includes('subgroup')) { - groupDefinition.push(tool.id); - } - break; - case 'subgroup': - // eslint-disable-next-line no-case-declarations - let subgroupDefinition = []; - for (let index = i + 1; index < nextGroupIndex; index++) { - let subgroupTool = flattenedToolbar[index]; - if (subgroupTool.groupId !== tool.id) continue; - subgroupDefinition.push(subgroupTool.id); - } - groupDefinition.push(subgroupDefinition); - break; - } - } - - toolbarDefinition.push(groupDefinition); - } - return toolbarDefinition; -}; - -export const moveSubGroup = ( - data: FlattenedToolbarItemType[], - _data: FlattenedToolbarItemType[], - to: number, - from: number, - prevDraggedItem: FlattenedToolbarItemType, - nextDraggedItem: FlattenedToolbarItemType -) => { - const groupIndexes = getGroupIndexes(data); - let { after, before } = getGroupBoundary(groupIndexes, to, from); - console.log(after, before, 'value'); - if ((from > after && from < before && to !== after && to !== before) || to === from || to === 0) { - console.log('invalid move'); - return _data; - } - const groupItems = data.slice(from + 1, getGroupBoundary(groupIndexes, from, to).before); - - let indexOfMovedGroup = _data.findIndex(item => item.id === prevDraggedItem.id); - _data.splice(indexOfMovedGroup, 1); - - if (to < from) { - // move up - _data.splice(after === to ? after : before, 0, prevDraggedItem, ...groupItems); - _data.splice(from + (groupItems.length + 1), groupItems.length); - } else { - // move down - _data.splice(before - 1, 0, prevDraggedItem, ...groupItems); - _data.splice(from, groupItems.length); - } - - console.log(groupItems.map(i => i.id)); - - return _data; -}; - -export const moveTool = ( - data: FlattenedToolbarItemType[], - _data: FlattenedToolbarItemType[], - to: number, - from: number, - prevDraggedItem: FlattenedToolbarItemType, - nextDraggedItem: FlattenedToolbarItemType -) => { - const itemAboveDrop = _data[to - 1]; - const isSubGroupOrItem = - itemAboveDrop.id.startsWith('subgroup') || itemAboveDrop.groupId?.startsWith('subgroup'); - console.log(itemAboveDrop.id); - if (isSubGroupOrItem) { - console.log('dropped in subgroup', itemAboveDrop.type); - _data[to].groupId = - itemAboveDrop.type === 'subgroup' ? itemAboveDrop.id : itemAboveDrop.groupId; - } else { - _data[to].groupId = itemAboveDrop.type === 'group' ? itemAboveDrop.id : itemAboveDrop.groupId; - } - - return _data; -}; diff --git a/apps/mobile/src/screens/settings/settingsdata.tsx b/apps/mobile/src/screens/settings/settingsdata.tsx index 50a29bcf1..0dce97212 100644 --- a/apps/mobile/src/screens/settings/settingsdata.tsx +++ b/apps/mobile/src/screens/settings/settingsdata.tsx @@ -758,7 +758,7 @@ export const settingsGroups: SettingSection[] = [ id: 'join-telegram', name: 'Join our Telegram group', description: "We are on telegram, let's talk", - icon: 'telegram', + // icon: 'telegram', modifer: () => { Linking.openURL('https://t.me/notesnook').catch(console.log); } diff --git a/apps/mobile/src/utils/hooks/useAppEvents.js b/apps/mobile/src/utils/hooks/useAppEvents.js index ea05c746e..151cba351 100644 --- a/apps/mobile/src/utils/hooks/useAppEvents.js +++ b/apps/mobile/src/utils/hooks/useAppEvents.js @@ -40,6 +40,7 @@ import { ToastEvent } from '../../services/event-manager'; import { useEditorStore } from '../../stores/use-editor-store'; +import { useDragState } from '../../screens/settings/editor/state'; const SodiumEventEmitter = new NativeEventEmitter(NativeModules.Sodium); export const useAppEvents = () => { @@ -251,6 +252,7 @@ export const useAppEvents = () => { user = await db.user.getUser(); await PremiumService.setPremiumStatus(); setLastSynced(await db.lastSynced()); + await useDragState.getState().init(); if (!user) { return setLoginMessage(); }