markdown sync问题

markdown fixConflict有问题
          原因, changeNote保存了笔记, 在nodejs端判断title, content, tags是否修改了,
若修改了才算是dirty [ok]
 markdown 莫名变成了非markdown editor 更新了其它非markdown笔记导致
          send changes 后, server端总会返回IsMarkdown为false [ok]
This commit is contained in:
life
2015-03-01 21:16:58 +08:00
parent 6453959413
commit 2b4b9b3114
6 changed files with 138 additions and 46 deletions

21
node_modules/api.js generated vendored
View File

@@ -498,11 +498,11 @@ var Api = {
Title: note.Title, Title: note.Title,
NotebookId: serverNotebookId, NotebookId: serverNotebookId,
Content: note.Content, Content: note.Content,
IsMarkdown: note.isMarkdown, IsMarkdown: note.IsMarkdown,
Tags: note.Tags, Tags: note.Tags,
IsBlog: note.IsBlog, IsBlog: note.IsBlog,
Files: note.Files, Files: note.Files,
FileDatas: note.FileDatas FileDatas: note.FileDatas,
} }
// log('add note'); // log('add note');
// log(data); // log(data);
@@ -543,6 +543,9 @@ var Api = {
updateNote: function(note, callback) { updateNote: function(note, callback) {
var me = this; var me = this;
Notebook.getServerNotebookIdByNotebookId(note.NotebookId, function(serverNotebookId) { Notebook.getServerNotebookIdByNotebookId(note.NotebookId, function(serverNotebookId) {
if(!note.Tags || note.Tags.length == 0) {
note.Tags = [''];
}
var data = { var data = {
noteId: note.ServerNoteId, noteId: note.ServerNoteId,
notebookId: serverNotebookId || "", notebookId: serverNotebookId || "",
@@ -551,7 +554,8 @@ var Api = {
isTrash: note.IsTrash, isTrash: note.IsTrash,
content: note.Content, content: note.Content,
Files: note.Files, Files: note.Files,
FileDatas: note.FileDatas FileDatas: note.FileDatas,
tags: note.Tags, // 新添加
} }
console.log('update note :'); console.log('update note :');
console.log(data); console.log(data);
@@ -573,6 +577,8 @@ var Api = {
var ret = resp.body; var ret = resp.body;
log('update note ret:'); log('update note ret:');
log(ret); log(ret);
// 没有传IsMarkdown, 后台会传过来总为false
delete ret['IsMarkdown'];
callback(ret); callback(ret);
/* /*
if(Common.isOk(ret)) { if(Common.isOk(ret)) {
@@ -630,11 +636,12 @@ var Api = {
return callback && callback(false); return callback && callback(false);
} }
var ret = resp.body; var ret = resp.body;
log('add tag ret =========='); console.log('add tag ret ==========');
log(ret); console.log(ret);
if(Common.isOk(ret)) { if(Common.isOk(ret)) {
// 以后不要再发了 // Tag.setNotDirty(title);
Tag.setNotDirty(title); // 更新, 添加usn
Tag.setNotDirtyAndUsn(title, ret.Usn);
callback && callback(ret); callback && callback(ret);
} else { } else {
callback && callback(false); callback && callback(false);

86
node_modules/note.js generated vendored
View File

@@ -44,7 +44,8 @@ var Note = {
var me = this; var me = this;
var userId = User.getCurActiveUserId(); var userId = User.getCurActiveUserId();
noteOrContent['UserId'] = userId; noteOrContent['UserId'] = userId;
console.log('updateNoteOrContent: '); console.error("updateNoteOrContent")
console.trace('updateNoteOrContent: ');
console.log(noteOrContent); console.log(noteOrContent);
var date = new Date(); var date = new Date();
noteOrContent.UpdatedTime = date; noteOrContent.UpdatedTime = date;
@@ -92,25 +93,46 @@ var Note = {
needUpdate = true; needUpdate = true;
} }
} }
if('Content' in updateFields) { if('Content' in updates) {
// 内容更新了, 因为内容是以后才从远程获取的, 获取内容后改变ContentIsDirty=false // 内容更新了, 因为内容是以后才从远程获取的, 获取内容后改变ContentIsDirty=false
noteOrContent['ContentIsDirty'] = true; noteOrContent['ContentIsDirty'] = true;
} }
if(needUpdate) { if(needUpdate) {
updates['IsDirty'] = true; var isDirty = false;
updates['LocalIsDelete'] = false; me.getNote(noteOrContent.NoteId, function(dbNote) {
updates.UpdatedTime = date; // 只有title, Content, Tags修改了才算是IsDirty
// Set an existing field's value if('Content' in updates && dbNote['Content'] != updates['Content']) {
Notes.update({NoteId: noteOrContent.NoteId}, { $set: updates }, {}, function (err, numReplaced) { isDirty = true;
if(err) { } else if('Title' in updates && dbNote['Title'] != updates['Title']) {
callback && callback(false); isDirty = true;
} else { } else if('Tags' in updates) {
callback && callback(noteOrContent); var dbTags = dbNote['Tags'] || [];
var nowTags = updates['Tags'] || [];
if('Content' in updates) { if(dbTags.join(',') != nowTags.join(',')) {
me.addNoteHistory(noteOrContent.NoteId, noteOrContent.Content); isDirty = true;
} }
} }
console.log('update note isDirty: ' + noteOrContent.NoteId);
console.error(isDirty);
updates['IsDirty'] = isDirty;
updates['LocalIsDelete'] = false;
updates.UpdatedTime = date;
// Set an existing field's value
Notes.update({NoteId: noteOrContent.NoteId}, { $set: updates }, {}, function (err, numReplaced) {
if(err) {
callback && callback(false);
} else {
callback && callback(noteOrContent);
if('Content' in updates) {
me.addNoteHistory(noteOrContent.NoteId, noteOrContent.Content);
}
}
});
}); });
} }
} }
@@ -198,7 +220,8 @@ var Note = {
searchNote: function(key, callback) { searchNote: function(key, callback) {
var reg = new RegExp(key); var reg = new RegExp(key);
Notes.find({IsTrash: false, LocalIsDelete: false, $or: [{Title: reg}, {Content: reg}]}).sort({'UpdatedTime': -1}).exec(function(err, notes) { var userId = User.getCurActiveUserId();
Notes.find({UserId: userId, IsTrash: false, LocalIsDelete: false, $or: [{Title: reg}, {Content: reg}]}).sort({'UpdatedTime': -1}).exec(function(err, notes) {
if(!err && notes) { if(!err && notes) {
console.log('search ' + key + ' result: ' + notes.length); console.log('search ' + key + ' result: ' + notes.length);
callback(notes); callback(notes);
@@ -209,7 +232,8 @@ var Note = {
}, },
searchNoteByTag: function(tag, callback) { searchNoteByTag: function(tag, callback) {
Notes.find({IsTrash: false, LocalIsDelete: false, Tags: {$in: [tag]}}).sort({'UpdatedTime': -1}).exec(function(err, notes) { var userId = User.getCurActiveUserId();
Notes.find({UserId: userId, IsTrash: false, LocalIsDelete: false, Tags: {$in: [tag]}}).sort({'UpdatedTime': -1}).exec(function(err, notes) {
if(!err && notes) { if(!err && notes) {
console.log('search by tag: ' + tag + ' result: ' + notes.length); console.log('search by tag: ' + tag + ' result: ' + notes.length);
callback(notes); callback(notes);
@@ -332,10 +356,10 @@ var Note = {
content = content.replace(reg, Server.localUrl + '/api/file/getImage'); content = content.replace(reg, Server.localUrl + '/api/file/getImage');
var reg2 = new RegExp(Evt.leanoteUrl + '/api/file/getAttach', 'g'); var reg2 = new RegExp(Evt.leanoteUrl + '/api/file/getAttach', 'g');
content = content.replace(reg, Evt.localUrl + '/api/file/getAttach'); content = content.replace(reg2, Evt.localUrl + '/api/file/getAttach');
var reg3 = new RegExp(Evt.leanoteUrl + '/api/file/getAllAttach', 'g'); var reg3 = new RegExp(Evt.leanoteUrl + '/api/file/getAllAttach', 'g');
content = content.replace(reg, Evt.localUrl + '/api/file/getAllAttach'); content = content.replace(reg3, Evt.localUrl + '/api/file/getAllAttach');
return content; return content;
}, },
@@ -345,15 +369,16 @@ var Note = {
if(!content) { if(!content) {
return content; return content;
} }
console.log(Evt.localUrl + '/api/file/getImage'); // console.log(Evt.localUrl + '/api/file/getImage');
// console.log(content);
var reg = new RegExp(Evt.localUrl + '/api/file/getImage', 'g'); var reg = new RegExp(Evt.localUrl + '/api/file/getImage', 'g');
content = content.replace(reg, Evt.leanoteUrl + '/api/file/getImage'); content = content.replace(reg, Evt.leanoteUrl + '/api/file/getImage');
var reg2 = new RegExp(Evt.localUrl + '/api/file/getAttach', 'g'); var reg2 = new RegExp(Evt.localUrl + '/api/file/getAttach', 'g');
content = content.replace(reg, Evt.leanoteUrl + '/api/file/getAttach'); content = content.replace(reg2, Evt.leanoteUrl + '/api/file/getAttach');
var reg3 = new RegExp(Evt.localUrl + '/api/file/getAllAttach', 'g'); var reg3 = new RegExp(Evt.localUrl + '/api/file/getAllAttach', 'g');
content = content.replace(reg, Evt.leanoteUrl + '/api/file/getAllAttach'); content = content.replace(reg3, Evt.leanoteUrl + '/api/file/getAllAttach');
return content; return content;
}, },
@@ -452,12 +477,17 @@ var Note = {
getNoteByServerNoteId: function(noteId, callback) { getNoteByServerNoteId: function(noteId, callback) {
var me = this; var me = this;
Notes.findOne({ServerNoteId: noteId}, function(err, doc) { Notes.find({ServerNoteId: noteId}, function(err, doc) {
// console.log(doc.length + '...'); // console.log(doc.length + '...');
if(doc.length > 1) {
console.error(doc.length + '. ..');
}
console.log('note length: ' + doc.length + '. ..');
if(err || !doc) { if(err || !doc) {
log('getNoteByServerNoteId 不存在' + noteId); log('getNoteByServerNoteId 不存在' + noteId);
callback && callback(false); callback && callback(false);
} else { } else {
doc = doc[0];
callback && callback(doc); callback && callback(doc);
} }
}); });
@@ -617,6 +647,8 @@ var Note = {
console.log("updateNoteForce 后的") console.log("updateNoteForce 后的")
console.log(note); console.log(note);
console.log(note.ServerNoteId + " " + note.IsDirty);
console.log('ever note'); console.log('ever note');
console.log(everNote.NoteId); console.log(everNote.NoteId);
console.log(everNote); console.log(everNote);
@@ -632,6 +664,11 @@ var Note = {
console.log('强制更新...'); console.log('强制更新...');
callback && callback(note); callback && callback(note);
me.getNoteByServerNoteId(note.ServerNoteId, function(t) {
console.log('强制更新后的...');
console.log(t);
});
// 下载内容, 图片, 附件 // 下载内容, 图片, 附件
me.syncContentAndImagesAndAttachs(note); me.syncContentAndImagesAndAttachs(note);
} }
@@ -750,7 +787,7 @@ var Note = {
// 新Id // 新Id
delete note['_id']; delete note['_id'];
delete note['ServerNoteId']; delete note['ServerNoteId'];
note.NoteId = Common.objectId(); note.NoteId = Common.objectId(); // 新生成一个NoteId
note.ConflictNoteId = noteId; // 与noteId有冲突 note.ConflictNoteId = noteId; // 与noteId有冲突
note.ConflictTime = new Date(); // 发生冲突时间 note.ConflictTime = new Date(); // 发生冲突时间
note.ConflictFixed = false; // 冲突未解决 note.ConflictFixed = false; // 冲突未解决
@@ -794,7 +831,7 @@ var Note = {
}, function() { }, function() {
note.Attachs = newAttachs; note.Attachs = newAttachs;
console.log('conflict 复制后的'); console.log('conflict 复制后的');
console.log(note.Attachs); console.log(note);
Notes.insert(note, function(err, newNote) { Notes.insert(note, function(err, newNote) {
if(err) { if(err) {
callback(false); callback(false);
@@ -888,6 +925,7 @@ var Note = {
async.eachSeries(conflictNotes, function(note, cb) { // note是服务器上最新的, note.NoteId, ServerNoteId已转换 async.eachSeries(conflictNotes, function(note, cb) { // note是服务器上最新的, note.NoteId, ServerNoteId已转换
var noteId = note.NoteId; // 本地noteId var noteId = note.NoteId; // 本地noteId
// 复制一份, 本地的复制一份, 然后服务器上的替换本地的 // 复制一份, 本地的复制一份, 然后服务器上的替换本地的
// newNote其实是现有的复制一份得到的
me.copyNoteForConfict(noteId, function(newNote) { me.copyNoteForConfict(noteId, function(newNote) {
if(newNote) { if(newNote) {
// 更新之前的 // 更新之前的

11
node_modules/sync.js generated vendored
View File

@@ -278,7 +278,7 @@ var Sync = {
Note.getNoteByServerNoteId(noteId, function(noteLocal) { Note.getNoteByServerNoteId(noteId, function(noteLocal) {
// 2.1 本地没有, 表示是新建 // 2.1 本地没有, 表示是新建
if(!noteLocal) { if(!noteLocal) {
log('add: ...') console.log('add: ...');
Note.addNoteForce(note, function(note) { Note.addNoteForce(note, function(note) {
me._syncInfo.note.adds.push(note); me._syncInfo.note.adds.push(note);
return canCall(); return canCall();
@@ -287,7 +287,10 @@ var Sync = {
// 2.2 本地是否修改了, 冲突, 报告给前端, 前端处理 // 2.2 本地是否修改了, 冲突, 报告给前端, 前端处理
// 冲突, 将本地修改的笔记复制一份(设置冲突字段, ConflictNoteId), 远程的覆盖本地的 // 冲突, 将本地修改的笔记复制一份(设置冲突字段, ConflictNoteId), 远程的覆盖本地的
if(noteLocal.IsDirty) { if(noteLocal.IsDirty) {
log('note 冲突....') console.log('note 冲突.... serverNoteId: ' + noteId);
console.log(noteLocal.NoteId);
console.log(noteLocal.IsDirty);
console.log(noteLocal);
note.ServerNoteId = note.NoteId; note.ServerNoteId = note.NoteId;
note.NoteId = noteLocal.NoteId; note.NoteId = noteLocal.NoteId;
me._syncInfo.note.conflicts.push(note); me._syncInfo.note.conflicts.push(note);
@@ -823,6 +826,7 @@ var Sync = {
return cb(); return cb();
} }
me._syncInfo.note.changeAdds.push(newTag); me._syncInfo.note.changeAdds.push(newTag);
// Tag.updateTagForce(newTag);
me.checkNeedIncSyncAgain(newTag.Usn); me.checkNeedIncSyncAgain(newTag.Usn);
cb(); cb();
}); });
@@ -831,6 +835,9 @@ var Sync = {
Api.deleteTag(tag, function(ret) { Api.deleteTag(tag, function(ret) {
if(Common.isOk(ret)) { if(Common.isOk(ret)) {
me.checkNeedIncSyncAgain(ret.Usn); me.checkNeedIncSyncAgain(ret.Usn);
} else {
// 有问题, 可能本地不存在
Tag.setNotDirty(tag);
} }
return cb(); return cb();
}); });

10
node_modules/tag.js generated vendored
View File

@@ -97,6 +97,16 @@ var Tag = {
}); });
}, },
// 添加tag后的返回, 更新usn
updateTagForce: function(tag, callback) {
var me = this;
tag.IsDirty = false;
var userId = User.getCurActiveUserId();
Tags.update({UserId: userId, Tag: tag.Tag}, {$set: tag}, function() {
callback && callback();
});
},
// 服务器上更新过来, 已经存在了 // 服务器上更新过来, 已经存在了
setNotDirty: function(title) { setNotDirty: function(title) {
var me = this; var me = this;

View File

@@ -39,7 +39,7 @@ Note.intervalTime = 600000; // 600s, 10mins
Note.startInterval = function() { Note.startInterval = function() {
Note.interval = setInterval(function() { Note.interval = setInterval(function() {
log("自动保存开始..."); log("自动保存开始...");
changedNote = Note.curChangedSaveIt(false); // changedNote = Note.curChangedSaveIt(false);
}, Note.intervalTime); // 600s, 10mins }, Note.intervalTime); // 600s, 10mins
} }
// 停止, 当切换note时 // 停止, 当切换note时
@@ -177,6 +177,15 @@ Note.curNoteIsDirtied = function() {
} }
}; };
// 保存后不dirty
Note.curNoteIsNotDirtied = function() {
var me = this;
var note = me.getCurNote();
if(note) {
note.isDirty = false;
}
};
// called by Notebook // called by Notebook
// render 所有notes, 和第一个note的content // render 所有notes, 和第一个note的content
Note.renderNotesAndFirstOneContent = function(ret) { Note.renderNotesAndFirstOneContent = function(ret) {
@@ -237,17 +246,18 @@ Note.curHasChanged = function(force) {
IsMarkdown: cacheNote.IsMarkdown, // 是否是markdown笔记 IsMarkdown: cacheNote.IsMarkdown, // 是否是markdown笔记
FromUserId: cacheNote.FromUserId, // 是否是共享新建的 FromUserId: cacheNote.FromUserId, // 是否是共享新建的
NoteId: cacheNote.NoteId, NoteId: cacheNote.NoteId,
NotebookId: cacheNote.NotebookId, NotebookId: cacheNote.NotebookId
Version: cacheNote.Version || 0, // 版本控制
}; };
if(hasChanged.IsNew) { if(hasChanged.IsNew) {
$.extend(hasChanged, cacheNote); $.extend(hasChanged, cacheNote);
} else { } else {
if(!cacheNote.isDirty) { if(!cacheNote.isDirty) { // 不是dirty
log("no dirty"); console.log("no dirty");
hasChanged.hasChanged = false; hasChanged.hasChanged = false;
return hasChanged; return hasChanged;
} else {
console.log("is dirty");
} }
} }
@@ -287,7 +297,7 @@ Note.curHasChanged = function(force) {
hasChanged["UserId"] = cacheNote["UserId"] || ""; hasChanged["UserId"] = cacheNote["UserId"] || "";
return hasChanged; return hasChanged;
} };
// 由content生成desc // 由content生成desc
// 换行不要替换 // 换行不要替换
@@ -435,6 +445,8 @@ Note.curChangedSaveIt = function(force, callback) {
me.saveInProcess[hasChanged.NoteId] = true; me.saveInProcess[hasChanged.NoteId] = true;
console.error('保存当前的笔记: ' + hasChanged.NoteId);
NoteService.updateNoteOrContent(hasChanged, function(ret) { NoteService.updateNoteOrContent(hasChanged, function(ret) {
me.saveInProcess[hasChanged.NoteId] = false; me.saveInProcess[hasChanged.NoteId] = false;
if(hasChanged.IsNew) { if(hasChanged.IsNew) {
@@ -442,6 +454,9 @@ Note.curChangedSaveIt = function(force, callback) {
ret.IsNew = false; ret.IsNew = false;
Note.setNoteCache(ret, false); Note.setNoteCache(ret, false);
// 设置不为dirty
Note.curNoteIsNotDirtied(hasChanged.NoteId);
// 新建笔记也要change history // 新建笔记也要change history
Pjax.changeNote(ret); Pjax.changeNote(ret);
} }
@@ -2372,7 +2387,9 @@ Note.fixSyncConflict = function(note, newNote) {
// 如果当前笔记在笔记列表中, 那么生成一个新笔记放在这个笔记上面 // 如果当前笔记在笔记列表中, 那么生成一个新笔记放在这个笔记上面
if(target.length > 0) { if(target.length > 0) {
var newHtmlObject = Note._getNoteHtmlObjct(note); var newHtmlObject = Note._getNoteHtmlObjct(note);
newHtmlObject.insertBefore(target); if(newHtmlObject) {
newHtmlObject.insertBefore(target);
}
} }
// 当前这个换成新复制的 // 当前这个换成新复制的
target.attr('noteId', newNote.NoteId); target.attr('noteId', newNote.NoteId);

25
test.js
View File

@@ -5,6 +5,7 @@ var Note = require('note');
var Api = require('api'); var Api = require('api');
var User = require('user'); var User = require('user');
var Server = require('server'); var Server = require('server');
var Evt = require('evt');
/* /*
Notebook.addNotebook("1", "life"); Notebook.addNotebook("1", "life");
@@ -19,10 +20,14 @@ Api.addNotebook({
// Api.uploadImage(); // Api.uploadImage();
User.userId = '54bdc65599c37b0da9000002'; User.userId = '54bdc65599c37b0da9000002';
User.userId = '54d7620d99c37b030600002c'; User.userId = '54d7620d99c37b030600002c';
User.userId = '54d7620d99c37b030600002c'; User.userId = '54f08a1699c37b877b0001ee';
// 54d7624205fcd105da00005 // 54d7624205fcd105da00005
// var reg = new RegExp(Evt.localUrl + '/api/file/getImage', 'g');
// content = content.replace(reg, Evt.leanoteUrl + '/api/file/getImage');
User.init(function() { User.init(function() {
/* /*
@@ -31,15 +36,15 @@ User.init(function() {
}); });
*/ */
Note.getNoteByServerNoteId('54d7624205fcd105da000005', function(note) {
Note.getNoteByServerNoteId('54f1a1f899c37b4faf000001', function(note) {
console.log(note); console.log(note);
}); });
/*
Note.getDirtyNotes(function(ret) { Note.getDirtyNotes(function(ret) {
// console.log(ret); console.log('getDirtyNotes: ');
console.log(ret);
}); });
*/
}); });
@@ -93,11 +98,19 @@ while((result = reg.exec(content)) != null) {
console.log("??"); console.log("??");
*/ */
/*
var a = '<img src="http://127.0.0.1:8008/api/file/getImage?fileId=34232323234iji3"'; var a = '<img src="http://127.0.0.1:8008/api/file/getImage?fileId=34232323234iji3"';
// var reg = /fileId=(.+?)"/g; // var reg = /fileId=(.+?)"/g;
var reg = new RegExp("http://127.0.0.1:8008/api/file/getImage\\?fileId=(.{10})", 'g'); var reg = new RegExp("http://127.0.0.1:8008/api/file/getImage\\?fileId=(.{10})", 'g');
a = a.replace(reg, 'xx');
console.log(a);
*/
/*
console.log(reg); console.log(reg);
while(s = reg.exec(a)) { while(s = reg.exec(a)) {
console.log(s); console.log(s);
} }
*/