Merge pull request #2354

Add sync reminders
This commit is contained in:
Dan Stillman 2022-03-02 05:25:38 -05:00
commit c0ab16e79d
7 changed files with 267 additions and 8 deletions

View file

@ -252,6 +252,15 @@ Zotero.Prefs = new function(){
else { else {
Zotero.Sync.EventListeners.AutoSyncListener.unregister(); Zotero.Sync.EventListeners.AutoSyncListener.unregister();
Zotero.Sync.EventListeners.IdleListener.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', Math.round(Date.now() / 1000));
}
try {
Zotero.getActiveZoteroPane().initSyncReminders(false);
}
catch (e) {
Zotero.logError(e);
} }
}], }],
[ "search.quicksearch-mode", function(val) { [ "search.quicksearch-mode", function(val) {

View file

@ -229,6 +229,7 @@ var ZoteroPane = new function()
setTimeout(function () { setTimeout(function () {
ZoteroPane.showRetractionBanner(); ZoteroPane.showRetractionBanner();
ZoteroPane.initSyncReminders(true);
}); });
// TEMP: Clean up extra files from Mendeley imports <5.0.51 // 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.collectionsView) this.collectionsView.unregister();
if(this.itemsView) this.itemsView.unregister(); if(this.itemsView) this.itemsView.unregister();
if (_syncRemindersObserverID) {
Zotero.Notifier.unregisterObserver(_syncRemindersObserverID);
}
this.uninitContainers(); this.uninitContainers();
@ -2249,6 +2253,205 @@ 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();
};
var _syncRemindersObserverID = null;
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', 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);
}
}
},
'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 (_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 (_syncRemindersObserverID) {
Zotero.Notifier.unregisterObserver(_syncRemindersObserverID);
_syncRemindersObserverID = null;
}
return;
}
// If we already have an observer don't add another one
if (_syncRemindersObserverID) {
return;
}
const eventTypes = ['add', 'modify', 'delete'];
_syncRemindersObserverID = Zotero.Notifier.registerObserver(
{
notify: (event) => {
if (!eventTypes.includes(event)) {
return;
}
setTimeout(() => {
this.showSetUpSyncReminder();
this.showAutoSyncReminder();
}, 5000);
}
},
'item',
'syncReminder');
};
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;
}
this.showSyncReminder('setUp', { learnMoreURL: ZOTERO_CONFIG.SYNC_INFO_URL });
};
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 7 days
if (!Zotero.Prefs.get('sync.reminder.autoSync.enabled')
|| !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 7+ days ago
let lastDisplayed = Zotero.Prefs.get('sync.reminder.autoSync.lastDisplayed');
if (lastDisplayed > Math.round(Date.now() / 1000) - sevenDays) {
return;
}
this.showSyncReminder('autoSync');
};
/**
* Configure the UI and show the sync reminder panel for a given type of reminder
*
* @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, options = {}) {
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`, Math.round(Date.now() / 1000));
};
let message = document.getElementById('sync-reminder-message');
message.textContent = Zotero.getString(`sync.reminder.${reminderType}.message`, Zotero.appName);
let actionLink = document.getElementById('sync-reminder-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();
switch (reminderType) {
case 'setUp':
Zotero.Utilities.Internal.openPreferences('zotero-prefpane-sync');
break;
case 'autoSync':
Zotero.Prefs.set(`sync.autoSync`, true);
break;
}
};
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.onclick = function () {
closePanel();
Zotero.Prefs.set(`sync.reminder.${reminderType}.enabled`, false);
// Check if we no longer need to observe item modifications
ZoteroPane.initSyncReminders(false);
};
let remindMeLink = document.getElementById('sync-reminder-remind');
remindMeLink.textContent = Zotero.getString('general.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) { this.selectItem = async function (itemID, inLibraryRoot) {
if (!itemID) { if (!itemID) {
return false; return false;

View file

@ -221,7 +221,7 @@
<panel id="zotero-sync-error-panel" type="arrow"/> <panel id="zotero-sync-error-panel" type="arrow"/>
<toolbarbutton id="zotero-tb-sync" class="zotero-tb-button" tooltip="_child" <toolbarbutton id="zotero-tb-sync" class="zotero-tb-button" tooltip="_child"
oncommand="Zotero.Sync.Server.canAutoResetClient = true; Zotero.Sync.Server.manualSyncRequired = false; Zotero.Sync.Runner.sync()"> oncommand="ZoteroPane.sync()">
<tooltip <tooltip
id="zotero-tb-sync-tooltip" id="zotero-tb-sync-tooltip"
onpopupshowing="Zotero.Sync.Runner.registerSyncStatus(this)" onpopupshowing="Zotero.Sync.Runner.registerSyncStatus(this)"
@ -236,6 +236,18 @@
</hbox> </hbox>
</toolbar> </toolbar>
<vbox id="sync-reminder-container" collapsed="true">
<div xmlns="http://www.w3.org/1999/xhtml" id="sync-reminder-banner">
<div id="sync-reminder-message"/>
<a id="sync-reminder-action" class="sync-reminder-link"/>
<a id="sync-reminder-learn-more" class="sync-reminder-link"/>
<div id="sync-reminder-spacer"/>
<a id="sync-reminder-disable" class="sync-reminder-link"/>
<a id="sync-reminder-remind" class="sync-reminder-link"/>
<div id="sync-reminder-close">×</div>
</div>
</vbox>
<vbox id="retracted-items-container" collapsed="true"> <vbox id="retracted-items-container" collapsed="true">
<div xmlns="http://www.w3.org/1999/xhtml" id="retracted-items-banner"> <div xmlns="http://www.w3.org/1999/xhtml" id="retracted-items-banner">
<div id="retracted-items-message"/> <div id="retracted-items-message"/>

View file

@ -49,6 +49,7 @@ general.import = Import
general.export = Export general.export = Export
general.update = Update general.update = Update
general.moreInformation = More Information general.moreInformation = More Information
general.learnMore = Learn More
general.seeForMoreInformation = See %S for more information. general.seeForMoreInformation = See %S for more information.
general.open = Open %S general.open = Open %S
general.close = Close general.close = Close
@ -64,7 +65,9 @@ general.numMore = %S more…
general.openPreferences = Open Preferences general.openPreferences = Open Preferences
general.keys.ctrlShift = Ctrl+Shift+ general.keys.ctrlShift = Ctrl+Shift+
general.keys.cmdShift = Cmd+Shift+ general.keys.cmdShift = Cmd+Shift+
general.dontShowAgain = Dont Show Again general.dontShowAgain = Dont Show Again
general.dontAskAgain = Dont Ask Again
general.remindMeLater = Remind Me Later
general.fix = Fix… general.fix = Fix…
general.tryAgain = Try Again general.tryAgain = Try Again
general.tryLater = Try Later general.tryLater = Try Later
@ -993,6 +996,10 @@ sync.resetGroupFilesAndSync = Reset Group Files and Sync
sync.skipGroup = Skip Group sync.skipGroup = Skip Group
sync.removeGroupsAndSync = Remove Groups and Sync 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 hasnt synced in a while. Do you want to enable automatic syncing?
sync.error.usernameNotSet = Username not set 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.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 sync.error.passwordNotSet = Password not set

View file

@ -533,11 +533,11 @@
} }
/* Sync error panel */ /* Sync error panel */
#zotero-sync-error-panel { #zotero-sync-error-panel, #zotero-sync-reminder-panel {
margin-right: 0; margin-right: 0;
} }
#zotero-sync-error-panel .error-header { #zotero-sync-error-panel .error-header, #zotero-sync-reminder-panel .header {
font-size: 14px; font-size: 14px;
font-weight: bold; font-weight: bold;
margin-bottom: 1em; margin-bottom: 1em;
@ -552,7 +552,7 @@
margin-bottom: 1.1em; margin-bottom: 1.1em;
} }
#zotero-sync-error-panel description { #zotero-sync-error-panel description, #zotero-sync-reminder-panel description {
width: 370px; width: 370px;
white-space: pre-wrap; white-space: pre-wrap;
} }
@ -635,7 +635,7 @@
margin-left: 3px !important; margin-left: 3px !important;
} }
#retracted-items-banner { #retracted-items-banner, #sync-reminder-banner {
display: flex; display: flex;
justify-content: center; justify-content: center;
background: #d93425; background: #d93425;
@ -646,23 +646,46 @@
text-align: center; text-align: center;
padding: 0 2em; padding: 0 2em;
position: relative; position: relative;
white-space: nowrap;
overflow: hidden;
} }
#retracted-items-message { #sync-reminder-banner {
background: rgb(255, 234, 80);
border-bottom: #a9a9a9 .5px solid;
color: black;
}
#retracted-items-message, #sync-reminder-message {
margin-right: .8em; margin-right: .8em;
} }
#sync-reminder-spacer {
flex: 1;
}
#retracted-items-link { #retracted-items-link {
text-decoration: underline; text-decoration: underline;
margin-left: .3em; margin-left: .3em;
cursor: pointer; cursor: pointer;
} }
.sync-reminder-link {
text-decoration: underline;
cursor: pointer;
padding-left: 0.5em;
padding-right: 0.5em;
}
#retracted-items-link:active { #retracted-items-link:active {
color: #f9e8e2; color: #f9e8e2;
} }
#retracted-items-close { .sync-reminder-link:active {
color: #4b4b4b;
}
#retracted-items-close, #sync-reminder-close {
position: absolute; position: absolute;
cursor: pointer; cursor: pointer;
top: -2px; top: -2px;

View file

@ -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.personal", "on-sync");
pref("extensions.zotero.sync.storage.downloadMode.groups", "on-sync"); pref("extensions.zotero.sync.storage.downloadMode.groups", "on-sync");
pref("extensions.zotero.sync.fulltext.enabled", true); 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 // Proxy
pref("extensions.zotero.proxies.autoRecognize", true); pref("extensions.zotero.proxies.autoRecognize", true);

View file

@ -21,6 +21,7 @@ var ZOTERO_CONFIG = {
QUICK_START_URL: "https://www.zotero.org/support/quick_start_guide", QUICK_START_URL: "https://www.zotero.org/support/quick_start_guide",
PDF_TOOLS_URL: "https://www.zotero.org/download/xpdf/", PDF_TOOLS_URL: "https://www.zotero.org/download/xpdf/",
SUPPORT_URL: "https://www.zotero.org/support/", 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", TROUBLESHOOTING_URL: "https://www.zotero.org/support/getting_help",
FEEDBACK_URL: "https://forums.zotero.org/", FEEDBACK_URL: "https://forums.zotero.org/",
CONNECTORS_URL: "https://www.zotero.org/download/connectors", CONNECTORS_URL: "https://www.zotero.org/download/connectors",