diff --git a/src/module/authorize.jsx b/src/module/authorize.jsx index 74f974f5..54fdb084 100644 --- a/src/module/authorize.jsx +++ b/src/module/authorize.jsx @@ -287,9 +287,15 @@ export default class Auth extends React.Component { save( state, value ) { state == "pocket" && ( storage.secret.pocket.tags = value.trim() ); state == "linnk" && ( storage.secret.linnk.group_name = value.trim() ); - state == "notion_save_image" && ( storage.secret.notion.save_image = value ); - state == "notion" && ( storage.secret.notion.type = this.state.notion.filter( item => item.value == value.trim() )[0].type ); state == "youdao" && ( storage.secret.youdao.folder_id = value.trim() ); + state == "notion_save_image" && ( storage.secret.notion.save_image = value ); + if ( state == 'notion' ) { + const obj = this.state.notion.filter( item => item.value == value.trim() )[0]; + storage.secret.notion.folder_id = value.trim(); + storage.secret.notion.type = obj.type; + obj.schema && ( storage.secret.notion.schema = obj.schema ); + obj.type == "page" && delete storage.secret.notion.schema; + } storage.Safe( () => this.setState({ secret: storage.secret }), storage.secret ); } diff --git a/src/service/export.js b/src/service/export.js index 2cf80171..34614b3f 100644 --- a/src/service/export.js +++ b/src/service/export.js @@ -1248,6 +1248,17 @@ class Notion { return "https://www.notion.so/"; } + hasWriteRule(role){ + return role === 'read_and_write' || role === 'editor' + } + + getBlockName(titleArray){ + if (!titleArray) return 'Undefined' + if (Array.isArray(titleArray)) + return titleArray.map((t) => t[0]).join('') + return 'Undefined' + } + UUID() { var __extends=void 0&&(void 0).__extends||function(){var _extendStatics=function extendStatics(d,b){_extendStatics=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(d,b){d.__proto__=b}||function(d,b){for(var p in b)if(b.hasOwnProperty(p))d[p]=b[p]};return _extendStatics(d,b)};return function(d,b){_extendStatics(d,b);function __(){this.constructor=d}d.prototype=b===null?Object.create(b):(__.prototype=b.prototype,new __())}}();var ValueUUID=function(){function ValueUUID(_value){this._value=_value;this._value=_value}ValueUUID.prototype.asHex=function(){return this._value};return ValueUUID}();var V4UUID=function(_super){__extends(V4UUID,_super);function V4UUID(){return _super.call(this,[V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),'-',V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),'-','4',V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),'-',V4UUID._oneOf(V4UUID._timeHighBits),V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),'-',V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex(),V4UUID._randomHex()].join(''))||this}V4UUID._oneOf=function(array){return array[Math.floor(array.length*Math.random())]};V4UUID._randomHex=function(){return V4UUID._oneOf(V4UUID._chars)};V4UUID._chars=['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'];V4UUID._timeHighBits=['8','9','a','b'];return V4UUID}(ValueUUID);function generateUuid(){return new V4UUID().asHex()} return generateUuid(); @@ -1261,20 +1272,92 @@ class Notion { if ( result && status == "success" ) { this.access_token = Object.values( result.recordMap.notion_user )[0].value.id; this.blocks = []; - Object.values( result.recordMap.space ).forEach( item => { - item.value.pages.forEach( ( id, idx ) => { - const block = result.recordMap.block[id]; - idx == 0 && this.blocks.push({ name: item.value.name, value: block.value.id, type: block.value.type }); - if ( block.value.type == "page" ) { - this.blocks.push({ name: "  " + ( block.value.properties ? block.value.properties.title[0][0] : "Undefined" ), value: block.value.id, type: "page" }); - } else if ( block.value.type == "collection_view_page" ) { - Object.values( result.recordMap.collection ).forEach( collection => { - collection.value.parent_id == block.value.id && - this.blocks.push({ name: "  " + collection.value.name[0][0], value: collection.value.id, type: "collection" }); - }); - } - }); + + /** + * 读取所有空间,并创建映射。 + */ + const spaceMaps = {} + Object.values( result.recordMap.space ).forEach(({ value: spaceValue, role }) => { + if (!this.hasWriteRule(role)) return; + spaceMaps[spaceValue.id] = { + name : spaceValue.name, + value : spaceValue.id, + type : 'space', + blocks: [], + } }); + + /** + * 读取所有收藏空间,并创建映射。 + */ + const collectionMaps = {}; + Object.values( + result.recordMap.collection + ).forEach(({ value: collectionValue, role }) => { + if (!this.hasWriteRule(role)) return; + collectionMaps[ collectionValue.parent_id ] = collectionValue; + collectionMaps[ collectionValue.id ] = collectionValue; + }) + + /** + * 遍历所有当前用户能看到的空间。 + */ + const processCollection = ( id, spaceBlocks ) => { + const collection = collectionMaps[id]; + if ( !collection ) return; + + let schemaKey; + Object.keys( collection.schema ).some( key => { + const schema = collection.schema[key]; + if ( schema.type === 'url' && schema.name === 'URL' ) { + schemaKey = key; + return true; + } + return false; + }) + + const block = { + name : '  ' + this.getBlockName( collection.name ), + value : collection.id, + type : 'collection', + }; + schemaKey && ( block.schema = schemaKey ); + spaceBlocks.push( block ); + } + Object.values( result.recordMap.block ).forEach( ({ role, value: blockValue }) => { + if ( !this.hasWriteRule( role )) return; + const { + type, + space_id, + parent_id, + id, + collection_id, + } = blockValue; + + const _space = space_id ? spaceMaps[space_id] : spaceMaps[parent_id], + _spaceBlocks = _space ? _space.blocks : this.blocks; + + if (type == 'page') { + _spaceBlocks.push({ + name : '  ' + this.getBlockName( blockValue.properties.title ), + value: id, + type : 'page', + }); + } else if ( type == 'collection_view_page' ) { + processCollection( id, _spaceBlocks ); + } else if ( type == 'collection_view' ) { + processCollection( collection_id, _spaceBlocks ); + } + }); + + Object.values( spaceMaps ).forEach( space => { + const { blocks, ...spaceAttr } = space; + if ( blocks && blocks.length > 0 ) { + this.blocks.push({ name: spaceAttr.name, type: blocks[0].type, value: blocks[0].value }); + this.blocks.push( ...blocks ); + } + }); + this.type = this.blocks[0].type; this.folder_id = this.blocks[0].value; callback( result, undefined ); @@ -1572,7 +1655,151 @@ class Notion { }, } } - }), result => callback( result )); + }), result => { + if ( this.type == 'collection' ) { + /* result.done && this.CheckQueueTask(result.done.data.taskId, () => { + this.SetProperties(documentId, () => callback(result)) + }) */ + const taskId = result.done.data.taskId; + if ( result.done ) { + this.CheckQueueTask( taskId, () => { + if ( this.schema ) { + this.SetProperties( documentId, () => callback( result )); + } else { + this.GetCollectionData( collection => { + this.AddCollectionUrlSchema( collection, schemaKey => { + this.schema = schemaKey; + this.SetProperties( documentId, () => callback( result )); + }); + }); + } + }) + } + } else callback( result ); + }); + } + + GetCollectionData( callback ) { + browser.runtime.sendMessage( + msg.Add( msg.MESSAGE_ACTION.AXIOS, { + type: 'post', + url : this.url + 'api/v3/loadUserContent', + }), result => { + if (result.done) { + const { + recordMap: { collection }, + } = result.done.data, + currentCollection = collection[ this.folder_id ].value; + callback( currentCollection ); + } + } + ) + } + + AddCollectionUrlSchema( collection, callback ) { + const { schema } = collection, + schemaKeys = Object.keys( schema ), + genSchemaKey = ( len = 4 ) => { + let key = ''; + for ( ; key.length < len; ) { + key += String.fromCharCode( 33 + 94 * Math.random()); + } + return key; + }; + let schemaKey = null; + + schemaKeys.some( key => { + const schemaItem = schema[key]; + if ( schemaItem.type === 'url' && schemaItem.name === 'URL' ) { + schemaKey = key; + return true; + } + return false; + }); + + if ( schemaKey ) { + callback( schemaKey ); + return; + } + + const newSchema = { ...schema }; + let newSchemaKey = ''; + while ( !newSchemaKey && schemaKeys.indexOf(newSchemaKey) < 0 ) { + newSchemaKey = genSchemaKey(); + } + + newSchema[ newSchemaKey ] = { type: 'url', name: 'URL' }; + + browser.runtime.sendMessage( + msg.Add( msg.MESSAGE_ACTION.AXIOS, { + type: 'post', + url : this.url + 'api/v3/submitTransaction', + data: { + operations: [{ + args: { + schema: newSchema, + }, + command: 'update', + id: this.folder_id, + path: [], + table: 'collection', + }], + }, + }), result => { + if ( result.done ) { + callback( newSchemaKey ); + } + } + ) + } + + CheckQueueTask( taskId, callback ) { + if ( taskId ) { + browser.runtime.sendMessage( + msg.Add(msg.MESSAGE_ACTION.AXIOS, { + type: 'post', + url : this.url + 'api/v3/getTasks', + data: { + taskIds: [taskId], + }, + }), result => { + if ( result.done ) { + const { results } = result.done.data; + if ( results[0].state !== 'success' ) { + setTimeout( () => { + this.CheckQueueTask( taskId, callback ); + }, 1000 ); + } else callback(); + } + } + ) + } + } + + SetProperties( documentId, callback ) { + browser.runtime.sendMessage( + msg.Add( msg.MESSAGE_ACTION.AXIOS, { + type: 'post', + url : this.url + 'api/v3/submitTransaction', + data: { + operations: [{ + id: documentId, + table: 'block', + path: ['properties', this.schema], + command: 'set', + args: [[ window.location.origin, [[ 'a', window.location.href ]]]], + }], + }, + }), result => { + result.done && callback( documentId, undefined ); + } + ) + } + + Save( storage ) { + storage.Safe( () => { + // TO-DO + }, storage.secret ); } } diff --git a/src/service/output.js b/src/service/output.js index a4da3387..ca171979 100644 --- a/src/service/output.js +++ b/src/service/output.js @@ -317,7 +317,14 @@ function action( type, title, desc, content ) { notion.access_token = storage.secret.notion.access_token; notion.folder_id = storage.secret.notion.folder_id; notion.save_image = storage.secret.notion.save_image; + notion.schema = storage.secret.notion.schema; + notion.type = storage.secret.notion.type; notion.Add( title, result.replace( /.jpeg!720/ig, '.jpeg' ), ( result, error ) => { + // hack code + if ( notion.type == "collection" && notion.schema != storage.secret.notion.schema ) { + storage.secret.notion.schema = notion.schema; + notion.Save( storage ); + } exp.svcCbWrapper( result, error, notion.name, type, new Notify() ) }); }, 500 );