Initial commit of MyWorkspace - contains multiple projects and global workspace configuration
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
// Conflict Resolution Utilities
|
||||
// Handles bookmark conflict resolution strategies
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const ConflictResolver = {
|
||||
|
||||
// Sync mode configurations
|
||||
MODES: {
|
||||
'bi-directional': {
|
||||
name: 'bi-directional',
|
||||
description: 'Bi-directional Sync',
|
||||
keepBoth: true,
|
||||
prioritizeLinkding: false,
|
||||
prioritizeBrowser: false
|
||||
},
|
||||
'write-only': {
|
||||
name: 'write-only',
|
||||
description: 'Write-Only (Browser Authoritative)',
|
||||
keepBoth: false,
|
||||
prioritizeLinkding: false,
|
||||
prioritizeBrowser: true
|
||||
},
|
||||
'read-only': {
|
||||
name: 'read-only',
|
||||
description: 'Read-Only (Linkding Authoritative)',
|
||||
keepBoth: false,
|
||||
prioritizeLinkding: true,
|
||||
prioritizeBrowser: false
|
||||
}
|
||||
},
|
||||
|
||||
// Get mode config
|
||||
getModeConfig(mode) {
|
||||
return this.MODES[mode] || this.MODES['bi-directional'];
|
||||
},
|
||||
|
||||
// Resolve conflict when same URL exists in different locations
|
||||
resolve(browserBookmark, linkdingBookmark, browserNotes, linkdingNotes, mode, action) {
|
||||
const config = this.getModeConfig(mode);
|
||||
const timestamp = Date.now();
|
||||
|
||||
switch (action) {
|
||||
case 'create':
|
||||
// New bookmark in browser
|
||||
return {
|
||||
action: 'create',
|
||||
result: {
|
||||
...linkdingBookmark,
|
||||
notes: this.formatNotes(browserNotes),
|
||||
title: browserBookmark.title,
|
||||
description: browserBookmark.description
|
||||
},
|
||||
note: `Created new bookmark: ${browserBookmark.url}`,
|
||||
timestamp: timestamp
|
||||
};
|
||||
|
||||
case 'update':
|
||||
// Update existing bookmark
|
||||
if (config.keepBoth) {
|
||||
// Bi-directional: keep Linkding data, merge browser notes
|
||||
return {
|
||||
action: 'update',
|
||||
result: {
|
||||
...linkdingBookmark,
|
||||
notes: this.mergeNotes(linkdingNotes, browserNotes),
|
||||
title: browserBookmark.title || linkdingBookmark.title,
|
||||
description: browserBookmark.description || linkdingBookmark.description
|
||||
},
|
||||
note: `Updated existing bookmark. Kept Linkding data.`,
|
||||
timestamp: timestamp
|
||||
};
|
||||
}
|
||||
|
||||
// Write-only or read-only: use browser data
|
||||
return {
|
||||
action: 'update',
|
||||
result: {
|
||||
...linkdingBookmark,
|
||||
notes: this.formatNotes(browserNotes),
|
||||
title: browserBookmark.title,
|
||||
description: browserBookmark.description
|
||||
},
|
||||
note: `Updated from browser`,
|
||||
timestamp: timestamp
|
||||
};
|
||||
|
||||
case 'delete':
|
||||
// Bookmark deleted
|
||||
if (config.prioritizeBrowser) {
|
||||
return {
|
||||
action: 'delete',
|
||||
result: linkdingBookmark,
|
||||
note: `Deleted from Linkding (browser is authoritative)`,
|
||||
timestamp: timestamp
|
||||
};
|
||||
}
|
||||
|
||||
if (config.prioritizeLinkding) {
|
||||
return {
|
||||
action: 'ignore',
|
||||
result: linkdingBookmark,
|
||||
note: `Kept Linkding version (read-only mode)`,
|
||||
timestamp: timestamp
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
action: 'delete',
|
||||
result: linkdingBookmark,
|
||||
note: `Deleted from Linkding`,
|
||||
timestamp: timestamp
|
||||
};
|
||||
|
||||
default:
|
||||
return {
|
||||
action: 'none',
|
||||
result: linkdingBookmark,
|
||||
note: 'No action needed',
|
||||
timestamp: timestamp
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// Format notes object for storage
|
||||
formatNotes(notes) {
|
||||
if (!notes) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return JSON.stringify({
|
||||
path: notes.path || '',
|
||||
userNotes: notes.userNotes || '',
|
||||
autoTags: notes.autoTags || []
|
||||
});
|
||||
},
|
||||
|
||||
// Merge two notes objects
|
||||
mergeNotes(notes1, notes2) {
|
||||
const p1 = this.parseNotes(notes1);
|
||||
const p2 = this.parseNotes(notes2);
|
||||
|
||||
return {
|
||||
path: p1.path || p2.path,
|
||||
userNotes: p1.userNotes || p2.userNotes,
|
||||
autoTags: [...(p1.autoTags || []), ...(p2.autoTags || [])]
|
||||
.filter((v, i, a) => a.indexOf(v) === i)
|
||||
};
|
||||
},
|
||||
|
||||
// Parse notes string
|
||||
parseNotes(noteString) {
|
||||
if (!noteString) {
|
||||
return {
|
||||
path: '',
|
||||
userNotes: '',
|
||||
autoTags: []
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(noteString);
|
||||
if (typeof parsed === 'object' && parsed !== null) {
|
||||
return {
|
||||
path: parsed.path || '',
|
||||
userNotes: parsed.userNotes || '',
|
||||
autoTags: parsed.autoTags || []
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
// Invalid JSON
|
||||
}
|
||||
|
||||
return {
|
||||
path: '',
|
||||
userNotes: noteString,
|
||||
autoTags: []
|
||||
};
|
||||
},
|
||||
|
||||
// Get conflict report
|
||||
getConflictReport(browserBookmark, linkdingBookmark) {
|
||||
const browserNotes = this.parseNotes(browserBookmark.notes || '');
|
||||
const linkdingNotes = this.parseNotes(linkdingBookmark.notes || '');
|
||||
|
||||
return {
|
||||
url: browserBookmark.url,
|
||||
browserPath: browserNotes.path,
|
||||
linkdingPath: linkdingNotes.path,
|
||||
browserNotes: browserNotes.userNotes,
|
||||
linkdingNotes: linkdingNotes.userNotes,
|
||||
differs: browserNotes.path !== linkdingNotes.path ||
|
||||
browserNotes.userNotes !== linkdingNotes.userNotes
|
||||
};
|
||||
},
|
||||
|
||||
// Check if sync is needed
|
||||
needsSync(browserBookmark, linkdingBookmark) {
|
||||
if (!linkdingBookmark) {
|
||||
return true; // New bookmark
|
||||
}
|
||||
|
||||
const browserNotes = this.parseNotes(browserBookmark.notes || '');
|
||||
const linkdingNotes = this.parseNotes(linkdingBookmark.notes || '');
|
||||
|
||||
// Check if paths differ
|
||||
if (browserNotes.path !== linkdingNotes.path) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if notes differ
|
||||
if (browserNotes.userNotes !== linkdingNotes.userNotes) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if titles differ
|
||||
if (browserBookmark.title !== linkdingBookmark.title) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Export for use in other scripts
|
||||
window.ConflictResolver = ConflictResolver;
|
||||
|
||||
})();
|
||||
Reference in New Issue
Block a user