diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/Command/Db/AddMissingIndices.php | 91 | ||||
-rw-r--r-- | core/Command/Maintenance/Repair.php | 2 | ||||
-rw-r--r-- | core/Command/Maintenance/UpdateTheme.php | 2 | ||||
-rw-r--r-- | core/Controller/LoginController.php | 1 | ||||
-rw-r--r-- | core/Migrations/Version13000Date20170718121200.php | 1 | ||||
-rw-r--r-- | core/css/fixes.scss | 7 | ||||
-rw-r--r-- | core/css/header.scss | 14 | ||||
-rw-r--r-- | core/css/mobile.scss | 2 | ||||
-rw-r--r-- | core/css/styles.scss | 16 | ||||
-rw-r--r-- | core/js/jquery.avatar.js | 77 | ||||
-rw-r--r-- | core/js/lostpassword.js | 1 | ||||
-rw-r--r-- | core/js/placeholder.js | 5 | ||||
-rw-r--r-- | core/js/tests/specs/jquery.avatarSpec.js | 137 | ||||
-rw-r--r-- | core/register_command.php | 1 | ||||
-rw-r--r-- | core/templates/login.php | 2 |
15 files changed, 213 insertions, 146 deletions
diff --git a/core/Command/Db/AddMissingIndices.php b/core/Command/Db/AddMissingIndices.php new file mode 100644 index 00000000000..314bed8ccb1 --- /dev/null +++ b/core/Command/Db/AddMissingIndices.php @@ -0,0 +1,91 @@ +<?php +/** + * @copyright Copyright (c) 2017 Bjoern Schiessle <bjoern@schiessle.org> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + + +namespace OC\Core\Command\Db; + +use OC\DB\SchemaWrapper; +use OCP\IDBConnection; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Class AddMissingIndices + * + * if you added any new indices to the database, this is the right place to add + * it your update routine for existing instances + * + * @package OC\Core\Command\Db + */ +class AddMissingIndices extends Command { + + /** @var IDBConnection */ + private $connection; + + /** + * @param IDBConnection $connection + */ + public function __construct(IDBConnection $connection) { + $this->connection = $connection; + parent::__construct(); + } + + protected function configure() { + $this + ->setName('db:add-missing-indices') + ->setDescription('Add missing indices to the database tables'); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $this->addShareTableIndicies($output); + + } + + /** + * add missing indices to the share table + * + * @param OutputInterface $output + * @throws \Doctrine\DBAL\Schema\SchemaException + */ + private function addShareTableIndicies(OutputInterface $output) { + + $output->writeln('<info>Check indices of the share table.</info>'); + + $schema = new SchemaWrapper($this->connection); + $updated = false; + + if ($schema->hasTable("share")) { + $table = $schema->getTable("share"); + if (!$table->hasIndex('share_with_index')) { + $output->writeln('<info>Adding additional index to the share table, this can take some time...</info>'); + $table->addIndex(['share_with'], 'share_with_index'); + $this->connection->migrateToSchema($schema->getWrappedSchema()); + $updated = true; + $output->writeln('<info>Share table updated successfully.</info>'); + } + } + + if (!$updated) { + $output->writeln('<info>Done.</info>'); + } + } +} diff --git a/core/Command/Maintenance/Repair.php b/core/Command/Maintenance/Repair.php index 9401dafd26b..71d13cd29f3 100644 --- a/core/Command/Maintenance/Repair.php +++ b/core/Command/Maintenance/Repair.php @@ -86,7 +86,7 @@ class Repair extends Command { $apps = $this->appManager->getInstalledApps(); foreach ($apps as $app) { - if (!$appManager->isEnabledForUser($app)) { + if (!$this->appManager->isEnabledForUser($app)) { continue; } $info = \OC_App::getAppInfo($app); diff --git a/core/Command/Maintenance/UpdateTheme.php b/core/Command/Maintenance/UpdateTheme.php index cf015b82635..2ab66a4ce75 100644 --- a/core/Command/Maintenance/UpdateTheme.php +++ b/core/Command/Maintenance/UpdateTheme.php @@ -57,7 +57,7 @@ class UpdateTheme extends UpdateJS { parent::execute($input, $output); // cleanup image cache - $c = $this->cacheFactory->create('imagePath'); + $c = $this->cacheFactory->createDistributed('imagePath'); $c->clear(''); $output->writeln('<info>Image cache cleared'); } diff --git a/core/Controller/LoginController.php b/core/Controller/LoginController.php index e87e097e423..e53095a7de7 100644 --- a/core/Controller/LoginController.php +++ b/core/Controller/LoginController.php @@ -179,6 +179,7 @@ class LoginController extends Controller { $parameters['alt_login'] = OC_App::getAlternativeLogIns(); $parameters['rememberLoginState'] = !empty($remember_login) ? $remember_login : 0; + $parameters['hideRemeberLoginState'] = !empty($redirect_url) && $this->session->exists('client.flow.state.token'); if (!is_null($user) && $user !== '') { $parameters['loginName'] = $user; diff --git a/core/Migrations/Version13000Date20170718121200.php b/core/Migrations/Version13000Date20170718121200.php index 0ab777f6de2..e71debfcb4b 100644 --- a/core/Migrations/Version13000Date20170718121200.php +++ b/core/Migrations/Version13000Date20170718121200.php @@ -400,6 +400,7 @@ class Version13000Date20170718121200 extends SimpleMigrationStep { $table->addIndex(['item_type', 'share_type'], 'item_share_type_index'); $table->addIndex(['file_source'], 'file_source_index'); $table->addIndex(['token'], 'token_index'); + $table->addIndex(['share_with'], 'share_with_index'); } if (!$schema->hasTable('jobs')) { diff --git a/core/css/fixes.scss b/core/css/fixes.scss index 3cb89c6599f..0303b4d751a 100644 --- a/core/css/fixes.scss +++ b/core/css/fixes.scss @@ -16,3 +16,10 @@ select { visibility: hidden; } +.ie #header .menu, +.ie .header-left #navigation, +.ie .ui-datepicker, +.ie .ui-timepicker.ui-widget, +.ie #appmenu li span { + box-shadow: 0 1px 10px $color-box-shadow; +} diff --git a/core/css/header.scss b/core/css/header.scss index 21305de0d02..b38c0bcb401 100644 --- a/core/css/header.scss +++ b/core/css/header.scss @@ -76,13 +76,16 @@ .menu { top: 45px; background-color: $color-main-background; - filter: drop-shadow(0 1px 3px $color-box-shadow); + filter: drop-shadow(0 1px 10px $color-box-shadow); border-radius: 0 0 3px 3px; - display: none; box-sizing: border-box; z-index: 2000; position: absolute; + &:not(.popovermenu) { + display: none; + } + /* Dropdown arrow */ &:after { border: 10px solid transparent; @@ -210,7 +213,7 @@ nav { left: -100%; width: 160px; background-color: $color-main-background; - filter: drop-shadow(0 1px 3px $color-box-shadow); + filter: drop-shadow(0 1px 10px $color-box-shadow); &:after { /* position of dropdown arrow */ left: 47%; @@ -408,7 +411,6 @@ nav { #expanddiv { right: 13px; background: $color-main-background; - box-shadow: 0 1px 10px $color-box-shadow; &:after { /* position of dropdown arrow */ right: 13px; @@ -483,7 +485,7 @@ nav { display: none; position: absolute; overflow: visible; - background-color: rgba($color-main-background, .97); + background-color: $color-main-background; white-space: nowrap; border: none; border-radius: $border-radius; @@ -496,7 +498,7 @@ nav { top: 45px; transform: translateX(-50%); padding: 4px 10px; - box-shadow: 0 1px 10px $color-box-shadow; + filter: drop-shadow(0 1px 10px $color-box-shadow); } li:hover span { diff --git a/core/css/mobile.scss b/core/css/mobile.scss index 19518479987..6f1583cb77a 100644 --- a/core/css/mobile.scss +++ b/core/css/mobile.scss @@ -83,9 +83,7 @@ /* position controls for apps with app-navigation */ #app-navigation+#app-content #controls { - left: 0 !important; padding-left: 44px; - width: 100%; } /* .viewer-mode is when text editor, PDF viewer, etc is open */ diff --git a/core/css/styles.scss b/core/css/styles.scss index 5474b41a2b4..1b76e3c68de 100644 --- a/core/css/styles.scss +++ b/core/css/styles.scss @@ -223,29 +223,23 @@ body { #controls { box-sizing: border-box; - position: fixed; - top: 45px; - right: 0; - left: 0; + position: -webkit-sticky; + position: sticky; height: 44px; - width: calc(100% - 250px); padding: 0; margin: 0; background-color: rgba($color-main-background, 0.95); - z-index: 50; + z-index: 55; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; - display: inline-flex; + display: flex; + top: 0; } /* position controls for apps with app-navigation */ -#app-navigation + #app-content #controls { - left: 250px; -} - .viewer-mode #app-navigation + #app-content #controls { left: 0; } diff --git a/core/js/jquery.avatar.js b/core/js/jquery.avatar.js index 54518c75cc7..958f0f9edd7 100644 --- a/core/js/jquery.avatar.js +++ b/core/js/jquery.avatar.js @@ -106,54 +106,39 @@ }); } - // If the displayname is not defined we use the old code path - if (typeof(displayname) === 'undefined') { - $.get(url).always(function(result, status) { - // if there is an error or an object returned (contains user information): - // -> show the fallback placeholder - if (typeof(result) === 'object' || status === 'error') { - if (!hidedefault) { - if (result.data && result.data.displayname) { - $div.imageplaceholder(user, result.data.displayname); - } else { - // User does not exist - setAvatarForUnknownUser($div); - } - } else { - $div.hide(); - } - // else an image is transferred and should be shown - } else { - $div.show(); - if (ie8fix === true) { - $div.html('<img width="' + size + '" height="' + size + '" src="'+url+'#'+Math.floor(Math.random()*1000)+'" alt="">'); - } else { - $div.html('<img width="' + size + '" height="' + size + '" src="'+url+'" alt="">'); - } - } - if(typeof callback === 'function') { - callback(); - } - }); - } else { - // We already have the displayname so set the placeholder (to show at least something) - if (!hidedefault) { - $div.imageplaceholder(displayname); - } + var img = new Image(); + + // If the new image loads successfully set it. + img.onload = function() { + $div.text(''); + $div.append(img); + $div.clearimageplaceholder(); - var img = new Image(); + if(typeof callback === 'function') { + callback(); + } + }; + // Fallback when avatar loading fails: + // Use old placeholder when a displayname attribute is defined, + // otherwise show the unknown user placeholder. + img.onerror = function () { + $div.clearimageplaceholder(); + if (typeof(displayname) !== 'undefined') { + $div.imageplaceholder(user, displayname); + } else { + setAvatarForUnknownUser($div); + $div.removeClass('icon-loading'); + } - // If the new image loads successfully set it. - img.onload = function() { - $div.show(); - $div.text(''); - $div.append(img); - $div.clearimageplaceholder(); - }; + if(typeof callback === 'function') { + callback(); + } + }; - img.width = size; - img.height = size; - img.src = url; - } + $div.addClass('icon-loading'); + $div.show(); + img.width = size; + img.height = size; + img.src = url; }; }(jQuery)); diff --git a/core/js/lostpassword.js b/core/js/lostpassword.js index 446d70d991e..b44962f552e 100644 --- a/core/js/lostpassword.js +++ b/core/js/lostpassword.js @@ -16,6 +16,7 @@ OC.Lostpassword = { $('#lost-password').click(OC.Lostpassword.resetLink); $('#lost-password-back').click(OC.Lostpassword.backToLogin); $('form[name=login]').submit(OC.Lostpassword.onSendLink); + $('#reset-password #submit').click(OC.Lostpassword.resetPassword); OC.Lostpassword.resetButtons(); }, diff --git a/core/js/placeholder.js b/core/js/placeholder.js index f173e738676..5cf7b9095ad 100644 --- a/core/js/placeholder.js +++ b/core/js/placeholder.js @@ -2,7 +2,7 @@ * ownCloud * * @author John Molakvoæ - * @copyright 2016 John Molakvoæ <fremulon@protonmail.com> + * @copyright 2016-2017 John Molakvoæ <skjnldsv@protonmail.com> * @author Morris Jobke * @copyright 2013 Morris Jobke <morris.jobke@gmail.com> * @@ -47,7 +47,7 @@ * <div id="albumart" style="background-color: hsl(123, 90%, 65%); ... ">A</div> * */ - + /* * Alternatively, you can use the prototype function to convert your string to hsl colors: * @@ -156,5 +156,6 @@ this.css('text-align', ''); this.css('line-height', ''); this.css('font-size', ''); + this.removeClass('icon-loading'); }; }(jQuery)); diff --git a/core/js/tests/specs/jquery.avatarSpec.js b/core/js/tests/specs/jquery.avatarSpec.js index b9351d2a8a0..bdd1fdcc163 100644 --- a/core/js/tests/specs/jquery.avatarSpec.js +++ b/core/js/tests/specs/jquery.avatarSpec.js @@ -19,6 +19,13 @@ describe('jquery.avatar tests', function() { devicePixelRatio = window.devicePixelRatio; window.devicePixelRatio = 1; + + spyOn(window, 'Image').and.returnValue({ + onload: function() { + }, + onerror: function() { + } + }); }); afterEach(function() { @@ -39,6 +46,9 @@ describe('jquery.avatar tests', function() { $div.height(9); $div.avatar('foo'); + expect(window.Image).toHaveBeenCalled(); + window.Image().onerror(); + expect($div.height()).toEqual(9); expect($div.width()).toEqual(9); }); @@ -47,6 +57,9 @@ describe('jquery.avatar tests', function() { $div.data('size', 10); $div.avatar('foo'); + expect(window.Image).toHaveBeenCalled(); + window.Image().onerror(); + expect($div.height()).toEqual(10); expect($div.width()).toEqual(10); }); @@ -55,6 +68,9 @@ describe('jquery.avatar tests', function() { it('defined', function() { $div.avatar('foo', 8); + expect(window.Image).toHaveBeenCalled(); + window.Image().onerror(); + expect($div.height()).toEqual(8); expect($div.width()).toEqual(8); }); @@ -73,16 +89,10 @@ describe('jquery.avatar tests', function() { describe('no avatar', function() { it('show placeholder for existing user', function() { spyOn($div, 'imageplaceholder'); - $div.avatar('foo'); - - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({ - data: {displayname: 'bar'} - }) - ); + $div.avatar('foo', undefined, undefined, undefined, undefined, 'bar'); + expect(window.Image).toHaveBeenCalled(); + window.Image().onerror(); expect($div.imageplaceholder).toHaveBeenCalledWith('foo', 'bar'); }); @@ -91,32 +101,23 @@ describe('jquery.avatar tests', function() { spyOn($div, 'css'); $div.avatar('foo'); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({ - data: {} - }) - ); + expect(window.Image).toHaveBeenCalled(); + window.Image().onerror(); expect($div.imageplaceholder).toHaveBeenCalledWith('?'); expect($div.css).toHaveBeenCalledWith('background-color', '#b9b9b9'); }); - it('show no placeholder', function() { + it('show no placeholder is ignored', function() { spyOn($div, 'imageplaceholder'); + spyOn($div, 'css'); $div.avatar('foo', undefined, undefined, true); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify({ - data: {} - }) - ); + expect(window.Image).toHaveBeenCalled(); + window.Image().onerror(); - expect($div.imageplaceholder.calls.any()).toEqual(false); - expect($div.css('display')).toEqual('none'); + expect($div.imageplaceholder).toHaveBeenCalledWith('?'); + expect($div.css).toHaveBeenCalledWith('background-color', '#b9b9b9'); }); }); @@ -129,24 +130,24 @@ describe('jquery.avatar tests', function() { window.devicePixelRatio = 1; $div.avatar('foo', 32); - expect(fakeServer.requests[0].method).toEqual('GET'); - expect(fakeServer.requests[0].url).toEqual('http://localhost/index.php/avatar/foo/32'); + expect(window.Image).toHaveBeenCalled(); + expect(window.Image().src).toEqual('http://localhost/index.php/avatar/foo/32'); }); it('high DPI icon', function() { window.devicePixelRatio = 4; $div.avatar('foo', 32); - expect(fakeServer.requests[0].method).toEqual('GET'); - expect(fakeServer.requests[0].url).toEqual('http://localhost/index.php/avatar/foo/128'); + expect(window.Image).toHaveBeenCalled(); + expect(window.Image().src).toEqual('http://localhost/index.php/avatar/foo/128'); }); it('high DPI icon round up size', function() { window.devicePixelRatio = 1.9; $div.avatar('foo', 32); - expect(fakeServer.requests[0].method).toEqual('GET'); - expect(fakeServer.requests[0].url).toEqual('http://localhost/index.php/avatar/foo/61'); + expect(window.Image).toHaveBeenCalled(); + expect(window.Image().src).toEqual('http://localhost/index.php/avatar/foo/61'); }); }); @@ -158,17 +159,12 @@ describe('jquery.avatar tests', function() { it('default (no ie8 fix)', function() { $div.avatar('foo', 32); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'image/jpeg' }, - '' - ); + expect(window.Image).toHaveBeenCalled(); + window.Image().onload(); - var img = $div.children('img')[0]; - - expect(img.height).toEqual(32); - expect(img.width).toEqual(32); - expect(img.src).toEqual('http://localhost/index.php/avatar/foo/32'); + expect(window.Image().height).toEqual(32); + expect(window.Image().width).toEqual(32); + expect(window.Image().src).toEqual('http://localhost/index.php/avatar/foo/32'); }); it('default high DPI icon', function() { @@ -176,37 +172,23 @@ describe('jquery.avatar tests', function() { $div.avatar('foo', 32); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'image/jpeg' }, - '' - ); - - var img = $div.children('img')[0]; + expect(window.Image).toHaveBeenCalled(); + window.Image().onload(); - expect(img.height).toEqual(32); - expect(img.width).toEqual(32); - expect(img.src).toEqual('http://localhost/index.php/avatar/foo/61'); + expect(window.Image().height).toEqual(32); + expect(window.Image().width).toEqual(32); + expect(window.Image().src).toEqual('http://localhost/index.php/avatar/foo/61'); }); - it('with ie8 fix', function() { - sinon.stub(Math, 'random').callsFake(function() { - return 0.5; - }); - + it('with ie8 fix (ignored)', function() { $div.avatar('foo', 32, true); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'image/jpeg' }, - '' - ); + expect(window.Image).toHaveBeenCalled(); + window.Image().onload(); - var img = $div.children('img')[0]; - - expect(img.height).toEqual(32); - expect(img.width).toEqual(32); - expect(img.src).toEqual('http://localhost/index.php/avatar/foo/32#500'); + expect(window.Image().height).toEqual(32); + expect(window.Image().width).toEqual(32); + expect(window.Image().src).toEqual('http://localhost/index.php/avatar/foo/32'); }); it('unhide div', function() { @@ -214,11 +196,12 @@ describe('jquery.avatar tests', function() { $div.avatar('foo', 32); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'image/jpeg' }, - '' - ); + expect(window.Image).toHaveBeenCalled(); + window.Image().onload(); + + expect(window.Image().height).toEqual(32); + expect(window.Image().width).toEqual(32); + expect(window.Image().src).toEqual('http://localhost/index.php/avatar/foo/32'); expect($div.css('display')).toEqual('block'); }); @@ -232,12 +215,12 @@ describe('jquery.avatar tests', function() { observer.callback(); }); - fakeServer.requests[0].respond( - 200, - { 'Content-Type': 'image/jpeg' }, - '' - ); + expect(window.Image).toHaveBeenCalled(); + window.Image().onload(); + expect(window.Image().height).toEqual(32); + expect(window.Image().width).toEqual(32); + expect(window.Image().src).toEqual('http://localhost/index.php/avatar/foo/32'); expect(observer.callback).toHaveBeenCalled(); }); }); diff --git a/core/register_command.php b/core/register_command.php index 60e151a5f2c..372d775dc14 100644 --- a/core/register_command.php +++ b/core/register_command.php @@ -90,6 +90,7 @@ if (\OC::$server->getConfig()->getSystemValue('installed', false)) { $application->add(new OC\Core\Command\Db\ConvertType(\OC::$server->getConfig(), new \OC\DB\ConnectionFactory(\OC::$server->getSystemConfig()))); $application->add(new OC\Core\Command\Db\ConvertMysqlToMB4(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection(), \OC::$server->getURLGenerator(), \OC::$server->getLogger())); $application->add(new OC\Core\Command\Db\ConvertFilecacheBigInt(\OC::$server->getDatabaseConnection())); + $application->add(new OC\Core\Command\Db\AddMissingIndices(\OC::$server->getDatabaseConnection())); $application->add(new OC\Core\Command\Db\Migrations\StatusCommand(\OC::$server->getDatabaseConnection())); $application->add(new OC\Core\Command\Db\Migrations\MigrateCommand(\OC::$server->getDatabaseConnection())); $application->add(new OC\Core\Command\Db\Migrations\GenerateCommand(\OC::$server->getDatabaseConnection())); diff --git a/core/templates/login.php b/core/templates/login.php index 82827bbef03..d28c92e36ef 100644 --- a/core/templates/login.php +++ b/core/templates/login.php @@ -70,6 +70,7 @@ script('core', 'merged-login'); <?php } ?> <div class="login-additional"> + <?php if (!$_['hideRemeberLoginState']) { ?> <div class="remember-login-container"> <?php if ($_['rememberLoginState'] === 0) { ?> <input type="checkbox" name="remember_login" value="1" id="remember_login" class="checkbox checkbox--white"> @@ -78,6 +79,7 @@ script('core', 'merged-login'); <?php } ?> <label for="remember_login"><?php p($l->t('Stay logged in')); ?></label> </div> + <?php } ?> <?php if (!empty($_['canResetPassword'])) { ?> <div class="lost-password-container"> <a id="lost-password" href="<?php p($_['resetPasswordLink']); ?>"> |