2019-08-26 20:21:43 +02:00
import ws from './ws.js' ;
2018-03-25 11:09:17 -04:00
import utils from './utils.js' ;
import server from './server.js' ;
2021-04-16 23:01:56 +02:00
import froca from './froca.js' ;
2018-12-12 20:39:56 +01:00
import hoistedNoteService from '../services/hoisted_note.js' ;
2020-01-12 11:15:23 +01:00
import appContext from "./app_context.js" ;
2020-01-12 09:12:13 +01:00
2019-05-11 21:27:27 +02:00
/ * *
2019-10-20 13:09:00 +02:00
* @ return { string | null }
2019-05-11 21:27:27 +02:00
* /
2021-03-03 21:49:57 +01:00
async function resolveNotePath ( notePath , hoistedNoteId = 'root' ) {
const runPath = await resolveNotePathToSegments ( notePath , hoistedNoteId ) ;
2019-05-11 21:27:27 +02:00
2019-05-14 22:29:47 +02:00
return runPath ? runPath . join ( "/" ) : null ;
2019-05-11 21:27:27 +02:00
}
2018-03-25 11:09:17 -04:00
/ * *
2020-08-24 23:33:27 +02:00
* Accepts notePath which might or might not be valid and returns an existing path as close to the original
* notePath as possible . Part of the path might not be valid because of note moving ( which causes
2018-03-25 11:09:17 -04:00
* path change ) or other corruption , in that case this will try to get some other valid path to the correct note .
2019-10-20 13:09:00 +02:00
*
* @ return { string [ ] }
2018-03-25 11:09:17 -04:00
* /
2021-03-03 21:49:57 +01:00
async function resolveNotePathToSegments ( notePath , hoistedNoteId = 'root' , logErrors = true ) {
2018-03-25 11:09:17 -04:00
utils . assertArguments ( notePath ) ;
2017-12-23 11:02:38 -05:00
2021-05-22 12:26:45 +02:00
// we might get notePath with the ntxId suffix, remove it if present
2019-07-28 14:08:05 +02:00
notePath = notePath . split ( "-" ) [ 0 ] . trim ( ) ;
if ( notePath . length === 0 ) {
return ;
}
2019-07-09 22:12:05 +02:00
2018-03-25 11:09:17 -04:00
const path = notePath . split ( "/" ) . reverse ( ) ;
2018-05-26 16:16:34 -04:00
if ( ! path . includes ( "root" ) ) {
path . push ( 'root' ) ;
}
2017-11-19 08:47:22 -05:00
2021-03-09 20:37:56 +01:00
const effectivePathSegments = [ ] ;
2018-03-25 11:09:17 -04:00
let childNoteId = null ;
let i = 0 ;
2017-11-19 18:16:50 -05:00
2018-03-25 11:09:17 -04:00
while ( true ) {
if ( i >= path . length ) {
break ;
}
2017-11-30 00:02:32 -05:00
2018-03-25 11:09:17 -04:00
const parentNoteId = path [ i ++ ] ;
2017-11-19 11:28:46 -05:00
2018-03-25 11:09:17 -04:00
if ( childNoteId !== null ) {
2021-05-11 22:00:16 +02:00
const child = await froca . getNote ( childNoteId , ! logErrors ) ;
2018-11-12 23:34:22 +01:00
if ( ! child ) {
2021-05-11 22:00:16 +02:00
if ( logErrors ) {
ws . logError ( ` Can't find note ${ childNoteId } ` ) ;
}
2019-05-14 22:29:47 +02:00
return ;
2018-11-12 23:34:22 +01:00
}
2021-02-24 22:38:26 +01:00
child . resortParents ( ) ;
2020-03-18 22:35:54 +01:00
const parents = child . getParentNotes ( ) ;
2017-11-19 11:28:46 -05:00
2020-08-24 23:33:27 +02:00
if ( ! parents . length ) {
if ( logErrors ) {
2020-10-19 22:10:25 +02:00
ws . logError ( ` No parents found for ${ childNoteId } ( ${ child . title } ) for path ${ notePath } ` ) ;
2020-08-24 23:33:27 +02:00
}
2018-03-25 11:09:17 -04:00
return ;
}
2017-11-26 21:00:42 -05:00
2018-03-25 11:09:17 -04:00
if ( ! parents . some ( p => p . noteId === parentNoteId ) ) {
2020-06-10 23:43:59 +02:00
if ( logErrors ) {
2021-04-16 22:57:37 +02:00
const parent = froca . getNoteFromCache ( parentNoteId ) ;
2020-10-12 21:05:34 +02:00
2021-05-09 22:00:21 +02:00
console . debug ( utils . now ( ) , ` Did not find parent ${ parentNoteId } ( ${ parent ? parent . title : 'n/a' } ) for child ${ childNoteId } ( ${ child . title } ), available parents: ${ parents . map ( p => ` ${ p . noteId } ( ${ p . title } ) ` ) } . You can ignore this message as it is mostly harmless. ` ) ;
2020-06-10 23:43:59 +02:00
}
2017-11-19 11:28:46 -05:00
2021-03-06 20:23:29 +01:00
const someNotePath = getSomeNotePath ( child , hoistedNoteId ) ;
2017-11-19 18:16:50 -05:00
2020-08-24 23:33:27 +02:00
if ( someNotePath ) { // in case it's root the path may be empty
2021-03-06 20:23:29 +01:00
const pathToRoot = someNotePath . split ( "/" ) . reverse ( ) . slice ( 1 ) ;
2018-05-27 12:26:34 -04:00
2020-08-24 23:33:27 +02:00
for ( const noteId of pathToRoot ) {
2021-03-09 20:37:56 +01:00
effectivePathSegments . push ( noteId ) ;
2017-11-19 11:28:46 -05:00
}
2018-03-25 11:09:17 -04:00
}
2020-06-10 23:43:59 +02:00
2020-08-24 23:33:27 +02:00
break ;
2017-11-19 08:47:22 -05:00
}
}
2017-12-03 17:46:56 -05:00
2021-03-09 20:37:56 +01:00
effectivePathSegments . push ( parentNoteId ) ;
2018-12-12 20:39:56 +01:00
childNoteId = parentNoteId ;
2017-11-19 08:47:22 -05:00
}
2021-03-09 20:37:56 +01:00
effectivePathSegments . reverse ( ) ;
if ( effectivePathSegments . includes ( hoistedNoteId ) ) {
return effectivePathSegments ;
}
else {
2021-04-16 22:57:37 +02:00
const note = await froca . getNote ( getNoteIdFromNotePath ( notePath ) ) ;
2021-03-09 20:37:56 +01:00
const someNotePathSegments = getSomeNotePathSegments ( note , hoistedNoteId ) ;
2021-10-29 21:37:12 +02:00
if ( ! someNotePathSegments ) {
throw new Error ( ` Did not find any path segments for ${ note . toString ( ) } , hoisted note ${ hoistedNoteId } ` ) ;
}
2021-03-09 20:37:56 +01:00
// if there isn't actually any note path with hoisted note then return the original resolved note path
return someNotePathSegments . includes ( hoistedNoteId ) ? someNotePathSegments : effectivePathSegments ;
}
2018-03-25 11:09:17 -04:00
}
2017-12-23 11:02:38 -05:00
2021-03-06 20:23:29 +01:00
function getSomeNotePathSegments ( note , hoistedNotePath = 'root' ) {
2018-03-25 11:09:17 -04:00
utils . assertArguments ( note ) ;
2017-11-21 20:04:06 -05:00
2021-03-08 00:04:43 +01:00
const notePaths = note . getSortedNotePaths ( hoistedNotePath ) ;
2017-11-21 20:04:06 -05:00
2021-05-08 23:31:20 +02:00
return notePaths . length > 0 ? notePaths [ 0 ] . notePath : null ;
2021-03-06 20:23:29 +01:00
}
2017-11-21 20:04:06 -05:00
2021-03-06 20:23:29 +01:00
function getSomeNotePath ( note , hoistedNotePath = 'root' ) {
const notePath = getSomeNotePathSegments ( note , hoistedNotePath ) ;
2020-01-03 10:48:36 +01:00
2021-05-08 23:31:20 +02:00
return notePath === null ? null : notePath . join ( '/' ) ;
2018-03-25 11:09:17 -04:00
}
2017-11-04 19:28:49 -04:00
2018-03-25 11:09:17 -04:00
async function sortAlphabetically ( noteId ) {
2020-08-24 23:33:27 +02:00
await server . put ( ` notes/ ${ noteId } /sort ` ) ;
2018-03-25 11:09:17 -04:00
}
2017-12-18 23:41:13 -05:00
2019-08-26 20:21:43 +02:00
ws . subscribeToMessages ( message => {
2021-04-24 11:39:44 +02:00
if ( message . type === 'openNote' ) {
2020-02-07 21:08:55 +01:00
appContext . tabManager . activateOrOpenNote ( message . noteId ) ;
2019-06-23 13:25:00 +02:00
if ( utils . isElectron ( ) ) {
2021-11-16 22:43:08 +01:00
const currentWindow = utils . dynamicRequire ( '@electron/remote' ) . getCurrentWindow ( ) ;
2019-06-23 13:25:00 +02:00
currentWindow . show ( ) ;
}
}
2018-08-01 09:26:02 +02:00
} ) ;
2020-02-10 20:57:56 +01:00
function getParentProtectedStatus ( node ) {
2021-03-06 20:23:29 +01:00
return hoistedNoteService . isHoistedNode ( node ) ? 0 : node . getParent ( ) . data . isProtected ;
2020-01-25 09:56:08 +01:00
}
function getNoteIdFromNotePath ( notePath ) {
if ( ! notePath ) {
return null ;
}
const path = notePath . split ( "/" ) ;
const lastSegment = path [ path . length - 1 ] ;
2021-05-22 12:26:45 +02:00
// path could have also ntxId suffix
2020-01-25 09:56:08 +01:00
return lastSegment . split ( "-" ) [ 0 ] ;
}
2020-09-13 21:12:22 +02:00
async function getBranchIdFromNotePath ( notePath ) {
const { noteId , parentNoteId } = getNoteIdAndParentIdFromNotePath ( notePath ) ;
2021-04-16 22:57:37 +02:00
return await froca . getBranchId ( parentNoteId , noteId ) ;
2020-09-13 21:12:22 +02:00
}
2020-01-25 09:56:08 +01:00
function getNoteIdAndParentIdFromNotePath ( notePath ) {
2020-05-17 21:07:54 +02:00
if ( notePath === 'root' ) {
return {
noteId : 'root' ,
parentNoteId : 'none'
} ;
}
2020-01-25 09:56:08 +01:00
let parentNoteId = 'root' ;
let noteId = '' ;
if ( notePath ) {
const path = notePath . split ( "/" ) ;
const lastSegment = path [ path . length - 1 ] ;
2021-05-22 12:26:45 +02:00
// path could have also ntxId suffix
2020-01-25 09:56:08 +01:00
noteId = lastSegment . split ( "-" ) [ 0 ] ;
if ( path . length > 1 ) {
parentNoteId = path [ path . length - 2 ] ;
}
}
return {
parentNoteId ,
noteId
2020-09-13 21:12:22 +02:00
} ;
2020-01-25 09:56:08 +01:00
}
2020-02-10 20:57:56 +01:00
function getNotePath ( node ) {
2020-01-25 09:56:08 +01:00
if ( ! node ) {
2020-10-12 21:05:34 +02:00
logError ( "Node is null" ) ;
2020-01-25 09:56:08 +01:00
return "" ;
}
const path = [ ] ;
2021-03-06 20:23:29 +01:00
while ( node ) {
2020-01-25 09:56:08 +01:00
if ( node . data . noteId ) {
path . push ( node . data . noteId ) ;
}
node = node . getParent ( ) ;
}
return path . reverse ( ) . join ( "/" ) ;
}
async function getNoteTitle ( noteId , parentNoteId = null ) {
utils . assertArguments ( noteId ) ;
2021-04-16 22:57:37 +02:00
const note = await froca . getNote ( noteId ) ;
2020-01-25 09:56:08 +01:00
if ( ! note ) {
return "[not found]" ;
}
let { title } = note ;
if ( parentNoteId !== null ) {
const branchId = note . parentToBranch [ parentNoteId ] ;
if ( branchId ) {
2021-04-16 22:57:37 +02:00
const branch = froca . getBranch ( branchId ) ;
2020-01-25 09:56:08 +01:00
if ( branch && branch . prefix ) {
2020-08-24 23:33:27 +02:00
title = ` ${ branch . prefix } - ${ title } ` ;
2020-01-25 09:56:08 +01:00
}
}
}
return title ;
}
2021-01-21 21:48:06 +01:00
async function getNotePathTitleComponents ( notePath ) {
const titleComponents = [ ] ;
2020-01-25 09:56:08 +01:00
if ( notePath . startsWith ( 'root/' ) ) {
notePath = notePath . substr ( 5 ) ;
}
// special case when we want just root's title
if ( notePath === 'root' ) {
2021-01-21 21:48:06 +01:00
titleComponents . push ( await getNoteTitle ( notePath ) ) ;
} else {
let parentNoteId = 'root' ;
for ( const noteId of notePath . split ( '/' ) ) {
titleComponents . push ( await getNoteTitle ( noteId , parentNoteId ) ) ;
parentNoteId = noteId ;
}
2020-01-25 09:56:08 +01:00
}
2021-01-21 21:48:06 +01:00
return titleComponents ;
}
2020-01-25 09:56:08 +01:00
2021-01-21 21:48:06 +01:00
async function getNotePathTitle ( notePath ) {
utils . assertArguments ( notePath ) ;
2020-01-25 09:56:08 +01:00
2021-01-21 21:48:06 +01:00
const titlePath = await getNotePathTitleComponents ( notePath ) ;
2020-01-25 09:56:08 +01:00
return titlePath . join ( ' / ' ) ;
}
2021-01-21 21:48:06 +01:00
async function getNoteTitleWithPathAsSuffix ( notePath ) {
utils . assertArguments ( notePath ) ;
const titleComponents = await getNotePathTitleComponents ( notePath ) ;
if ( ! titleComponents || titleComponents . length === 0 ) {
return "" ;
}
const title = titleComponents [ titleComponents . length - 1 ] ;
const path = titleComponents . slice ( 0 , titleComponents . length - 1 ) ;
const $titleWithPath = $ ( '<span class="note-title-with-path">' )
. append ( $ ( '<span class="note-title">' ) . text ( title ) ) ;
if ( path . length > 0 ) {
$titleWithPath
. append ( $ ( '<span class="note-path">' ) . text ( ' (' + path . join ( ' / ' ) + ')' ) ) ;
}
return $titleWithPath ;
}
2020-02-09 21:13:05 +01:00
function getHashValueFromAddress ( ) {
const str = document . location . hash ? document . location . hash . substr ( 1 ) : "" ; // strip initial #
return str . split ( "-" ) ;
}
2020-04-07 22:53:03 +02:00
function parseNotePath ( notePath ) {
let noteIds = notePath . split ( '/' ) ;
if ( noteIds [ 0 ] !== 'root' ) {
noteIds = [ 'root' ] . concat ( noteIds ) ;
}
return noteIds ;
}
2018-03-25 11:09:17 -04:00
export default {
2018-03-26 22:29:14 -04:00
sortAlphabetically ,
2019-05-19 18:21:29 +02:00
resolveNotePath ,
2020-08-24 23:33:27 +02:00
resolveNotePathToSegments ,
2019-06-16 11:12:07 +02:00
getSomeNotePath ,
2021-03-06 20:23:29 +01:00
getSomeNotePathSegments ,
2020-01-25 09:56:08 +01:00
getParentProtectedStatus ,
getNotePath ,
getNoteIdFromNotePath ,
getNoteIdAndParentIdFromNotePath ,
2020-09-13 21:12:22 +02:00
getBranchIdFromNotePath ,
2020-01-25 09:56:08 +01:00
getNoteTitle ,
2020-02-09 21:13:05 +01:00
getNotePathTitle ,
2021-01-21 21:48:06 +01:00
getNoteTitleWithPathAsSuffix ,
2020-04-07 22:53:03 +02:00
getHashValueFromAddress ,
parseNotePath
2020-05-09 14:25:27 +02:00
} ;