🔧 Work on setting migration

This commit is contained in:
Simon Schneegans
2023-02-10 05:55:50 +01:00
parent 43130b4680
commit f2cf78971d
5 changed files with 133 additions and 53 deletions
+15 -2
View File
@@ -30,6 +30,7 @@ try {
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const Me = imports.misc.extensionUtils.getCurrentExtension(); const Me = imports.misc.extensionUtils.getCurrentExtension();
const migrate = Me.imports.src.migrate;
const utils = Me.imports.src.utils; const utils = Me.imports.src.utils;
const ProfileManager = Me.imports.src.ProfileManager.ProfileManager; const ProfileManager = Me.imports.src.ProfileManager.ProfileManager;
const WindowPicker = Me.imports.src.WindowPicker.WindowPicker; const WindowPicker = Me.imports.src.WindowPicker.WindowPicker;
@@ -82,6 +83,20 @@ class Extension {
// Store a reference to the settings object. // Store a reference to the settings object.
this._settings = ExtensionUtils.getSettings(); this._settings = ExtensionUtils.getSettings();
// Now we check whether the extension settings need to be migrated from a previous
// version. If this is the case, we defer the profile loading until this is finished.
const lastVersion = this._settings.get_int('last-extension-version');
if (lastVersion < Me.metadata.version) {
if (lastVersion <= 26) {
migrate.fromVersion26().then(() => {
this._loadProfiles();
this._settings.set_int('last-extension-version', Me.metadata.version);
});
}
} else {
this._loadProfiles();
}
// We reload all effect profiles whenever the currently edited profile in the // We reload all effect profiles whenever the currently edited profile in the
// preferences dialog changes. This is most likely a bit too often, but it will also // preferences dialog changes. This is most likely a bit too often, but it will also
// happen whenever a new profile is created and whenever an old profile is deleted. // happen whenever a new profile is created and whenever an old profile is deleted.
@@ -89,8 +104,6 @@ class Extension {
this._loadProfiles(); this._loadProfiles();
}); });
this._loadProfiles();
// This is used to get the desktop's color scheme. // This is used to get the desktop's color scheme.
this._shellSettings = new Gio.Settings({schema: 'org.gnome.desktop.interface'}); this._shellSettings = new Gio.Settings({schema: 'org.gnome.desktop.interface'});
+4 -7
View File
@@ -28,7 +28,6 @@ const _ = imports.gettext.domain('burn-my-windows').gettext;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const Me = imports.misc.extensionUtils.getCurrentExtension(); const Me = imports.misc.extensionUtils.getCurrentExtension();
const migrate = Me.imports.src.migrate;
const utils = Me.imports.src.utils; const utils = Me.imports.src.utils;
const ProfileManager = Me.imports.src.ProfileManager.ProfileManager; const ProfileManager = Me.imports.src.ProfileManager.ProfileManager;
@@ -68,8 +67,6 @@ var PreferencesDialog = class PreferencesDialog {
new Me.imports.src.effects.Wisps.Wisps(), new Me.imports.src.effects.Wisps.Wisps(),
]; ];
migrate.migrate();
// Load all of our resources. // Load all of our resources.
this._resources = Gio.Resource.load(Me.path + '/resources/burn-my-windows.gresource'); this._resources = Gio.Resource.load(Me.path + '/resources/burn-my-windows.gresource');
Gio.resources_register(this._resources); Gio.resources_register(this._resources);
@@ -358,7 +355,7 @@ var PreferencesDialog = class PreferencesDialog {
// Show an Adw.Toast or a Gtk.InfoBar whenever Burn-My-Windows was updated. We use a // Show an Adw.Toast or a Gtk.InfoBar whenever Burn-My-Windows was updated. We use a
// small timeout so that it is not shown instantaneously. // small timeout so that it is not shown instantaneously.
const lastVersion = this._settings.get_int('last-version'); const lastVersion = this._settings.get_int('last-prefs-version');
if (lastVersion < Me.metadata.version) { if (lastVersion < Me.metadata.version) {
this._showUpdateInfoTimeout = this._showUpdateInfoTimeout =
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 2000, () => { GLib.timeout_add(GLib.PRIORITY_DEFAULT, 2000, () => {
@@ -372,13 +369,13 @@ var PreferencesDialog = class PreferencesDialog {
toast.connect( toast.connect(
'dismissed', 'dismissed',
() => this._settings.set_int('last-version', Me.metadata.version)); () => this._settings.set_int('last-prefs-version', Me.metadata.version));
window.add_toast(toast); window.add_toast(toast);
} else { } else {
const infoBar = this._builder.get_object('update-info'); const infoBar = this._builder.get_object('update-info');
infoBar.connect('response', i => { infoBar.connect('response', i => {
this._settings.set_int('last-version', Me.metadata.version); this._settings.set_int('last-prefs-version', Me.metadata.version);
i.set_revealed(false); i.set_revealed(false);
}); });
infoBar.set_revealed(true); infoBar.set_revealed(true);
@@ -459,7 +456,7 @@ var PreferencesDialog = class PreferencesDialog {
null, null,
'https://github.com/Schneegans/Burn-My-Windows/blob/main/docs/changelog.md', 'https://github.com/Schneegans/Burn-My-Windows/blob/main/docs/changelog.md',
Gdk.CURRENT_TIME); Gdk.CURRENT_TIME);
this._settings.set_int('last-version', Me.metadata.version) this._settings.set_int('last-prefs-version', Me.metadata.version)
}); });
group.add_action(changelogAction); group.add_action(changelogAction);
@@ -31,10 +31,16 @@ SPDX-License-Identifier: CC0-1.0
<description>If set to true, all animations will show only one still frame to allow for continuous integration tests.</description> <description>If set to true, all animations will show only one still frame to allow for continuous integration tests.</description>
</key> </key>
<key name="last-version" type="i"> <key name="last-prefs-version" type="i">
<default>0</default> <default>0</default>
<summary>Last Version</summary> <summary>Last Prefs Version</summary>
<description>Used to check whether the extension got updated.</description> <description>Used to check whether the extension got updated from the preferences dialog.</description>
</key>
<key name="last-extension-version" type="i">
<default>0</default>
<summary>Last Extension Version</summary>
<description>Used to check whether the extension got updated from the extension side.</description>
</key> </key>
</schema> </schema>
+7 -5
View File
@@ -56,15 +56,17 @@ var ProfileManager = class {
return this._profiles; return this._profiles;
} }
// This will create a new profile with all values initialized to their defaults. The // This will create a new profile. If no content is given, all values will be
// method will return an effect profile object (as described above). We will use the // initialized to their defaults. The method will return an effect profile object (as
// current system time in microseconds as profile name. This ensures that they are // described above). We will use the current system time in microseconds as profile
// always sorted according to their creation date. // name. This ensures that they are always sorted according to their creation date.
createProfile() { createProfile(content = '') {
const path = `${GLib.get_user_config_dir()}/burn-my-windows/profiles/${ const path = `${GLib.get_user_config_dir()}/burn-my-windows/profiles/${
GLib.get_real_time()}.conf`; GLib.get_real_time()}.conf`;
const file = Gio.File.new_for_path(path); const file = Gio.File.new_for_path(path);
file.create(Gio.FileCreateFlags.NONE, null); file.create(Gio.FileCreateFlags.NONE, null);
file.replace_contents(content, null, false, Gio.FileCreateFlags.REPLACE_DESTINATION,
null);
const profile = {'path': path, 'settings': this._getProfileSettings(path)}; const profile = {'path': path, 'settings': this._getProfileSettings(path)};
+98 -36
View File
@@ -16,27 +16,35 @@
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const Me = imports.misc.extensionUtils.getCurrentExtension(); const Me = imports.misc.extensionUtils.getCurrentExtension();
const ProfileManager = Me.imports.src.ProfileManager.ProfileManager;
const utils = Me.imports.src.utils; const utils = Me.imports.src.utils;
function migrate() { // Migrating from pre-27 versions is pretty involved. Before, all settings were stored in
utils.executeCommand(['dconf', 'dump', '/org/gnome/shell/extensions/burn-my-windows/']) // the standard Gio.Settings backend. Now, there are effect profiles. Depending on the
// settings one or two profiles may be required.
async function fromVersion26() {
return utils
.executeCommand(['dconf', 'dump', '/org/gnome/shell/extensions/burn-my-windows/'])
.catch(r => utils.debug('Failed to get old settings for effect migration: ' + r)) .catch(r => utils.debug('Failed to get old settings for effect migration: ' + r))
.then(r => { .then(r => {
utils.debug('Starting Burn-My-Windows profile migration!'); utils.debug('Starting Burn-My-Windows profile migration (old version <= 26)!');
// The default value of this is false, so not-present is equal to false. // We use this to write the new profiles.
const profileManager = new ProfileManager();
// The default value of this was false, so not-present is equal to false.
const destroyDialogs = r.includes('destroy-dialogs=true'); const destroyDialogs = r.includes('destroy-dialogs=true');
if (!destroyDialogs) { if (!destroyDialogs) {
utils.debug('Only normal windows will be burned by the new profile(s).'); utils.debug('Only normal windows will be burned by the new profile(s).');
} }
// The default value of this is false, so not-present is equal to false. // The default value of this was false, so not-present is equal to false.
const disableOnBattery = r.includes('disable-on-battery=true'); const disableOnBattery = r.includes('disable-on-battery=true');
if (disableOnBattery) { if (disableOnBattery) {
utils.debug('The new profile(s) will not be active on battery.'); utils.debug('The new profile(s) will not be active on battery.');
} }
// The default value of this is false, so not-present is equal to false. // The default value of this was false, so not-present is equal to false.
const disableOnPowerSave = r.includes('disable-on-power-save=true'); const disableOnPowerSave = r.includes('disable-on-power-save=true');
if (disableOnPowerSave) { if (disableOnPowerSave) {
utils.debug('The new profile(s) will not be active in power-save mode.'); utils.debug('The new profile(s) will not be active in power-save mode.');
@@ -45,7 +53,8 @@ function migrate() {
// Remove some unnecessary lines. // Remove some unnecessary lines.
r = r.replace(/^active-profile=.*\n?/gm, ''); r = r.replace(/^active-profile=.*\n?/gm, '');
r = r.replace(/^test-mode=.*\n?/gm, ''); r = r.replace(/^test-mode=.*\n?/gm, '');
r = r.replace(/^last-version=.*\n?/gm, ''); r = r.replace(/^last-extension-version=.*\n?/gm, '');
r = r.replace(/^last-prefs-version=.*\n?/gm, '');
r = r.replace(/^destroy-dialogs=.*\n?/gm, ''); r = r.replace(/^destroy-dialogs=.*\n?/gm, '');
r = r.replace(/^disable-on-battery=.*\n?/gm, ''); r = r.replace(/^disable-on-battery=.*\n?/gm, '');
r = r.replace(/^disable-on-power-save=.*\n?/gm, ''); r = r.replace(/^disable-on-power-save=.*\n?/gm, '');
@@ -53,15 +62,14 @@ function migrate() {
r = r.replace('[/]\n', ''); r = r.replace('[/]\n', '');
r = r.trim(); r = r.trim();
// There were some inconsistencies in the key names. // There were some inconsistencies in the key names. The update fixes them.
r.replace('flame-', 'fire-'); r.replace('flame-', 'fire-');
r.replace('claw-', 'trex-'); r.replace('claw-', 'trex-');
let lines = r.split('\n');
// Find all effects which were used for openeing and closing. This first extracts // Find all effects which were used for openeing and closing. This first extracts
// all lines which end in "-open-effect=true" and then remove this suffix from the // all lines which end in "-open-effect=true" and then remove this suffix from the
// lines. This leaves only the effect nicks. // lines. This leaves only the effect nicks.
let lines = r.split('\n');
let openEffects = lines.filter(l => l.includes('-open-effect=true')) let openEffects = lines.filter(l => l.includes('-open-effect=true'))
.map(l => l.replace('-open-effect=true', '')); .map(l => l.replace('-open-effect=true', ''));
let closeEffects = lines.filter(l => l.includes('-close-effect=true')) let closeEffects = lines.filter(l => l.includes('-close-effect=true'))
@@ -73,11 +81,13 @@ function migrate() {
closeEffects.push('fire'); closeEffects.push('fire');
} }
// Print all effects we've found.
utils.debug('Enabled open effects: ' + openEffects); utils.debug('Enabled open effects: ' + openEffects);
utils.debug('Enabled close effects: ' + closeEffects); utils.debug('Enabled close effects: ' + closeEffects);
// If the same effects were used for opening and closing windows, only one profile // If the same effects were used for opening and closing windows or there is either
// is required. Else we have to create two new profiles. // no opening or no closing animation configured, only one profile is required. Else
// we have to create two new profiles.
const numProfiles = openEffects.join() == closeEffects.join() ? 1 : 2; const numProfiles = openEffects.join() == closeEffects.join() ? 1 : 2;
if (numProfiles == 1) { if (numProfiles == 1) {
utils.debug('Only one profile is required.'); utils.debug('Only one profile is required.');
@@ -89,69 +99,121 @@ function migrate() {
utils.debug('Two profiles are required.'); utils.debug('Two profiles are required.');
} }
const profile = // Remove all open / close lines.
const profileLines =
lines.filter(l => !l.includes('-close-effect=') && !l.includes('-open-effect=')); lines.filter(l => !l.includes('-close-effect=') && !l.includes('-open-effect='));
profile.unshift('[burn-my-windows-profile]');
// Add the header.
profileLines.unshift('[burn-my-windows-profile]');
// Push the line which makes the profile only apply to normal windows.
if (!destroyDialogs) { if (!destroyDialogs) {
profile.push('profile-window-type=1'); profileLines.push('profile-window-type=1');
} }
// Push the line which makes the profile only active when plugged in.
if (disableOnBattery) { if (disableOnBattery) {
profile.push('profile-power-mode=2'); profileLines.push('profile-power-mode=2');
} }
// Push the line which makes the profile only active when on balanced or performance
// mode.
if (disableOnPowerSave) { if (disableOnPowerSave) {
profile.push('profile-power-profile=5'); profileLines.push('profile-power-profile=5');
} }
// Now comes a bit of code repetition, but it is more readable this way.
if (numProfiles == 1) { if (numProfiles == 1) {
openEffects.forEach(e => profile.push(e + '-enable-effect=true'));
// Add all relevant effects.
openEffects.forEach(e => profileLines.push(e + '-enable-effect=true'));
// The fire effect is enabled per default, so we have to explicitly disable it if
// not required.
if (!openEffects.includes('fire')) { if (!openEffects.includes('fire')) {
profile.push('fire-enable-effect=false'); profileLines.push('fire-enable-effect=false');
} }
// Print and save the new profile.
const profile = profileLines.join('\n');
utils.debug('The new profile:'); utils.debug('The new profile:');
utils.debug(profile.join('\n')); utils.debug(profile);
profileManager.createProfile(profile);
} else if (closeEffects.length == 0) { } else if (closeEffects.length == 0) {
profile.push('profile-animation-type=1') // This profile is only for window openeing.
openEffects.forEach(e => profile.push(e + '-enable-effect=true')); profileLines.push('profile-animation-type=1')
// Add all relevant effects.
openEffects.forEach(e => profileLines.push(e + '-enable-effect=true'));
// The fire effect is enabled per default, so we have to explicitly disable it if
// not required.
if (!openEffects.includes('fire')) { if (!openEffects.includes('fire')) {
profile.push('fire-enable-effect=false'); profileLines.push('fire-enable-effect=false');
} }
// Print and save the new profile.
const profile = profileLines.join('\n');
utils.debug('The new window-open profile:'); utils.debug('The new window-open profile:');
utils.debug(profile.join('\n')); utils.debug(profile);
profileManager.createProfile(profile);
} else if (openEffects.length == 0) { } else if (openEffects.length == 0) {
profile.push('profile-animation-type=2') // This profile is only for window closing.
closeEffects.forEach(e => profile.push(e + '-enable-effect=true')); profileLines.push('profile-animation-type=2')
// Add all relevant effects.
closeEffects.forEach(e => profileLines.push(e + '-enable-effect=true'));
// The fire effect is enabled per default, so we have to explicitly disable it if
// not required.
if (!closeEffects.includes('fire')) { if (!closeEffects.includes('fire')) {
profile.push('fire-enable-effect=false'); profileLines.push('fire-enable-effect=false');
} }
// Print and save the new profile.
const profile = profileLines.join('\n');
utils.debug('The new window-close profile:'); utils.debug('The new window-close profile:');
utils.debug(profile.join('\n')); utils.debug(profile);
profileManager.createProfile(profile);
} else { } else {
const openProfile = [...profile, 'profile-animation-type=1']; const openProfileLines = [...profile, 'profile-animation-type=1'];
const closeProfile = [...profile, 'profile-animation-type=2']; const closeProfileLines = [...profile, 'profile-animation-type=2'];
openEffects.forEach(e => openProfile.push(e + '-enable-effect=true')); // Add all relevant effects.
closeEffects.forEach(e => closeProfile.push(e + '-enable-effect=true')); openEffects.forEach(e => openProfileLines.push(e + '-enable-effect=true'));
closeEffects.forEach(e => closeProfileLines.push(e + '-enable-effect=true'));
// The fire effect is enabled per default, so we have to explicitly disable it if
// not required.
if (!closeEffects.includes('fire')) { if (!closeEffects.includes('fire')) {
closeProfile.push('fire-enable-effect=false'); closeProfileLines.push('fire-enable-effect=false');
} }
// Print and save the new profiles.
const openProfile = openProfileLines.join('\n');
const closeProfile = closeProfileLines.join('\n');
utils.debug('The new open-window profile:'); utils.debug('The new open-window profile:');
utils.debug(openProfile.join('\n')); utils.debug(openProfile);
utils.debug('The new close-window profile:'); utils.debug('The new close-window profile:');
utils.debug(closeProfile.join('\n')); utils.debug(closeProfile);
profileManager.createProfile(openProfile);
profileManager.createProfile(closeProfile);
} }
}) })
.catch(r => utils.debug('Failed migrate settings: ' + r)); .catch(r => utils.debug('Failed to migrate settings: ' + r));
} }