From 1a3f6301b762daaae4bf5bc9ac62c67a93974dba Mon Sep 17 00:00:00 2001 From: Fletcher Hazlehurst Date: Fri, 18 Dec 2020 10:11:01 -0700 Subject: [PATCH 1/3] Add syncing reminders (#2354) There are two: - Sync never set up (no username in DB) / set up, but unlinked - Sync set up but auto-sync disabled and sync not completed in 30 days Checks are trigged on item adds. --- chrome/content/zotero/xpcom/prefs.js | 9 + chrome/content/zotero/zoteroPane.js | 171 +++++++++++++++++++ chrome/content/zotero/zoteroPane.xul | 13 +- chrome/locale/en-US/zotero/zotero.properties | 7 + chrome/skin/default/zotero/overlay.css | 29 +++- defaults/preferences/zotero.js | 4 + 6 files changed, 225 insertions(+), 8 deletions(-) diff --git a/chrome/content/zotero/xpcom/prefs.js b/chrome/content/zotero/xpcom/prefs.js index f21ea54a08..c00ac200d0 100644 --- a/chrome/content/zotero/xpcom/prefs.js +++ b/chrome/content/zotero/xpcom/prefs.js @@ -252,6 +252,15 @@ Zotero.Prefs = new function(){ else { Zotero.Sync.EventListeners.AutoSyncListener.unregister(); Zotero.Sync.EventListeners.IdleListener.unregister(); + Zotero.Prefs.set('sync.reminder.autoSync.enabled', true); + // We don't want to immediately display reminder so bump this value + Zotero.Prefs.set('sync.reminder.autoSync.lastDisplayed', String(Date.now())); + } + try { + Zotero.getActiveZoteroPane().setupSyncReminders(false); + } + catch (e) { + Zotero.logError(e); } }], [ "search.quicksearch-mode", function(val) { diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js index 6ee28ebcb2..a9d67fcb07 100644 --- a/chrome/content/zotero/zoteroPane.js +++ b/chrome/content/zotero/zoteroPane.js @@ -229,6 +229,7 @@ var ZoteroPane = new function() setTimeout(function () { ZoteroPane.showRetractionBanner(); + ZoteroPane.setupSyncReminders(true); }); // TEMP: Clean up extra files from Mendeley imports <5.0.51 @@ -355,6 +356,9 @@ var ZoteroPane = new function() if(this.collectionsView) this.collectionsView.unregister(); if(this.itemsView) this.itemsView.unregister(); + if (this._syncRemindersObserverID) { + Zotero.Notifier.unregisterObserver(this._syncRemindersObserverID); + } this.uninitContainers(); @@ -2249,6 +2253,173 @@ var ZoteroPane = new function() }); + this.sync = function () { + let syncReminder = document.getElementById('sync-reminder-container'); + if (!syncReminder.collapsed) { + syncReminder.collapsed = true; + } + + Zotero.Sync.Server.canAutoResetClient = true; + Zotero.Sync.Server.manualSyncRequired = false; + Zotero.Sync.Runner.sync(); + }; + + + this._syncRemindersObserverID = null; + this.setupSyncReminders = function (startup) { + if (startup) { + Zotero.Notifier.registerObserver( + { notify: (event) => { + // When the API Key is deleted we need to add an observer + if (event === 'delete') { + Zotero.Prefs.set('sync.reminder.setup.enabled', true); + Zotero.Prefs.set('sync.reminder.setup.lastDisplayed', String(Date.now())); + ZoteroPane.setupSyncReminders(false); + } + // When API Key is added we can remove the observer + else if (event === 'add') { + ZoteroPane.setupSyncReminders(false); + } + } }, + 'api-key'); + } + + // If both reminders are disabled, we don't need an observer + if (!Zotero.Prefs.get('sync.reminder.setup.enabled') + && !Zotero.Prefs.get('sync.reminder.autoSync.enabled')) { + if (this._syncRemindersObserverID) { + Zotero.Notifier.unregisterObserver(this._syncRemindersObserverID); + this._syncRemindersObserverID = null; + } + return; + } + + // If we are syncing and auto-syncing then no need for observer + if (Zotero.Sync.Runner.enabled && Zotero.Prefs.get('sync.autoSync')) { + if (this._syncRemindersObserverID) { + Zotero.Notifier.unregisterObserver(this._syncRemindersObserverID); + this._syncRemindersObserverID = null; + } + return; + } + + // If we already have an observer don't add another one + if (this._syncRemindersObserverID) { + return; + } + + const eventTypes = ['add', 'modify', 'delete']; + this._syncRemindersObserverID = Zotero.Notifier.registerObserver( + { notify: (event) => { + if (!eventTypes.includes(event)) { + return; + } + setTimeout(() => { + this.showSetupSyncReminder(); + this.showAutoSyncOffReminder(); + }, 5000); + } }, + 'item', + 'syncReminder'); + }; + + + this.showAutoSyncOffReminder = function () { + // Reasons not to show reminder: + // - User turned reminder off + // - Sync is not enabled + // - Auto-Sync is enabled + // - Last sync for all libraries was within 30 days + if (!Zotero.Prefs.get('sync.reminder.autoSync.enabled') + || !Zotero.Sync.Runner.enabled + || Zotero.Prefs.get('sync.autoSync') + || !Zotero.Libraries.getAll() + .find(library => library.lastSync.getTime() < (Date.now() - 2592000000))) { + return; + } + + // Check lastDisplayed was 30+ days ago + let lastDisplayed = parseInt(Zotero.Prefs.get(`sync.reminder.autoSync.lastDisplayed`)); + if (lastDisplayed > (Date.now() - 2592000000)) { + return; + } + + this.showSyncReminder('autoSync', false); + }; + + + this.showSetupSyncReminder = function () { + // Reasons not to show reminder: + // - User turned reminder off + // - Sync is enabled + if (!Zotero.Prefs.get('sync.reminder.setup.enabled') + || Zotero.Sync.Runner.enabled) { + return; + } + + // Check lastDisplayed was 7+ days ago + let lastDisplayed = parseInt(Zotero.Prefs.get(`sync.reminder.setup.lastDisplayed`)); + if (lastDisplayed > (Date.now() - 604800000)) { + return; + } + + // When we have not seen the first warning, hide the checkbox + this.showSyncReminder('setup', lastDisplayed === 0); + }; + + + /** + * Configure the UI and show the sync reminder panel for a given type of reminder + * + * @param reminderType - Possible values: 'setup' or 'autoSync' + * @param hideDisable - True if the 'Don't show again' link is hidden + */ + this.showSyncReminder = function (reminderType, hideDisable) { + let panel = document.getElementById('sync-reminder-container'); + const closePanel = function () { + panel.setAttribute('collapsed', true); + Zotero.Prefs.set(`sync.reminder.${reminderType}.lastDisplayed`, String(Date.now())); + }; + + let message = document.getElementById('sync-reminder-message'); + message.textContent = Zotero.getString(`sync.reminder.${reminderType}.message`); + message.onclick = function () { + closePanel(); + Zotero.Utilities.Internal.openPreferences('zotero-prefpane-sync'); + }; + + let actionLink = document.getElementById('sync-reminder-action'); + actionLink.textContent = Zotero.getString(`sync.reminder.${reminderType}.action`); + actionLink.onclick = function () { + closePanel(); + Zotero.Utilities.Internal.openPreferences('zotero-prefpane-sync'); + }; + + let dontShowAgainLink = document.getElementById('sync-reminder-disable'); + dontShowAgainLink.textContent = Zotero.getString('general.dontAskMeAgain'); + dontShowAgainLink.hidden = hideDisable; + dontShowAgainLink.onclick = function () { + closePanel(); + Zotero.Prefs.set(`sync.reminder.${reminderType}.enabled`, false); + // Check if we no longer need to observe item modifications + ZoteroPane.setupSyncReminders(false); + }; + + let remindMeLink = document.getElementById('sync-reminder-remind'); + remindMeLink.textContent = Zotero.getString('sync.reminder.remindMeLater'); + remindMeLink.onclick = function () { + closePanel(); + }; + + let closeButton = document.getElementById('sync-reminder-close'); + closeButton.onclick = function () { + closePanel(); + }; + + panel.removeAttribute('collapsed'); + }; + + this.selectItem = async function (itemID, inLibraryRoot) { if (!itemID) { return false; diff --git a/chrome/content/zotero/zoteroPane.xul b/chrome/content/zotero/zoteroPane.xul index 1361ff418d..a613d937fe 100644 --- a/chrome/content/zotero/zoteroPane.xul +++ b/chrome/content/zotero/zoteroPane.xul @@ -221,7 +221,7 @@ + oncommand="ZoteroPane.sync()"> + + +
+
+ + +
diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties index dbb10b3968..c8cb628187 100644 --- a/chrome/locale/en-US/zotero/zotero.properties +++ b/chrome/locale/en-US/zotero/zotero.properties @@ -3,6 +3,7 @@ extensions.zotero@chnm.gmu.edu.description = The Next-Generation Research Tool general.success = Success general.error = Error general.warning = Warning +general.dontAskMeAgain = Don't ask me again general.dontShowWarningAgain = Don't show this warning again. general.dontShowAgainFor = Don’t show again today;Don’t show again for %1$S days general.browserIsOffline = %S is currently in offline mode. @@ -993,6 +994,12 @@ sync.resetGroupFilesAndSync = Reset Group Files and Sync sync.skipGroup = Skip Group sync.removeGroupsAndSync = Remove Groups and Sync +sync.reminder.setup.message = Back up your library with Zotero syncing. +sync.reminder.setup.action = Set Up Syncing +sync.reminder.autoSync.message = Zotero can automatically sync after you make changes. +sync.reminder.autoSync.action = Enable Automatic Sync +sync.reminder.remindMeLater = Remind Me Later + sync.error.usernameNotSet = Username not set sync.error.usernameNotSet.text = You must enter your zotero.org username and password in the Zotero preferences to sync with the Zotero server. sync.error.passwordNotSet = Password not set diff --git a/chrome/skin/default/zotero/overlay.css b/chrome/skin/default/zotero/overlay.css index 67571a05cd..e505ebb6d2 100644 --- a/chrome/skin/default/zotero/overlay.css +++ b/chrome/skin/default/zotero/overlay.css @@ -533,11 +533,11 @@ } /* Sync error panel */ -#zotero-sync-error-panel { +#zotero-sync-error-panel, #zotero-sync-reminder-panel { margin-right: 0; } -#zotero-sync-error-panel .error-header { +#zotero-sync-error-panel .error-header, #zotero-sync-reminder-panel .header { font-size: 14px; font-weight: bold; margin-bottom: 1em; @@ -552,7 +552,7 @@ margin-bottom: 1.1em; } -#zotero-sync-error-panel description { +#zotero-sync-error-panel description, #zotero-sync-reminder-panel description { width: 370px; white-space: pre-wrap; } @@ -635,7 +635,7 @@ margin-left: 3px !important; } -#retracted-items-banner { +#retracted-items-banner, #sync-reminder-banner { display: flex; justify-content: center; background: #d93425; @@ -648,21 +648,36 @@ position: relative; } -#retracted-items-message { +#sync-reminder-banner { + background: rgb(89, 139, 236); +} + +#retracted-items-message, #sync-reminder-message { margin-right: .8em; } +#sync-reminder-spacer { + flex: 1; +} + #retracted-items-link { text-decoration: underline; margin-left: .3em; cursor: pointer; } -#retracted-items-link:active { +.sync-reminder-link { + text-decoration: underline; + cursor: pointer; + padding-left: 0.5em; + padding-right: 0.5em; +} + +#retracted-items-link:active, .sync-reminder-link:active { color: #f9e8e2; } -#retracted-items-close { +#retracted-items-close, #sync-reminder-close { position: absolute; cursor: pointer; top: -2px; diff --git a/defaults/preferences/zotero.js b/defaults/preferences/zotero.js index 4e63e598d5..db39bd87e3 100644 --- a/defaults/preferences/zotero.js +++ b/defaults/preferences/zotero.js @@ -160,6 +160,10 @@ pref("extensions.zotero.sync.storage.groups.enabled", true); pref("extensions.zotero.sync.storage.downloadMode.personal", "on-sync"); pref("extensions.zotero.sync.storage.downloadMode.groups", "on-sync"); pref("extensions.zotero.sync.fulltext.enabled", true); +pref("extensions.zotero.sync.reminder.setup.enabled", true); +pref("extensions.zotero.sync.reminder.setup.lastDisplayed", "0"); +pref("extensions.zotero.sync.reminder.autoSync.enabled", true); +pref("extensions.zotero.sync.reminder.autoSync.lastDisplayed", "0"); // Proxy pref("extensions.zotero.proxies.autoRecognize", true); From b0f09b3a864b2e989a990836d0f17ca8fb2eb646 Mon Sep 17 00:00:00 2001 From: Abe Jellinek Date: Wed, 16 Feb 2022 12:12:36 -0800 Subject: [PATCH 2/3] Sync reminders changes (#2354) - Always wait seven days, standardize casing - Enable auto-sync without opening preferences - Implement suggestions --- chrome/content/zotero/xpcom/prefs.js | 4 +- chrome/content/zotero/zoteroPane.js | 139 +++++++++++-------- chrome/locale/en-US/zotero/zotero.properties | 12 +- defaults/preferences/zotero.js | 6 +- 4 files changed, 91 insertions(+), 70 deletions(-) diff --git a/chrome/content/zotero/xpcom/prefs.js b/chrome/content/zotero/xpcom/prefs.js index c00ac200d0..e932db012a 100644 --- a/chrome/content/zotero/xpcom/prefs.js +++ b/chrome/content/zotero/xpcom/prefs.js @@ -254,10 +254,10 @@ Zotero.Prefs = new function(){ Zotero.Sync.EventListeners.IdleListener.unregister(); Zotero.Prefs.set('sync.reminder.autoSync.enabled', true); // We don't want to immediately display reminder so bump this value - Zotero.Prefs.set('sync.reminder.autoSync.lastDisplayed', String(Date.now())); + Zotero.Prefs.set('sync.reminder.autoSync.lastDisplayed', Math.round(Date.now() / 1000)); } try { - Zotero.getActiveZoteroPane().setupSyncReminders(false); + Zotero.getActiveZoteroPane().initSyncReminders(false); } catch (e) { Zotero.logError(e); diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js index a9d67fcb07..4f0364ff9c 100644 --- a/chrome/content/zotero/zoteroPane.js +++ b/chrome/content/zotero/zoteroPane.js @@ -229,7 +229,7 @@ var ZoteroPane = new function() setTimeout(function () { ZoteroPane.showRetractionBanner(); - ZoteroPane.setupSyncReminders(true); + ZoteroPane.initSyncReminders(true); }); // TEMP: Clean up extra files from Mendeley imports <5.0.51 @@ -2266,27 +2266,29 @@ var ZoteroPane = new function() this._syncRemindersObserverID = null; - this.setupSyncReminders = function (startup) { + this.initSyncReminders = function (startup) { if (startup) { Zotero.Notifier.registerObserver( - { notify: (event) => { - // When the API Key is deleted we need to add an observer - if (event === 'delete') { - Zotero.Prefs.set('sync.reminder.setup.enabled', true); - Zotero.Prefs.set('sync.reminder.setup.lastDisplayed', String(Date.now())); - ZoteroPane.setupSyncReminders(false); + { + notify: (event) => { + // When the API Key is deleted we need to add an observer + if (event === 'delete') { + Zotero.Prefs.set('sync.reminder.setUp.enabled', true); + Zotero.Prefs.set('sync.reminder.setUp.lastDisplayed', Math.round(Date.now() / 1000)); + ZoteroPane.initSyncReminders(false); + } + // When API Key is added we can remove the observer + else if (event === 'add') { + ZoteroPane.initSyncReminders(false); + } } - // When API Key is added we can remove the observer - else if (event === 'add') { - ZoteroPane.setupSyncReminders(false); - } - } }, + }, 'api-key'); } // If both reminders are disabled, we don't need an observer - if (!Zotero.Prefs.get('sync.reminder.setup.enabled') - && !Zotero.Prefs.get('sync.reminder.autoSync.enabled')) { + if (!Zotero.Prefs.get('sync.reminder.setUp.enabled') + && !Zotero.Prefs.get('sync.reminder.autoSync.enabled')) { if (this._syncRemindersObserverID) { Zotero.Notifier.unregisterObserver(this._syncRemindersObserverID); this._syncRemindersObserverID = null; @@ -2310,37 +2312,64 @@ var ZoteroPane = new function() const eventTypes = ['add', 'modify', 'delete']; this._syncRemindersObserverID = Zotero.Notifier.registerObserver( - { notify: (event) => { - if (!eventTypes.includes(event)) { - return; + { + notify: (event) => { + if (!eventTypes.includes(event)) { + return; + } + setTimeout(() => { + this.showSetUpSyncReminder(); + this.showAutoSyncReminder(); + }, 5000); } - setTimeout(() => { - this.showSetupSyncReminder(); - this.showAutoSyncOffReminder(); - }, 5000); - } }, + }, 'item', 'syncReminder'); }; - this.showAutoSyncOffReminder = function () { + this.showSetUpSyncReminder = function () { + const sevenDays = 60 * 60 * 24 * 7; + + // Reasons not to show reminder: + // - User turned reminder off + // - Sync is enabled + if (!Zotero.Prefs.get('sync.reminder.setUp.enabled') + || Zotero.Sync.Runner.enabled) { + return; + } + + // Check lastDisplayed was 7+ days ago + let lastDisplayed = Zotero.Prefs.get('sync.reminder.setUp.lastDisplayed'); + if (lastDisplayed > Math.round(Date.now() / 1000) - sevenDays) { + return; + } + + // When we have not seen the first warning, hide the checkbox + this.showSyncReminder('setUp', lastDisplayed === 0); + }; + + + this.showAutoSyncReminder = function () { + const sevenDays = 60 * 60 * 24 * 7; + // Reasons not to show reminder: // - User turned reminder off // - Sync is not enabled // - Auto-Sync is enabled - // - Last sync for all libraries was within 30 days + // - Last sync for all libraries was within 7 days if (!Zotero.Prefs.get('sync.reminder.autoSync.enabled') - || !Zotero.Sync.Runner.enabled - || Zotero.Prefs.get('sync.autoSync') - || !Zotero.Libraries.getAll() - .find(library => library.lastSync.getTime() < (Date.now() - 2592000000))) { + || !Zotero.Sync.Runner.enabled + || Zotero.Prefs.get('sync.autoSync') + || Zotero.Libraries.getAll() + .every(library => !library.syncable + || library.lastSync.getTime() > Date.now() - 1000 * sevenDays)) { return; } - // Check lastDisplayed was 30+ days ago - let lastDisplayed = parseInt(Zotero.Prefs.get(`sync.reminder.autoSync.lastDisplayed`)); - if (lastDisplayed > (Date.now() - 2592000000)) { + // Check lastDisplayed was 7+ days ago + let lastDisplayed = Zotero.Prefs.get('sync.reminder.autoSync.lastDisplayed'); + if (lastDisplayed > Math.round(Date.now() / 1000) - sevenDays) { return; } @@ -2348,41 +2377,25 @@ var ZoteroPane = new function() }; - this.showSetupSyncReminder = function () { - // Reasons not to show reminder: - // - User turned reminder off - // - Sync is enabled - if (!Zotero.Prefs.get('sync.reminder.setup.enabled') - || Zotero.Sync.Runner.enabled) { - return; - } - - // Check lastDisplayed was 7+ days ago - let lastDisplayed = parseInt(Zotero.Prefs.get(`sync.reminder.setup.lastDisplayed`)); - if (lastDisplayed > (Date.now() - 604800000)) { - return; - } - - // When we have not seen the first warning, hide the checkbox - this.showSyncReminder('setup', lastDisplayed === 0); - }; - - /** * Configure the UI and show the sync reminder panel for a given type of reminder * - * @param reminderType - Possible values: 'setup' or 'autoSync' + * @param reminderType - Possible values: 'setUp' or 'autoSync' * @param hideDisable - True if the 'Don't show again' link is hidden */ this.showSyncReminder = function (reminderType, hideDisable) { + if (!['setUp', 'autoSync'].includes(reminderType)) { + throw new Error(`Invalid reminder type: ${reminderType}`); + } + let panel = document.getElementById('sync-reminder-container'); const closePanel = function () { panel.setAttribute('collapsed', true); - Zotero.Prefs.set(`sync.reminder.${reminderType}.lastDisplayed`, String(Date.now())); + Zotero.Prefs.set(`sync.reminder.${reminderType}.lastDisplayed`, Math.round(Date.now() / 1000)); }; let message = document.getElementById('sync-reminder-message'); - message.textContent = Zotero.getString(`sync.reminder.${reminderType}.message`); + message.textContent = Zotero.getString(`sync.reminder.${reminderType}.message`, Zotero.appName); message.onclick = function () { closePanel(); Zotero.Utilities.Internal.openPreferences('zotero-prefpane-sync'); @@ -2392,21 +2405,29 @@ var ZoteroPane = new function() actionLink.textContent = Zotero.getString(`sync.reminder.${reminderType}.action`); actionLink.onclick = function () { closePanel(); - Zotero.Utilities.Internal.openPreferences('zotero-prefpane-sync'); + + switch (reminderType) { + case 'setUp': + Zotero.Utilities.Internal.openPreferences('zotero-prefpane-sync'); + break; + case 'autoSync': + Zotero.Prefs.set(`sync.autoSync`, true); + break; + } }; let dontShowAgainLink = document.getElementById('sync-reminder-disable'); - dontShowAgainLink.textContent = Zotero.getString('general.dontAskMeAgain'); + dontShowAgainLink.textContent = Zotero.getString('general.dontAskAgain'); dontShowAgainLink.hidden = hideDisable; dontShowAgainLink.onclick = function () { closePanel(); Zotero.Prefs.set(`sync.reminder.${reminderType}.enabled`, false); // Check if we no longer need to observe item modifications - ZoteroPane.setupSyncReminders(false); + ZoteroPane.initSyncReminders(false); }; let remindMeLink = document.getElementById('sync-reminder-remind'); - remindMeLink.textContent = Zotero.getString('sync.reminder.remindMeLater'); + remindMeLink.textContent = Zotero.getString('general.remindMeLater'); remindMeLink.onclick = function () { closePanel(); }; diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties index c8cb628187..f2154e36ee 100644 --- a/chrome/locale/en-US/zotero/zotero.properties +++ b/chrome/locale/en-US/zotero/zotero.properties @@ -3,7 +3,6 @@ extensions.zotero@chnm.gmu.edu.description = The Next-Generation Research Tool general.success = Success general.error = Error general.warning = Warning -general.dontAskMeAgain = Don't ask me again general.dontShowWarningAgain = Don't show this warning again. general.dontShowAgainFor = Don’t show again today;Don’t show again for %1$S days general.browserIsOffline = %S is currently in offline mode. @@ -65,7 +64,9 @@ general.numMore = %S more… general.openPreferences = Open Preferences general.keys.ctrlShift = Ctrl+Shift+ general.keys.cmdShift = Cmd+Shift+ -general.dontShowAgain = Don’t Show Again +general.dontShowAgain = Don’t Show Again +general.dontAskAgain = Don’t Ask Again +general.remindMeLater = Remind Me Later general.fix = Fix… general.tryAgain = Try Again general.tryLater = Try Later @@ -994,11 +995,10 @@ sync.resetGroupFilesAndSync = Reset Group Files and Sync sync.skipGroup = Skip Group sync.removeGroupsAndSync = Remove Groups and Sync -sync.reminder.setup.message = Back up your library with Zotero syncing. -sync.reminder.setup.action = Set Up Syncing -sync.reminder.autoSync.message = Zotero can automatically sync after you make changes. +sync.reminder.setUp.message = Back up your library with %S syncing. +sync.reminder.setUp.action = Set Up Syncing +sync.reminder.autoSync.message = %S can automatically sync after you make changes. sync.reminder.autoSync.action = Enable Automatic Sync -sync.reminder.remindMeLater = Remind Me Later sync.error.usernameNotSet = Username not set sync.error.usernameNotSet.text = You must enter your zotero.org username and password in the Zotero preferences to sync with the Zotero server. diff --git a/defaults/preferences/zotero.js b/defaults/preferences/zotero.js index db39bd87e3..cf72994e82 100644 --- a/defaults/preferences/zotero.js +++ b/defaults/preferences/zotero.js @@ -160,10 +160,10 @@ pref("extensions.zotero.sync.storage.groups.enabled", true); pref("extensions.zotero.sync.storage.downloadMode.personal", "on-sync"); pref("extensions.zotero.sync.storage.downloadMode.groups", "on-sync"); pref("extensions.zotero.sync.fulltext.enabled", true); -pref("extensions.zotero.sync.reminder.setup.enabled", true); -pref("extensions.zotero.sync.reminder.setup.lastDisplayed", "0"); +pref("extensions.zotero.sync.reminder.setUp.enabled", true); +pref("extensions.zotero.sync.reminder.setUp.lastDisplayed", 0); pref("extensions.zotero.sync.reminder.autoSync.enabled", true); -pref("extensions.zotero.sync.reminder.autoSync.lastDisplayed", "0"); +pref("extensions.zotero.sync.reminder.autoSync.lastDisplayed", 0); // Proxy pref("extensions.zotero.proxies.autoRecognize", true); From 706233c9746cb8ef990bd5eb415b39b2a136e6f1 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Wed, 2 Mar 2022 05:05:50 -0500 Subject: [PATCH 3/3] Sync reminders changes (#2354) - Adjust text - Add "Learn More" button with link to sync documentation for set-up-sync notification - Show "Don't Show Again" for set-up-sync even on first display - Don't perform any action when clicking unlinked text - Use yellow/orange background instead of blue for notification bar - Prevent text from wrapping out of the bar at narrow window widths - Use local variable for observer id --- chrome/content/zotero/zoteroPane.js | 59 ++++++++++++-------- chrome/content/zotero/zoteroPane.xul | 1 + chrome/locale/en-US/zotero/zotero.properties | 4 +- chrome/skin/default/zotero/overlay.css | 12 +++- resource/config.js | 1 + 5 files changed, 49 insertions(+), 28 deletions(-) diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js index 4f0364ff9c..25828e8e5e 100644 --- a/chrome/content/zotero/zoteroPane.js +++ b/chrome/content/zotero/zoteroPane.js @@ -356,8 +356,8 @@ var ZoteroPane = new function() if(this.collectionsView) this.collectionsView.unregister(); if(this.itemsView) this.itemsView.unregister(); - if (this._syncRemindersObserverID) { - Zotero.Notifier.unregisterObserver(this._syncRemindersObserverID); + if (_syncRemindersObserverID) { + Zotero.Notifier.unregisterObserver(_syncRemindersObserverID); } this.uninitContainers(); @@ -2265,7 +2265,7 @@ var ZoteroPane = new function() }; - this._syncRemindersObserverID = null; + var _syncRemindersObserverID = null; this.initSyncReminders = function (startup) { if (startup) { Zotero.Notifier.registerObserver( @@ -2289,29 +2289,29 @@ var ZoteroPane = new function() // If both reminders are disabled, we don't need an observer if (!Zotero.Prefs.get('sync.reminder.setUp.enabled') && !Zotero.Prefs.get('sync.reminder.autoSync.enabled')) { - if (this._syncRemindersObserverID) { - Zotero.Notifier.unregisterObserver(this._syncRemindersObserverID); - this._syncRemindersObserverID = null; + if (_syncRemindersObserverID) { + Zotero.Notifier.unregisterObserver(_syncRemindersObserverID); + _syncRemindersObserverID = null; } return; } // If we are syncing and auto-syncing then no need for observer if (Zotero.Sync.Runner.enabled && Zotero.Prefs.get('sync.autoSync')) { - if (this._syncRemindersObserverID) { - Zotero.Notifier.unregisterObserver(this._syncRemindersObserverID); - this._syncRemindersObserverID = null; + if (_syncRemindersObserverID) { + Zotero.Notifier.unregisterObserver(_syncRemindersObserverID); + _syncRemindersObserverID = null; } return; } // If we already have an observer don't add another one - if (this._syncRemindersObserverID) { + if (_syncRemindersObserverID) { return; } const eventTypes = ['add', 'modify', 'delete']; - this._syncRemindersObserverID = Zotero.Notifier.registerObserver( + _syncRemindersObserverID = Zotero.Notifier.registerObserver( { notify: (event) => { if (!eventTypes.includes(event)) { @@ -2345,8 +2345,7 @@ var ZoteroPane = new function() return; } - // When we have not seen the first warning, hide the checkbox - this.showSyncReminder('setUp', lastDisplayed === 0); + this.showSyncReminder('setUp', { learnMoreURL: ZOTERO_CONFIG.SYNC_INFO_URL }); }; @@ -2372,18 +2371,19 @@ var ZoteroPane = new function() if (lastDisplayed > Math.round(Date.now() / 1000) - sevenDays) { return; } - - this.showSyncReminder('autoSync', false); + + this.showSyncReminder('autoSync'); }; /** * Configure the UI and show the sync reminder panel for a given type of reminder * - * @param reminderType - Possible values: 'setUp' or 'autoSync' - * @param hideDisable - True if the 'Don't show again' link is hidden + * @param {String} reminderType - Possible values: 'setUp' or 'autoSync' + * @param {Object} [options] + * @param {String} [options.learnMoreURL] - Show "Learn More" link to this URL */ - this.showSyncReminder = function (reminderType, hideDisable) { + this.showSyncReminder = function (reminderType, options = {}) { if (!['setUp', 'autoSync'].includes(reminderType)) { throw new Error(`Invalid reminder type: ${reminderType}`); } @@ -2396,13 +2396,18 @@ var ZoteroPane = new function() let message = document.getElementById('sync-reminder-message'); message.textContent = Zotero.getString(`sync.reminder.${reminderType}.message`, Zotero.appName); - message.onclick = function () { - closePanel(); - Zotero.Utilities.Internal.openPreferences('zotero-prefpane-sync'); - }; let actionLink = document.getElementById('sync-reminder-action'); - actionLink.textContent = Zotero.getString(`sync.reminder.${reminderType}.action`); + switch (reminderType) { + case 'autoSync': + var actionStr = Zotero.getString('general.enable'); + break; + + default: + var actionStr = Zotero.getString(`sync.reminder.${reminderType}.action`); + break; + } + actionLink.textContent = actionStr; actionLink.onclick = function () { closePanel(); @@ -2416,9 +2421,15 @@ var ZoteroPane = new function() } }; + let learnMoreLink = document.getElementById('sync-reminder-learn-more'); + learnMoreLink.textContent = Zotero.getString('general.learnMore'); + learnMoreLink.hidden = !options.learnMoreURL; + learnMoreLink.onclick = function () { + Zotero.launchURL(options.learnMoreURL); + }; + let dontShowAgainLink = document.getElementById('sync-reminder-disable'); dontShowAgainLink.textContent = Zotero.getString('general.dontAskAgain'); - dontShowAgainLink.hidden = hideDisable; dontShowAgainLink.onclick = function () { closePanel(); Zotero.Prefs.set(`sync.reminder.${reminderType}.enabled`, false); diff --git a/chrome/content/zotero/zoteroPane.xul b/chrome/content/zotero/zoteroPane.xul index a613d937fe..2a1e2ca556 100644 --- a/chrome/content/zotero/zoteroPane.xul +++ b/chrome/content/zotero/zoteroPane.xul @@ -240,6 +240,7 @@
+
diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties index f2154e36ee..b0f9cae3f8 100644 --- a/chrome/locale/en-US/zotero/zotero.properties +++ b/chrome/locale/en-US/zotero/zotero.properties @@ -49,6 +49,7 @@ general.import = Import general.export = Export general.update = Update general.moreInformation = More Information +general.learnMore = Learn More general.seeForMoreInformation = See %S for more information. general.open = Open %S general.close = Close @@ -997,8 +998,7 @@ sync.removeGroupsAndSync = Remove Groups and Sync sync.reminder.setUp.message = Back up your library with %S syncing. sync.reminder.setUp.action = Set Up Syncing -sync.reminder.autoSync.message = %S can automatically sync after you make changes. -sync.reminder.autoSync.action = Enable Automatic Sync +sync.reminder.autoSync.message = %S hasn’t synced in a while. Do you want to enable automatic syncing? sync.error.usernameNotSet = Username not set sync.error.usernameNotSet.text = You must enter your zotero.org username and password in the Zotero preferences to sync with the Zotero server. diff --git a/chrome/skin/default/zotero/overlay.css b/chrome/skin/default/zotero/overlay.css index e505ebb6d2..cf0d0cbc29 100644 --- a/chrome/skin/default/zotero/overlay.css +++ b/chrome/skin/default/zotero/overlay.css @@ -646,10 +646,14 @@ text-align: center; padding: 0 2em; position: relative; + white-space: nowrap; + overflow: hidden; } #sync-reminder-banner { - background: rgb(89, 139, 236); + background: rgb(255, 234, 80); + border-bottom: #a9a9a9 .5px solid; + color: black; } #retracted-items-message, #sync-reminder-message { @@ -673,10 +677,14 @@ padding-right: 0.5em; } -#retracted-items-link:active, .sync-reminder-link:active { +#retracted-items-link:active { color: #f9e8e2; } +.sync-reminder-link:active { + color: #4b4b4b; +} + #retracted-items-close, #sync-reminder-close { position: absolute; cursor: pointer; diff --git a/resource/config.js b/resource/config.js index 4a480e3a40..199504a3f1 100644 --- a/resource/config.js +++ b/resource/config.js @@ -21,6 +21,7 @@ var ZOTERO_CONFIG = { QUICK_START_URL: "https://www.zotero.org/support/quick_start_guide", PDF_TOOLS_URL: "https://www.zotero.org/download/xpdf/", SUPPORT_URL: "https://www.zotero.org/support/", + SYNC_INFO_URL: "https://www.zotero.org/support/sync", TROUBLESHOOTING_URL: "https://www.zotero.org/support/getting_help", FEEDBACK_URL: "https://forums.zotero.org/", CONNECTORS_URL: "https://www.zotero.org/download/connectors",