Page MenuHomePhabricator

D15961.diff
No OneTemporary

D15961.diff

diff --git a/resources/celerity/packages.php b/resources/celerity/packages.php
--- a/resources/celerity/packages.php
+++ b/resources/celerity/packages.php
@@ -81,6 +81,7 @@
'javelin-behavior-scrollbar',
'javelin-behavior-durable-column',
'conpherence-thread-manager',
+ 'javelin-behavior-detect-timezone',
),
'core.pkg.css' => array(
'phabricator-core-css',
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -3355,6 +3355,7 @@
'PhabricatorSettingsMainController' => 'applications/settings/controller/PhabricatorSettingsMainController.php',
'PhabricatorSettingsMainMenuBarExtension' => 'applications/settings/extension/PhabricatorSettingsMainMenuBarExtension.php',
'PhabricatorSettingsPanel' => 'applications/settings/panel/PhabricatorSettingsPanel.php',
+ 'PhabricatorSettingsTimezoneController' => 'applications/settings/controller/PhabricatorSettingsTimezoneController.php',
'PhabricatorSetupCheck' => 'applications/config/check/PhabricatorSetupCheck.php',
'PhabricatorSetupCheckTestCase' => 'applications/config/check/__tests__/PhabricatorSetupCheckTestCase.php',
'PhabricatorSetupIssue' => 'applications/config/issue/PhabricatorSetupIssue.php',
@@ -8065,6 +8066,7 @@
'PhabricatorSettingsMainController' => 'PhabricatorController',
'PhabricatorSettingsMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension',
'PhabricatorSettingsPanel' => 'Phobject',
+ 'PhabricatorSettingsTimezoneController' => 'PhabricatorController',
'PhabricatorSetupCheck' => 'Phobject',
'PhabricatorSetupCheckTestCase' => 'PhabricatorTestCase',
'PhabricatorSetupIssue' => 'Phobject',
diff --git a/src/applications/people/storage/PhabricatorUser.php b/src/applications/people/storage/PhabricatorUser.php
--- a/src/applications/people/storage/PhabricatorUser.php
+++ b/src/applications/people/storage/PhabricatorUser.php
@@ -755,6 +755,17 @@
return new DateTimeZone($this->getTimezoneIdentifier());
}
+ public function getTimeZoneOffset() {
+ $timezone = $this->getTimeZone();
+ $now = new DateTime('@'.PhabricatorTime::getNow());
+ $offset = $timezone->getOffset($now);
+
+ // Javascript offsets are in minutes and have the opposite sign.
+ $offset = -(int)($offset / 60);
+
+ return $offset;
+ }
+
public function formatShortDateTime($when, $now = null) {
if ($now === null) {
$now = PhabricatorTime::getNow();
diff --git a/src/applications/settings/application/PhabricatorSettingsApplication.php b/src/applications/settings/application/PhabricatorSettingsApplication.php
--- a/src/applications/settings/application/PhabricatorSettingsApplication.php
+++ b/src/applications/settings/application/PhabricatorSettingsApplication.php
@@ -32,6 +32,8 @@
'(?:(?P<id>\d+)/)?(?:panel/(?P<key>[^/]+)/)?'
=> 'PhabricatorSettingsMainController',
'adjust/' => 'PhabricatorSettingsAdjustController',
+ 'timezone/(?P<offset>[^/]+)/'
+ => 'PhabricatorSettingsTimezoneController',
),
);
}
diff --git a/src/applications/settings/controller/PhabricatorSettingsTimezoneController.php b/src/applications/settings/controller/PhabricatorSettingsTimezoneController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/settings/controller/PhabricatorSettingsTimezoneController.php
@@ -0,0 +1,108 @@
+<?php
+
+final class PhabricatorSettingsTimezoneController
+ extends PhabricatorController {
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $this->getViewer();
+
+ $client_offset = $request->getURIData('offset');
+ $client_offset = (int)$client_offset;
+
+ $timezones = DateTimeZone::listIdentifiers();
+ $now = new DateTime('@'.PhabricatorTime::getNow());
+
+ $options = array(
+ 'ignore' => pht('Ignore Conflict'),
+ );
+
+ foreach ($timezones as $identifier) {
+ $zone = new DateTimeZone($identifier);
+ $offset = -($zone->getOffset($now) / 60);
+ if ($offset == $client_offset) {
+ $options[$identifier] = $identifier;
+ }
+ }
+
+ $settings_help = pht(
+ 'You can change your date and time preferences in Settings.');
+
+ if ($request->isFormPost()) {
+ $timezone = $request->getStr('timezone');
+
+ $pref_ignore = PhabricatorUserPreferences::PREFERENCE_IGNORE_OFFSET;
+
+ $preferences = $viewer->loadPreferences();
+
+ if ($timezone == 'ignore') {
+ $preferences
+ ->setPreference($pref_ignore, $client_offset)
+ ->save();
+
+ return $this->newDialog()
+ ->setTitle(pht('Conflict Ignored'))
+ ->appendParagraph(
+ pht(
+ 'The conflict between your browser and profile timezone '.
+ 'settings will be ignored.'))
+ ->appendParagraph($settings_help)
+ ->addCancelButton('/', pht('Done'));
+ }
+
+ if (isset($options[$timezone])) {
+ $preferences
+ ->setPreference($pref_ignore, null)
+ ->save();
+
+ $viewer
+ ->setTimezoneIdentifier($timezone)
+ ->save();
+ }
+ }
+
+ $server_offset = $viewer->getTimeZoneOffset();
+
+ if ($client_offset == $server_offset) {
+ return $this->newDialog()
+ ->setTitle(pht('Timezone Calibrated'))
+ ->appendParagraph(
+ pht(
+ 'Your browser timezone and profile timezone are now '.
+ 'in agreement (%s).',
+ $this->formatOffset($client_offset)))
+ ->appendParagraph($settings_help)
+ ->addCancelButton('/', pht('Done'));
+ }
+
+ $form = id(new AphrontFormView())
+ ->appendChild(
+ id(new AphrontFormSelectControl())
+ ->setName('timezone')
+ ->setLabel(pht('Timezone'))
+ ->setOptions($options));
+
+ return $this->newDialog()
+ ->setTitle(pht('Adjust Timezone'))
+ ->appendParagraph(
+ pht(
+ 'Your browser timezone (%s) differs from your profile timezone '.
+ '(%s). You can ignore this conflict or adjust your profile setting '.
+ 'to match your client.',
+ $this->formatOffset($client_offset),
+ $this->formatOffset($server_offset)))
+ ->appendForm($form)
+ ->addCancelButton(pht('Cancel'))
+ ->addSubmitButton(pht('Submit'));
+ }
+
+ private function formatOffset($offset) {
+ $offset = $offset / 60;
+
+ if ($offset >= 0) {
+ return pht('GMT-%d', $offset);
+ } else {
+ return pht('GMT+%d', -$offset);
+ }
+ }
+
+}
diff --git a/src/applications/settings/panel/PhabricatorDateTimeSettingsPanel.php b/src/applications/settings/panel/PhabricatorDateTimeSettingsPanel.php
--- a/src/applications/settings/panel/PhabricatorDateTimeSettingsPanel.php
+++ b/src/applications/settings/panel/PhabricatorDateTimeSettingsPanel.php
@@ -21,6 +21,7 @@
$pref_time = PhabricatorUserPreferences::PREFERENCE_TIME_FORMAT;
$pref_date = PhabricatorUserPreferences::PREFERENCE_DATE_FORMAT;
$pref_week_start = PhabricatorUserPreferences::PREFERENCE_WEEK_START_DAY;
+ $pref_ignore = PhabricatorUserPreferences::PREFERENCE_IGNORE_OFFSET;
$preferences = $user->loadPreferences();
$errors = array();
@@ -41,7 +42,8 @@
$request->getStr($pref_date))
->setPreference(
$pref_week_start,
- $request->getStr($pref_week_start));
+ $request->getStr($pref_week_start))
+ ->setPreference($pref_ignore, null);
if (!$errors) {
$preferences->save();
diff --git a/src/applications/settings/storage/PhabricatorUserPreferences.php b/src/applications/settings/storage/PhabricatorUserPreferences.php
--- a/src/applications/settings/storage/PhabricatorUserPreferences.php
+++ b/src/applications/settings/storage/PhabricatorUserPreferences.php
@@ -43,6 +43,7 @@
const PREFERENCE_PROFILE_MENU_COLLAPSED = 'profile-menu.collapsed';
const PREFERENCE_FAVORITE_POLICIES = 'policy.favorites';
+ const PREFERENCE_IGNORE_OFFSET = 'time.offset.ignore';
// These are in an unusual order for historic reasons.
const MAILTAG_PREFERENCE_NOTIFY = 0;
diff --git a/src/view/page/PhabricatorStandardPageView.php b/src/view/page/PhabricatorStandardPageView.php
--- a/src/view/page/PhabricatorStandardPageView.php
+++ b/src/view/page/PhabricatorStandardPageView.php
@@ -223,6 +223,30 @@
}
if ($user) {
+ if ($user->isLoggedIn()) {
+ $offset = $user->getTimeZoneOffset();
+
+ $preferences = $user->loadPreferences();
+ $ignore_key = PhabricatorUserPreferences::PREFERENCE_IGNORE_OFFSET;
+
+ $ignore = $preferences->getPreference($ignore_key);
+ if (!strlen($ignore)) {
+ $ignore = null;
+ }
+
+ Javelin::initBehavior(
+ 'detect-timezone',
+ array(
+ 'offset' => $offset,
+ 'uri' => '/settings/timezone/',
+ 'message' => pht(
+ 'Your browser timezone setting differs from the timezone '.
+ 'setting in your profile.'),
+ 'ignoreKey' => $ignore_key,
+ 'ignore' => $ignore,
+ ));
+ }
+
$default_img_uri =
celerity_get_resource_uri(
'rsrc/image/icon/fatcow/document_black.png');
diff --git a/webroot/rsrc/js/core/behavior-detect-timezone.js b/webroot/rsrc/js/core/behavior-detect-timezone.js
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/js/core/behavior-detect-timezone.js
@@ -0,0 +1,53 @@
+/**
+ * @provides javelin-behavior-detect-timezone
+ * @requires javelin-behavior
+ * javelin-uri
+ * phabricator-notification
+ */
+
+JX.behavior('detect-timezone', function(config) {
+
+ var offset = new Date().getTimezoneOffset();
+ var ignore = config.ignore;
+
+ if (ignore !== null) {
+ // If we're ignoring a client offset and it's the current offset, just
+ // bail. This means the user has chosen to ignore the clock difference
+ // between the current client setting and their server setting.
+ if (offset == ignore) {
+ return;
+ }
+
+ // If we're ignoring a client offset but the current offset is different,
+ // wipe the offset. If you go from SF to NY, ignore the difference, return
+ // to SF, then travel back to NY a few months later, we want to prompt you
+ // again. This code will clear the ignored setting upon your return to SF.
+ new JX.Request('/settings/adjust/', JX.bag)
+ .setData({key: config.ignoreKey, value: ''})
+ .send();
+
+ ignore = null;
+ }
+
+ // If the client and server clocks are in sync, we're all set.
+ if (offset == config.offset) {
+ return;
+ }
+
+ var notification = new JX.Notification()
+ .alterClassName('jx-notification-alert', true)
+ .setContent(config.message)
+ .setDuration(0);
+
+ notification.listen('activate', function() {
+ JX.Stratcom.context().kill();
+ notification.hide();
+
+ var uri = config.uri + offset + '/';
+
+ new JX.Workflow(uri)
+ .start();
+ });
+
+ notification.show();
+});

File Metadata

Mime Type
text/plain
Expires
Thu, May 16, 1:23 AM (2 w, 3 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6285496
Default Alt Text
D15961.diff (10 KB)

Event Timeline