506 lines
18 KiB
JavaScript
506 lines
18 KiB
JavaScript
/*
|
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
'use strict';
|
|
|
|
import {
|
|
log as internalLogger,
|
|
configs,
|
|
saveUserStyleRules,
|
|
notify,
|
|
wait,
|
|
isLinux,
|
|
isMacOS,
|
|
} from '/common/common.js';
|
|
import * as Constants from '/common/constants.js';
|
|
import * as Permissions from '/common/permissions.js';
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
function log(...args) {
|
|
internalLogger('background/migration', ...args);
|
|
}
|
|
|
|
const kCONFIGS_VERSION = 33;
|
|
const kFEATURES_VERSION = 9;
|
|
|
|
export function migrateConfigs() {
|
|
switch (configs.configsVersion) {
|
|
case 0:
|
|
case 1:
|
|
if (configs.startDragTimeout !== null)
|
|
configs.longPressDuration = configs.startDragTimeout;
|
|
if (configs.emulateDefaultContextMenu !== null)
|
|
configs.emulateDefaultContextMenu = configs.emulateDefaultContextMenu;
|
|
|
|
case 2:
|
|
if (configs.simulateSelectOwnerOnClose !== null &&
|
|
!configs.simulateSelectOwnerOnClose)
|
|
configs.successorTabControlLevel = Constants.kSUCCESSOR_TAB_CONTROL_NEVER;
|
|
|
|
case 3:
|
|
if (!(configs.tabDragBehavior & Constants.kDRAG_BEHAVIOR_ALLOW_BOOKMARK))
|
|
configs.tabDragBehavior |= Constants.kDRAG_BEHAVIOR_TEAR_OFF;
|
|
if (!(configs.tabDragBehaviorShift & Constants.kDRAG_BEHAVIOR_ALLOW_BOOKMARK))
|
|
configs.tabDragBehaviorShift |= Constants.kDRAG_BEHAVIOR_TEAR_OFF;
|
|
|
|
case 4:
|
|
if (configs.fakeContextMenu !== null)
|
|
configs.emulateDefaultContextMenu = configs.fakeContextMenu;
|
|
if (configs.context_closeTabOptions_closeTree !== null)
|
|
configs.context_topLevel_closeTree = configs.context_closeTabOptions_closeTree;
|
|
if (configs.context_closeTabOptions_closeDescendants !== null)
|
|
configs.context_topLevel_closeDescendants = configs.context_closeTabOptions_closeDescendants;
|
|
if (configs.context_closeTabOptions_closeOthers !== null)
|
|
configs.context_topLevel_closeOthers = configs.context_closeTabOptions_closeOthers;
|
|
|
|
case 5:
|
|
if (configs.scrollbarMode !== null) {
|
|
switch (configs.scrollbarMode < 0 ? (isMacOS() ? 3 : 1) : configs.scrollbarMode) {
|
|
case 0: // default, refular width
|
|
configs.userStyleRules += `
|
|
|
|
/* regular width scrollbar */
|
|
#tabbar { scrollbar-width: auto; }`;
|
|
break;
|
|
case 1: // narrow width
|
|
break;
|
|
case 2: // hide
|
|
configs.userStyleRules += `
|
|
|
|
/* hide scrollbar */
|
|
#tabbar { scrollbar-width: none; }
|
|
|
|
/* cancel spaces for macOS overlay scrollbar */
|
|
:root.platform-mac #tabbar:dir(rtl).overflow .tab:not(.pinned) {
|
|
padding-inline-start: 0;
|
|
}
|
|
:root.platform-mac #tabbar:dir(ltr).overflow .tab:not(.pinned) {
|
|
padding-inline-end: 0;
|
|
}`;
|
|
break;
|
|
case 3: // overlay (macOS)
|
|
break;
|
|
}
|
|
}
|
|
if (configs.sidebarScrollbarPosition !== null) {
|
|
switch (configs.sidebarScrollbarPosition) {
|
|
default:
|
|
case 0: // auto
|
|
case 1: // left
|
|
break;
|
|
break;
|
|
case 2: // right
|
|
configs.userStyleRules += `
|
|
|
|
/* put scrollbar rightside */
|
|
:root.left #tabbar { direction: ltr; }`;
|
|
break;
|
|
}
|
|
}
|
|
|
|
case 6:
|
|
if (configs.promoteFirstChildForClosedRoot != null &&
|
|
configs.promoteFirstChildForClosedRoot &&
|
|
configs.closeParentBehavior == Constants.kPARENT_TAB_OPERATION_BEHAVIOR_PROMOTE_ALL_CHILDREN)
|
|
configs.closeParentBehavior = Constants.kPARENT_TAB_OPERATION_BEHAVIOR_PROMOTE_INTELLIGENTLY;
|
|
if (configs.parentTabBehaviorForChanges !== null) {
|
|
switch (configs.parentTabBehaviorForChanges) {
|
|
case Constants.kPARENT_TAB_BEHAVIOR_ALWAYS:
|
|
configs.parentTabOperationBehaviorMode = Constants.kPARENT_TAB_OPERATION_BEHAVIOR_MODE_CONSISTENT;
|
|
break;
|
|
default:
|
|
case Constants.kPARENT_TAB_BEHAVIOR_ONLY_WHEN_VISIBLE:
|
|
configs.parentTabOperationBehaviorMode = Constants.kPARENT_TAB_OPERATION_BEHAVIOR_MODE_PARALLEL;
|
|
break;
|
|
case Constants.kPARENT_TAB_BEHAVIOR_ONLY_ON_SIDEBAR:
|
|
configs.parentTabOperationBehaviorMode = Constants.kPARENT_TAB_OPERATION_BEHAVIOR_MODE_CUSTOM;
|
|
configs.closeParentBehavior_outsideSidebar_expanded = configs.closeParentBehavior_noSidebar_expanded = configs. closeParentBehavior;
|
|
break;
|
|
}
|
|
}
|
|
|
|
case 7:
|
|
if (configs.collapseExpandSubtreeByDblClick !== null &&
|
|
configs.collapseExpandSubtreeByDblClick)
|
|
configs.treeDoubleClickBehavior = Constants.kTREE_DOUBLE_CLICK_BEHAVIOR_TOGGLE_COLLAPSED;
|
|
|
|
case 8:
|
|
if (configs.autoExpandOnCollapsedChildActive !== null)
|
|
configs.unfocusableCollapsedTab = configs.autoExpandOnCollapsedChildActive;
|
|
|
|
case 9:
|
|
if (configs.simulateCloseTabByDblclick !== null &&
|
|
configs.simulateCloseTabByDblclick)
|
|
configs.treeDoubleClickBehavior = Constants.kTREE_DOUBLE_CLICK_BEHAVIOR_CLOSE;
|
|
|
|
case 10:
|
|
if (configs.style == 'plain-dark' ||
|
|
configs.style == 'metal')
|
|
configs.style = configs.$default.style;
|
|
|
|
case 11:
|
|
if (configs.userStyleRules) {
|
|
configs.userStyleRules0 = configs.userStyleRules;
|
|
configs.userStyleRules = '';
|
|
}
|
|
|
|
case 12:
|
|
try {
|
|
saveUserStyleRules(Array.from(new Uint8Array(8), (_, index) => {
|
|
const key = `userStyleRules${index}`;
|
|
if (key in configs) {
|
|
const chunk = configs[key];
|
|
configs[key] = '';
|
|
return chunk || '';
|
|
}
|
|
else {
|
|
return '';
|
|
}
|
|
}).join(''));
|
|
}
|
|
catch(error) {
|
|
console.error(error);
|
|
}
|
|
|
|
case 13:
|
|
if (configs.style == 'mixed' ||
|
|
configs.style == 'vertigo')
|
|
configs.style = 'photon';
|
|
|
|
case 14:
|
|
if (configs.inheritContextualIdentityToNewChildTab !== null)
|
|
configs.inheritContextualIdentityToChildTabMode = configs.inheritContextualIdentityToNewChildTab ? Constants.kCONTEXTUAL_IDENTITY_FROM_PARENT : Constants.kCONTEXTUAL_IDENTITY_DEFAULT;
|
|
if (configs.inheritContextualIdentityToSameSiteOrphan !== null)
|
|
configs.inheritContextualIdentityToSameSiteOrphanMode = configs.inheritContextualIdentityToSameSiteOrphan ? Constants.kCONTEXTUAL_IDENTITY_FROM_LAST_ACTIVE : Constants.kCONTEXTUAL_IDENTITY_DEFAULT;
|
|
if (configs.inheritContextualIdentityToTabsFromExternal !== null)
|
|
configs.inheritContextualIdentityToTabsFromExternalMode = configs.inheritContextualIdentityToTabsFromExternal ? Constants.kCONTEXTUAL_IDENTITY_FROM_PARENT : Constants.kCONTEXTUAL_IDENTITY_DEFAULT;
|
|
|
|
case 15:
|
|
if (configs.moveDroppedTabToNewWindowForUnhandledDragEvent !== null &&
|
|
!configs.moveDroppedTabToNewWindowForUnhandledDragEvent) {
|
|
if (configs.tabDragBehavior & Constants.kDRAG_BEHAVIOR_TEAR_OFF)
|
|
configs.tabDragBehavior = configs.tabDragBehavior ^ Constants.kDRAG_BEHAVIOR_TEAR_OFF;
|
|
else if (configs.tabDragBehavior & Constants.kDRAG_BEHAVIOR_ALLOW_BOOKMARK)
|
|
configs.tabDragBehavior = configs.tabDragBehavior ^ Constants.kDRAG_BEHAVIOR_ALLOW_BOOKMARK;
|
|
|
|
if (configs.tabDragBehaviorShift & Constants.kDRAG_BEHAVIOR_TEAR_OFF)
|
|
configs.tabDragBehaviorShift = configs.tabDragBehaviorShift ^ Constants.kDRAG_BEHAVIOR_TEAR_OFF;
|
|
else if (configs.tabDragBehaviorShift & Constants.kDRAG_BEHAVIOR_ALLOW_BOOKMARK)
|
|
configs.tabDragBehaviorShift = configs.tabDragBehaviorShift ^ Constants.kDRAG_BEHAVIOR_ALLOW_BOOKMARK;
|
|
}
|
|
|
|
case 16:
|
|
configs.maximumDelayForBug1561879 = Math.max(configs.$default.maximumDelayForBug1561879, configs.maximumDelayForBug1561879);
|
|
|
|
case 17:
|
|
configs.tabDragBehavior |= Constants.kDRAG_BEHAVIOR_MOVE;
|
|
configs.tabDragBehaviorShift |= Constants.kDRAG_BEHAVIOR_MOVE;
|
|
|
|
case 18:
|
|
if (configs.connectionTimeoutDelay == 5000)
|
|
configs.connectionTimeoutDelay = configs.$default.connectionTimeoutDelay;
|
|
|
|
case 19:
|
|
if (configs.suppressGapFromShownOrHiddenToolbar !== null) {
|
|
configs.suppressGapFromShownOrHiddenToolbarOnNewTab =
|
|
configs.suppressGapFromShownOrHiddenToolbarOnFullScreen = configs.suppressGapFromShownOrHiddenToolbar;
|
|
}
|
|
|
|
case 20:
|
|
if (configs.treatTreeAsExpandedOnClosedWithNoSidebar !== null) {
|
|
configs.treatTreeAsExpandedOnClosed_noSidebar = configs.treatTreeAsExpandedOnClosedWithNoSidebar;
|
|
}
|
|
|
|
case 21:
|
|
if (configs.style == 'plain')
|
|
configs.style = 'photon';
|
|
|
|
case 22:
|
|
case 23:
|
|
if (configs.closeParentBehaviorMode !== null) {
|
|
configs.parentTabOperationBehaviorMode = configs.closeParentBehaviorMode;
|
|
}
|
|
if (configs.closeParentBehavior !== null) {
|
|
configs.closeParentBehavior_insideSidebar_expanded =
|
|
configs.closeParentBehavior;
|
|
}
|
|
if (configs.closeParentBehavior_outsideSidebar !== null) {
|
|
configs.closeParentBehavior_outsideSidebar_expanded =
|
|
configs.moveParentBehavior_outsideSidebar_expanded =
|
|
configs.closeParentBehavior_outsideSidebar;
|
|
}
|
|
if (configs.closeParentBehavior_noSidebar !== null) {
|
|
configs.closeParentBehavior_noSidebar_expanded =
|
|
configs.closeParentBehavior_noSidebar_expanded =
|
|
configs.closeParentBehavior_noSidebar;
|
|
}
|
|
if (configs.treatTreeAsExpandedOnClosed_outsideSidebar === true) {
|
|
configs.closeParentBehavior_outsideSidebar_collapsed =
|
|
configs.moveParentBehavior_outsideSidebar_collapsed =
|
|
configs.moveParentBehavior_outsideSidebar_expanded;
|
|
}
|
|
if (configs.treatTreeAsExpandedOnClosed_noSidebar === false) {
|
|
configs.closeParentBehavior_noSidebar_collapsed =
|
|
configs.moveParentBehavior_noSidebar_collapsed =
|
|
Constants.kPARENT_TAB_OPERATION_BEHAVIOR_ENTIRE_TREE;
|
|
}
|
|
if (configs.treatTreeAsExpandedOnClosed_outsideSidebar === true ||
|
|
configs.treatTreeAsExpandedOnClosed_noSidebar === false) {
|
|
configs.parentTabOperationBehaviorMode = Constants.kPARENT_TAB_OPERATION_BEHAVIOR_MODE_CUSTOM;
|
|
}
|
|
|
|
case 24:
|
|
if (configs.autoGroupNewTabsTimeout !== null)
|
|
configs.tabBunchesDetectionTimeout = configs.autoGroupNewTabsTimeout;
|
|
if (configs.autoGroupNewTabsDelayOnNewWindow !== null)
|
|
configs.tabBunchesDetectionDelayOnNewWindow = configs.autoGroupNewTabsDelayOnNewWindow;
|
|
|
|
case 25:
|
|
if (configs.autoHiddenScrollbarPlaceholderSize !== null)
|
|
configs.shiftTabsForScrollbarDistance = configs.autoHiddenScrollbarPlaceholderSize;
|
|
|
|
case 26:
|
|
if (!configs.guessNewOrphanTabAsOpenedByNewTabCommandUrl.includes('about:privatebrowsing'))
|
|
configs.guessNewOrphanTabAsOpenedByNewTabCommandUrl = `${configs.guessNewOrphanTabAsOpenedByNewTabCommandUrl.trim().replace(/\|$/, '')}|about:privatebrowsing`;
|
|
|
|
case 27:
|
|
if (configs.openAllBookmarksWithGroupAlways !== null)
|
|
configs.suppressGroupTabForStructuredTabsFromBookmarks = !configs.openAllBookmarksWithGroupAlways;
|
|
|
|
case 28:
|
|
if (configs.heartbeatInterval == 1000)
|
|
configs.heartbeatInterval = configs.$default.heartbeatInterval;
|
|
|
|
case 29:
|
|
const autoAttachKeys = [
|
|
'autoAttachOnOpenedWithOwner',
|
|
'autoAttachOnNewTabCommand',
|
|
'autoAttachOnContextNewTabCommand',
|
|
'autoAttachOnNewTabButtonMiddleClick',
|
|
'autoAttachOnNewTabButtonAccelClick',
|
|
'autoAttachOnDuplicated',
|
|
'autoAttachSameSiteOrphan',
|
|
'autoAttachOnOpenedFromExternal',
|
|
'autoAttachOnAnyOtherTrigger',
|
|
];
|
|
if (configs.insertNewChildAt != configs.$default.insertNewChildAt &&
|
|
(configs.insertNewChildAt == Constants.kINSERT_TOP ||
|
|
configs.insertNewChildAt == Constants.kINSERT_END)) {
|
|
for (const key of autoAttachKeys) {
|
|
if (configs[key] != configs.$default[key] &&
|
|
configs[key] != Constants.kNEWTAB_OPEN_AS_CHILD)
|
|
continue;
|
|
if (configs.insertNewChildAt == Constants.kINSERT_TOP)
|
|
configs[key] = Constants.kNEWTAB_OPEN_AS_CHILD_TOP;
|
|
else
|
|
configs[key] = Constants.kNEWTAB_OPEN_AS_CHILD_END;
|
|
}
|
|
}
|
|
else {
|
|
for (const key of autoAttachKeys) {
|
|
if (configs[key] == Constants.kNEWTAB_OPEN_AS_CHILD)
|
|
configs[key] = Constants.kNEWTAB_OPEN_AS_CHILD_TOP;
|
|
}
|
|
}
|
|
|
|
case 30:
|
|
browser.windows.getAll().then(windows => {
|
|
for (const win of windows) {
|
|
browser.sessions.removeWindowValue(win.id, Constants.kWINDOW_STATE_CACHED_SIDEBAR);
|
|
browser.sessions.removeWindowValue(win.id, Constants.kWINDOW_STATE_CACHED_SIDEBAR_TABS_DIRTY);
|
|
browser.sessions.removeWindowValue(win.id, Constants.kWINDOW_STATE_CACHED_SIDEBAR_COLLAPSED_DIRTY);
|
|
}
|
|
});
|
|
|
|
case 31:
|
|
if (configs.tabPreviewTooltipInSidebar !== null)
|
|
configs.tabPreviewTooltipRenderIn = configs.tabPreviewTooltipInSidebar ?
|
|
Constants.kIN_CONTENT_PANEL_RENDER_IN_ANYWHERE :
|
|
Constants.kIN_CONTENT_PANEL_RENDER_IN_CONTENT;
|
|
|
|
case 32:
|
|
if (configs.tabPreviewTooltipOffsetTop !== null)
|
|
configs.inContentUIOffsetTop = configs.tabPreviewTooltipOffsetTop;
|
|
}
|
|
configs.configsVersion = kCONFIGS_VERSION;
|
|
}
|
|
|
|
let mShouldShowInitialStartupPage = false;
|
|
|
|
export function tryNotifyNewFeatures() {
|
|
/*
|
|
let featuresVersionOffset = 0;
|
|
const browserInfo = await browser.runtime.getBrowserInfo().catch(ApiTabs.createErrorHandler());
|
|
// "search" permission becomes available!
|
|
if (parseInt(browserInfo.version.split('.')[0]) >= 63)
|
|
featuresVersionOffset++;
|
|
// "menus.overrideContext" permission becomes available!
|
|
if (parseInt(browserInfo.version.split('.')[0]) >= 64)
|
|
featuresVersionOffset++;
|
|
*/
|
|
|
|
const featuresVersion = kFEATURES_VERSION /*+ featuresVersionOffset*/;
|
|
const isInitialInstall = configs.notifiedFeaturesVersion == 0;
|
|
|
|
if (configs.notifiedFeaturesVersion >= featuresVersion)
|
|
return;
|
|
configs.notifiedFeaturesVersion = featuresVersion;
|
|
|
|
if (isInitialInstall &&
|
|
!configs.syncOtherDevicesDetected &&
|
|
Object.keys(configs.syncDevices).length > 1) {
|
|
configs.syncAvailableNotified = true;
|
|
configs.syncOtherDevicesDetected = true;
|
|
}
|
|
|
|
const typeSuffix = isInitialInstall ? 'installed' : 'updated';
|
|
const platformSuffix = isLinux() ? '_linux' : '';
|
|
const url = isInitialInstall ? Constants.kSHORTHAND_URIS.startup : browser.i18n.getMessage('message_startup_history_uri');
|
|
notify({
|
|
url,
|
|
title: browser.i18n.getMessage(`startup_notification_title_${typeSuffix}`),
|
|
message: browser.i18n.getMessage(`startup_notification_message_${typeSuffix}${platformSuffix}`),
|
|
timeout: 90 * 1000
|
|
});
|
|
|
|
if (isInitialInstall) {
|
|
mShouldShowInitialStartupPage = true;
|
|
browser.browserAction.setBadgeText({
|
|
text: '!',
|
|
});
|
|
}
|
|
}
|
|
|
|
export function isInitialStartup() {
|
|
return !!mShouldShowInitialStartupPage;
|
|
}
|
|
|
|
export function openInitialStartupPage() {
|
|
mShouldShowInitialStartupPage = false;
|
|
browser.browserAction.setBadgeText({
|
|
text: null,
|
|
});
|
|
browser.tabs.create({
|
|
url: Constants.kSHORTHAND_URIS.startup,
|
|
active: true,
|
|
});
|
|
}
|
|
|
|
|
|
// Auto-migration of bookmarked internal URLs
|
|
//
|
|
// Internal URLs like "moz-extension://(UUID)/..." are runtime environment
|
|
// dependent and unavailable when such bookmarks are loaded in different
|
|
// runtime environment, for example they are synchronized from other devices.
|
|
// Thus we should migrate such internal URLs to universal shorthand URIs like
|
|
// "ext+ws:(name)".
|
|
|
|
export async function migrateBookmarkUrls() {
|
|
const granted = await Permissions.isGranted(Permissions.BOOKMARKS);
|
|
if (!granted)
|
|
return;
|
|
|
|
startBookmarksUrlAutoMigration();
|
|
|
|
const urls = new Set(configs.migratedBookmarkUrls);
|
|
const migrations = [];
|
|
const updates = [];
|
|
for (const key in Constants.kSHORTHAND_URIS) {
|
|
const url = Constants.kSHORTHAND_URIS[key].split('?')[0];
|
|
if (urls.has(url))
|
|
continue;
|
|
|
|
const shorthand = `ext+ws:${key.toLowerCase()}`;
|
|
migrations.push(browser.bookmarks.search({ query: url })
|
|
.then(bookmarks => {
|
|
for (const bookmark of bookmarks) {
|
|
updates.push(browser.bookmarks.update(bookmark.id, {
|
|
url: bookmark.url.replace(url, shorthand)
|
|
}));
|
|
}
|
|
}));
|
|
urls.add(url);
|
|
}
|
|
if (migrations.length > 0)
|
|
await Promise.all(migrations);
|
|
if (updates.length > 0)
|
|
await Promise.all(updates);
|
|
if (urls.size > configs.migratedBookmarkUrls.length)
|
|
configs.migratedBookmarkUrls = Array.from(urls);
|
|
}
|
|
|
|
async function migrateBookmarkUrl(bookmark) {
|
|
for (const key in Constants.kSHORTHAND_URIS) {
|
|
const url = Constants.kSHORTHAND_URIS[key].split('?')[0];
|
|
if (!bookmark.url.startsWith(url))
|
|
continue;
|
|
|
|
const shorthand = `ext+ws:${key.toLowerCase()}`;
|
|
return browser.bookmarks.update(bookmark.id, {
|
|
url: bookmark.url.replace(url, shorthand)
|
|
});
|
|
}
|
|
}
|
|
|
|
let mObservingBookmarks = false;
|
|
let mBookmarksListenersRegistered = false;
|
|
|
|
function onBookmarkCreated(id, bookmark) {
|
|
if (!mObservingBookmarks)
|
|
return;
|
|
|
|
if (bookmark.url)
|
|
migrateBookmarkUrl(bookmark);
|
|
}
|
|
|
|
async function onBookmarkChanged(id, changeInfo) {
|
|
if (!mObservingBookmarks)
|
|
return;
|
|
|
|
if (changeInfo.url &&
|
|
changeInfo.url.startsWith(browser.runtime.getURL(''))) {
|
|
const bookmark = await browser.bookmarks.get(id);
|
|
if (Array.isArray(bookmark))
|
|
bookmark.forEach(migrateBookmarkUrl);
|
|
else
|
|
migrateBookmarkUrl(bookmark);
|
|
}
|
|
}
|
|
|
|
if (browser.bookmarks &&
|
|
browser.bookmarks.onCreated) {
|
|
browser.bookmarks.onCreated.addListener(onBookmarkCreated);
|
|
browser.bookmarks.onChanged.addListener(onBookmarkChanged);
|
|
mBookmarksListenersRegistered = true;
|
|
}
|
|
|
|
async function startBookmarksUrlAutoMigration() {
|
|
if (mObservingBookmarks)
|
|
return;
|
|
|
|
mObservingBookmarks = true;
|
|
|
|
if (mBookmarksListenersRegistered ||
|
|
!browser.bookmarks ||
|
|
!browser.bookmarks.onCreated)
|
|
return;
|
|
|
|
browser.bookmarks.onCreated.addListener(onBookmarkCreated);
|
|
browser.bookmarks.onChanged.addListener(onBookmarkChanged);
|
|
mBookmarksListenersRegistered = true;
|
|
}
|
|
|
|
|
|
configs.$loaded.then(() => {
|
|
configs.$addObserver(async key => {
|
|
// This may be triggered not only "reset all", but while importing of configs also.
|
|
// We should try initial migration after all configs are successfully imported.
|
|
await wait(100);
|
|
if (key == 'configsVersion' &&
|
|
configs.configsVersion == 0)
|
|
migrateConfigs();
|
|
});
|
|
});
|