Skip to content

Commit

Permalink
work on #291, migrate group id from int value to UUID
Browse files Browse the repository at this point in the history
  • Loading branch information
drive4ik committed Jul 25, 2024
1 parent bd17853 commit 122bce3
Show file tree
Hide file tree
Showing 18 changed files with 375 additions and 290 deletions.
11 changes: 6 additions & 5 deletions addon/src/components/edit-group.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
this.DEFAULT_COOKIE_STORE_ID = Constants.DEFAULT_COOKIE_STORE_ID;
this.GROUP_ICON_VIEW_TYPES = Constants.GROUP_ICON_VIEW_TYPES;
this.TITLE_VARIABLES = {
index: '{index}',
uid: '{uid}',
...Utils.DATE_LOCALE_VARIABLES,
};
Expand Down Expand Up @@ -265,13 +265,13 @@
this.group.title = title.slice(0, selectionStart) + value + title.slice(selectionEnd, title.length);
},
triggerChanges() {
async triggerChanges() {
const changes = {};
for(const [key, value] of Object.entries(this.group)) {
for (const [key, value] of Object.entries(this.group)) {
const defaultValue = this.groupToCompare[key];
if (value !== Object(value)) { // is primitive
if (Utils.isPrimitive(value)) {
if (value !== defaultValue) {
changes[key] = value;
}
Expand All @@ -284,7 +284,8 @@
if (changes.hasOwnProperty('title')) {
const groupId = this.isDefaultGroup ? null : this.group.id;
changes.title = Groups.createTitle(changes.title, groupId);
const {defaultGroupProps} = await Groups.getDefaults();
changes.title = Groups.createTitle(changes.title, groupId, defaultGroupProps, !this.isDefaultGroup);
}
changes.catchTabRules
Expand Down
2 changes: 1 addition & 1 deletion addon/src/help/open-in-container.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ async function init() {
anotherCookieStoreId = urlParams.get('anotherCookieStoreId'),
destCookieStoreId = urlParams.get('destCookieStoreId'),
conflictedExtId = urlParams.get('conflictedExtId'),
groupId = Number(urlParams.get('groupId')),
groupId = urlParams.get('groupId'),
asInfo = urlParams.get('asInfo'),
conflictedExt = await loadConflictedExt(conflictedExtId),
group = await loadGroup(groupId),
Expand Down
7 changes: 3 additions & 4 deletions addon/src/js/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,6 @@ export const SYNC_STORAGE_LOCAL = 'local';
export const DEFAULT_OPTIONS = Object.freeze({
version: MANIFEST.version,
groups: [],
lastCreatedGroupPosition: 0, // TODO remove

// options

Expand Down Expand Up @@ -349,11 +348,11 @@ export const DEFAULT_OPTIONS = Object.freeze({
{
value: `${IS_MAC ? 'Mac' : ''}Ctrl+Backquote`,
action: 'load-next-group',
groupId: 0,
groupId: null,
}, {
value: `${IS_MAC ? 'Mac' : ''}Ctrl+Shift+Backquote`,
action: 'load-prev-group',
groupId: 0,
groupId: null,
},
],
});
Expand All @@ -362,7 +361,7 @@ const DEFAULT_OPTION_KEYS = Object.keys(DEFAULT_OPTIONS);

export const ONLY_BOOL_OPTION_KEYS = Object.freeze(DEFAULT_OPTION_KEYS.filter(key => 'boolean' === typeof DEFAULT_OPTIONS[key]));

export const NON_OPTION_KEYS = Object.freeze(['version', 'groups', 'lastCreatedGroupPosition']);
export const NON_OPTION_KEYS = Object.freeze(['version', 'groups']);

export const ALL_OPTION_KEYS = Object.freeze(DEFAULT_OPTION_KEYS.filter(key => !NON_OPTION_KEYS.includes(key)));

Expand Down
59 changes: 29 additions & 30 deletions addon/src/js/groups.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ export async function save(groups, withMessage = false) {
return groups;
}

export function createId() {
return self.crypto.randomUUID();
}

// extract "uid" from "group.id" that matches UUID
export function extractUId(groupId) {
return groupId?.slice(0, 4);
}

export function create(id, title, defaultGroupProps = {}) {
const group = {
id,
Expand Down Expand Up @@ -114,7 +123,7 @@ export function create(id, title, defaultGroupProps = {}) {
if (id) { // create title for group
group.title = createTitle(title, id, defaultGroupProps);
} else { // create title for default group, if needed
group.title ??= createTitle(title, id, defaultGroupProps);
group.title ??= createTitle(title, null, defaultGroupProps);
}

group.iconColor ??= Utils.randomColor();
Expand Down Expand Up @@ -169,25 +178,20 @@ export async function add(windowId, tabIds = [], title = null) {
}
}

let [
{lastCreatedGroupPosition},
const [
{groups},
{defaultGroupProps},
] = await Promise.all([
Storage.get('lastCreatedGroupPosition'),
load(),
getDefaults(),
]);

lastCreatedGroupPosition++;

const {groups} = await load(),
newGroup = create(lastCreatedGroupPosition, title, defaultGroupProps);
const newGroup = create(createId(), title, defaultGroupProps);

groups.push(newGroup);

await save(groups);

await Storage.set({lastCreatedGroupPosition});

if (windowId) {
await Cache.setWindowGroup(windowId, newGroup.id);
await backgroundSelf.updateBrowserActionData(newGroup.id);
Expand Down Expand Up @@ -290,7 +294,7 @@ export async function update(groupId, updateData) {
const log = logger.start('update', {groupId, updateData});

if (updateData.iconUrl?.startsWith('chrome:')) {
Utils.notify('Icon not supported');
// Utils.notify('Icon not supported');
delete updateData.iconUrl;
}

Expand All @@ -308,8 +312,9 @@ export async function update(groupId, updateData) {

// updateData = JSON.clone(updateData); // clone need for fix bug: dead object after close tab which create object

if (updateData.title) {
updateData.title = updateData.title.slice(0, 256);
if (updateData.hasOwnProperty('title')) {
const {defaultGroupProps} = await getDefaults();
updateData.title = createTitle(updateData.title, groupId, defaultGroupProps).slice(0, 256);
}

Object.assign(group, updateData);
Expand Down Expand Up @@ -555,18 +560,6 @@ export function setNewTabsParams(tabs, group) {
return tabs.map(tab => Object.assign(tab, newTabParams));
}

export async function getNextTitle() {
const [
{lastCreatedGroupPosition},
{defaultGroupProps},
] = await Promise.all([
Storage.get('lastCreatedGroupPosition'),
getDefaults(),
]);

return createTitle(null, lastCreatedGroupPosition + 1, defaultGroupProps);
}

function isCatchedUrl(url, catchTabRules) {
return catchTabRules
.split(/\s*\n\s*/)
Expand Down Expand Up @@ -770,16 +763,22 @@ export function getIconUrl(group, keyInObj = null) {
return result;
}

export function createTitle(title = null, groupId = null, defaultGroupProps = {}) {
export function createTitle(title = null, groupId = null, defaultGroupProps = {}, format = true) {
const uid = extractUId(groupId) || '{uid}';

if (title) {
return String(title);
title = String(title);
} else if (defaultGroupProps.title) {
title = defaultGroupProps.title;
} else {
title = browser.i18n.getMessage('newGroupTitle', uid);
}

if (defaultGroupProps.title && groupId) {
return Utils.format(defaultGroupProps.title, {index: groupId}, Utils.DATE_LOCALE_VARIABLES);
if (format) {
return Utils.format(title, {uid}, Utils.DATE_LOCALE_VARIABLES);
}

return browser.i18n.getMessage('newGroupTitle', groupId || '{index}');
return title;
}

export function getTitle({id, title, isArchive, isSticky, tabs, iconViewType, newTabContainer}, args = '') {
Expand Down
2 changes: 1 addition & 1 deletion addon/src/js/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export function sendExternalMessage(exId, ...args) {

self.logger?.info('sending', `SEND-EXTERNAL-MESSAGE#${message.action}`, 'to:', exId);

browser.runtime.sendMessage(exId, message).catch(() => {});
return browser.runtime.sendMessage(exId, message).catch(() => {});
}

export function connectToBackground(name, listeners = null, callback = null) {
Expand Down
18 changes: 3 additions & 15 deletions addon/src/js/sync/cloud/cloud.js
Original file line number Diff line number Diff line change
Expand Up @@ -297,20 +297,8 @@ async function syncGroups(localData, cloudData, sourceOfTruth, changes) {
// const localTabsToRemove = new Set;

cloudGroups.forEach(cloudGroup => {
let localGroup;

// if first sync - add cloud group as new. This will duplicate groups, sorry ¯\_(ツ)_/¯
// it is impossible otherwise, because the id of the group on one computer
// and the same id on another computer do not mean the same groups
if (localData.syncId === Constants.DEFAULT_OPTIONS.syncId) {
// nevertheless, we are trying to find a group with the same name and the same id,
// this will happen when restoring groups from a backup on different computers with data cleansing
// (then the id of the groups are saved)
localGroup = localGroups.find(localGroup => localGroup.id === cloudGroup.id && localGroup.title === cloudGroup.title);
} else {
// find local group
localGroup = localGroups.find(localGroup => localGroup.id === cloudGroup.id);
}
// find local group
let localGroup = localGroups.find(localGroup => localGroup.id === cloudGroup.id);

if (localGroup?.dontUploadToCloud) {
resultLocalGroups.push(localGroup); // leave group in local
Expand All @@ -323,7 +311,7 @@ async function syncGroups(localData, cloudData, sourceOfTruth, changes) {
changes.local = true;

log.log('create/clone new local group from cloud:', cloudGroup.id);
// TODO work with group id => to timestamp

localGroup = JSON.clone(cloudGroup);

if (!localGroup.isArchive) {
Expand Down
4 changes: 2 additions & 2 deletions addon/src/js/urls.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ export async function openManageGroups() {
await Windows.setFocus(win.id);
} else {
await Windows.createPopup(MANAGE_TABS_URL, {
width: Number(window.localStorage.manageGroupsWindowWidth) || 1000,
height: Number(window.localStorage.manageGroupsWindowHeight) || 700,
width: +window.localStorage.manageGroupsWindowWidth || 1000,
height: +window.localStorage.manageGroupsWindowHeight || 700,
});
}
}
Expand Down
11 changes: 4 additions & 7 deletions addon/src/manage/Manage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -593,9 +593,8 @@
tabIds = this.getTabIdsForMove(tabId);
if (this.options.alwaysAskNewGroupName) {
newGroupTitle = await Groups.getNextTitle();
newGroupTitle = await this.showPrompt(this.lang('createNewGroup'), newGroupTitle);
const {defaultGroupProps} = await Groups.getDefaults();
newGroupTitle = await this.showPrompt(this.lang('createNewGroup'), Groups.createTitle(null, null, defaultGroupProps));
if (!newGroupTitle) {
return;
Expand Down Expand Up @@ -671,10 +670,8 @@
return new Vue({
data: group,
watch: {
title: function(title) {
Messages.sendMessageModule('Groups.update', this.id, {
title: Groups.createTitle(title, this.id),
});
title(title) {
Messages.sendMessageModule('Groups.update', this.id, {title});
},
},
computed: {
Expand Down
2 changes: 1 addition & 1 deletion addon/src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

"name": "__MSG_extensionName__",
"description": "__MSG_extensionDescription__",
"version": "5.2",
"version": "5.5",
"author": "Drive4ik",
"homepage_url": "https://github.com/drive4ik/simple-tab-groups",

Expand Down
18 changes: 9 additions & 9 deletions addon/src/options/Options.vue
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@
return;
}
if ('object' !== Utils.type(data) || !Array.isArray(data.groups) || !Number.isSafeInteger(data.lastCreatedGroupPosition)) {
if ('object' !== Utils.type(data) || 'object' !== Utils.type(data.defaultGroupProps) || !Array.isArray(data.groups) || !data.version) {
Utils.notify('This is wrong backup!');
return;
}
Expand Down Expand Up @@ -406,7 +406,7 @@
Object.values(oldGroups).forEach(function({id, title, catchRules}) {
groups[id] = {
title: Groups.createTitle(title, id),
title,
tabs: [],
catchTabRules: catchRules || '',
};
Expand Down Expand Up @@ -479,9 +479,9 @@
panoramaOptions.windows.forEach(function(win) {
let groups = {};
win.groups.forEach(function({id, name}) {
win.groups.forEach(function({id, name: title}) {
groups[id] = {
title: Groups.createTitle(name, id),
title,
tabs: [],
};
});
Expand Down Expand Up @@ -515,7 +515,7 @@
if (groupTabs.length) {
data.groups.push({
title: Groups.createTitle(title, groupTabs.length),
title,
tabs: groupTabs,
});
}
Expand Down Expand Up @@ -574,7 +574,7 @@
.filter(Boolean);
data.groups.push({
title: Groups.createTitle(title, id),
title,
tabs: tabs.filter(tab => !tab.pinned),
});
Expand All @@ -594,7 +594,7 @@
return {
value: '',
action: '',
groupId: 0,
groupId: null,
};
},
Expand Down Expand Up @@ -865,8 +865,8 @@
<div v-if="HOTKEY_ACTIONS_WITH_CUSTOM_GROUP.includes(hotkey.action)" class="is-flex is-align-items-center custom-group">
<div :class="['control', {'has-icons-left': hotkey.groupId}]">
<div class="select">
<select v-model.number="hotkey.groupId">
<option :value="0" v-text="lang('selectGroup')"></option>
<select v-model="hotkey.groupId">
<option :value="null" v-text="lang('selectGroup')"></option>
<option v-if="hotkey.groupId && !groupIds.includes(hotkey.groupId)" disabled :value="hotkey.groupId" v-text="lang('unknownGroup')"></option>
<option v-for="group in groups" :key="group.id" :value="group.id" v-text="getGroupTitle(group)"></option>
</select>
Expand Down
4 changes: 0 additions & 4 deletions addon/src/options/manage-addon-backup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,6 @@
result.containers = this.data.containers;
}
if (this.data.lastCreatedGroupPosition) {
result.lastCreatedGroupPosition = this.data.lastCreatedGroupPosition;
}
if (this.readyPinnedTabs) {
result.pinnedTabs = this.data.pinnedTabs;
}
Expand Down
11 changes: 4 additions & 7 deletions addon/src/popup/Popup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -762,20 +762,17 @@
},
async createNewGroup(tabIds, proposalTitle, applyGroupWithTabId) {
let newGroupTitle = '';
if (this.options.alwaysAskNewGroupName) {
newGroupTitle = await Groups.getNextTitle();
newGroupTitle = await this.showPrompt(this.lang('createNewGroup'), proposalTitle || newGroupTitle);
const {defaultGroupProps} = await Groups.getDefaults();
proposalTitle = await this.showPrompt(this.lang('createNewGroup'), Groups.createTitle(proposalTitle, null, defaultGroupProps));
if (!newGroupTitle) {
if (!proposalTitle) {
return false;
}
}
let newGroupWindowId = Cache.getWindowGroup(this.currentWindow.id) ? undefined : this.currentWindow.id,
newGroup = await Groups.add(newGroupWindowId, tabIds, newGroupTitle);
newGroup = await Groups.add(newGroupWindowId, tabIds, proposalTitle);
if (applyGroupWithTabId) {
this.applyGroup(newGroup, {id: applyGroupWithTabId});
Expand Down
Loading

0 comments on commit 122bce3

Please sign in to comment.