diff --git a/Sources/Profile.php b/Sources/Profile.php index 53bf4dcf32..ec3208340c 100644 --- a/Sources/Profile.php +++ b/Sources/Profile.php @@ -1218,7 +1218,6 @@ public function loadAvatarData(): bool // Get a list of all the server stored avatars. if ($this->avatar->allow_server_stored) { - Utils::$context['avatar_list'] = []; Utils::$context['avatars'] = is_dir(Config::$modSettings['avatar_directory']) ? $this->getAvatars('', 0) : []; } else { Utils::$context['avatars'] = []; @@ -2607,14 +2606,12 @@ protected function getAvatars(string $directory, int $level = 0): array $result[] = [ 'filename' => Utils::htmlspecialchars($line), - 'checked' => $line == Utils::$context['member']['avatar']['server_pic'], + // server_pic names the directory too, so a file one level down + // has to be compared against the path, not just its own name. + 'checked' => ($directory === '' ? $line : $directory . '/' . $line) == Utils::$context['member']['avatar']['server_pic'], 'name' => Utils::htmlspecialchars(str_replace('_', ' ', $filename)), 'is_dir' => false, ]; - - if ($level == 1) { - Utils::$context['avatar_list'][] = $directory . '/' . $line; - } } return $result; diff --git a/Themes/default/Profile.template.php b/Themes/default/Profile.template.php index ef257af485..d7e97bfe57 100644 --- a/Themes/default/Profile.template.php +++ b/Themes/default/Profile.template.php @@ -2978,7 +2978,7 @@ function template_profile_avatar_select() if (empty(Config::$modSettings['gravatarEnabled']) || empty(Config::$modSettings['gravatarOverride'])) { echo ' - +
'; @@ -2986,7 +2986,7 @@ function template_profile_avatar_select() if (!empty(Utils::$context['member']['avatar']['allow_server_stored'])) { echo ' - +
'; @@ -2994,7 +2994,7 @@ function template_profile_avatar_select() if (!empty(Utils::$context['member']['avatar']['allow_external'])) { echo ' - +
'; @@ -3002,7 +3002,7 @@ function template_profile_avatar_select() if (!empty(Utils::$context['member']['avatar']['allow_upload'])) { echo ' - +
'; @@ -3010,7 +3010,7 @@ function template_profile_avatar_select() if (!empty(Utils::$context['member']['avatar']['allow_gravatar'])) { echo ' - + '; } @@ -3022,59 +3022,55 @@ function template_profile_avatar_select() // If users are allowed to choose avatars stored on the server show selection boxes to choice them from. if (!empty(Utils::$context['member']['avatar']['allow_server_stored'])) { echo ' -
+
- '; - // This lists all the file categories. + // One entry per avatar, with the directories as groups. Nothing here is + // nested more than one deep, because that is all the picker can show. foreach (Utils::$context['avatars'] as $avatar) { - echo ' - '; + if (!empty($avatar['is_dir'])) { + echo ' + '; + + foreach ($avatar['files'] as $file) { + echo ' + '; + } + + echo ' + '; + } else { + echo ' + '; + } } echo '
-
- -
-
'; } // If the user can link to an off server avatar, show them a box to input the address. if (!empty(Utils::$context['member']['avatar']['allow_external'])) { echo ' -
+
', Utils::$context['member']['avatar']['choice'] == 'external' ? '
' : '', '
', Lang::getTxt('avatar_by_url', file: 'Profile'), '
', !empty(Config::$modSettings['avatar_action_too_large']) && Config::$modSettings['avatar_action_too_large'] == 'option_download_and_resize' ? template_max_size('external') : '', ' -
+
'; } // If the user is able to upload avatars to the server show them an upload box. if (!empty(Utils::$context['member']['avatar']['allow_upload'])) { echo ' -
+
', Utils::$context['member']['avatar']['choice'] == 'upload' ? '
' : '', ' - ', template_max_size('upload'), ' + ', template_max_size('upload'), ' ', (!empty(Utils::$context['member']['avatar']['id_attach']) ? '
' : ''), '
'; } @@ -3082,7 +3078,7 @@ function template_profile_avatar_select() // if the user is able to use Gravatar avatars show then the image preview if (!empty(Utils::$context['member']['avatar']['allow_gravatar'])) { echo ' -
+
', Utils::$context['member']['avatar']['choice'] == 'gravatar' ? '
' : ''; if (empty(Config::$modSettings['gravatarAllowExtraEmail'])) { @@ -3105,51 +3101,6 @@ function template_profile_avatar_select() } echo ' - '; } diff --git a/Themes/default/scripts/profile.js b/Themes/default/scripts/profile.js index e72465db71..9e43d78278 100644 --- a/Themes/default/scripts/profile.js +++ b/Themes/default/scripts/profile.js @@ -162,67 +162,85 @@ function ajax_getSignaturePreview (showPreview) return false; } -function changeSel(selected) +/* + * The avatar picker. Which panel is on show follows the radio buttons, and + * every panel says which choice it belongs to with data-avatar-choice, so + * nothing here has to be told which ones the forum allows. + */ +document.addEventListener('DOMContentLoaded', function () { - if (cat.selectedIndex == -1) + var panels = document.querySelectorAll('[data-avatar-choice]'); + + if (!panels.length) return; - if (cat.options[cat.selectedIndex].value.indexOf("/") > 0) - { - var i; - var count = 0; + var form = panels[0].closest('form'), + choices = form.avatar_choice; - file.style.display = "inline"; - file.disabled = false; + var showPanel = function () { + var chosen = form.avatar_choice.value; - for (i = file.length; i >= 0; i = i - 1) - file.options[i] = null; + for (var i = 0; i < panels.length; i++) + panels[i].style.display = panels[i].dataset.avatarChoice == chosen ? '' : 'none'; - for (i = 0; i < files.length; i++) - if (files[i].indexOf(cat.options[cat.selectedIndex].value) == 0) - { - var filename = files[i].substr(files[i].indexOf("/") + 1); - var showFilename = filename.substr(0, filename.lastIndexOf(".")); - showFilename = showFilename.replace(/[_]/g, " "); + // Switching to Gravatar throws away an address that came from one of + // the other choices, since it would not be an address at all. + var gravatar = document.getElementById('avatar_gravatar'); - file.options[count] = new Option(showFilename, files[i]); + if (chosen == 'gravatar' && gravatar && 'clearEmail' in gravatar.dataset && document.getElementById('gravatarEmail')) + document.getElementById('gravatarEmail').value = ''; + }; - if (filename == selected) - { - if (file.options.defaultSelected) - file.options[count].defaultSelected = true; - else - file.options[count].selected = true; - } + for (var i = 0; i < choices.length; i++) + choices[i].addEventListener('change', showPanel); - count++; - } + showPanel(); - if (file.selectedIndex == -1 && file.options[0]) - file.options[0].selected = true; + // Touching anything inside a panel picks that panel's radio, which is what + // the onfocus attributes on each field used to do. + for (var i = 0; i < panels.length; i++) + panels[i].addEventListener('focusin', function () { + selectRadioByName(form.avatar_choice, this.dataset.avatarChoice); + showPanel(); + }); - showAvatar(); - } - else + var gallery = document.getElementById('cat'); + + if (gallery) { - file.style.display = "none"; - file.disabled = true; - document.getElementById("avatar").src = avatardir + cat.options[cat.selectedIndex].value; - document.getElementById("avatar").style.width = ""; - document.getElementById("avatar").style.height = ""; + gallery.addEventListener('change', showAvatar); + showAvatar.call(gallery); } -} + var external = form.userpicpersonal; + + if (external) + external.addEventListener('change', function () { + previewExternalAvatar(this.value); + }); + + var upload = document.getElementById('avatar_upload_box'); + + if (upload) + upload.addEventListener('change', function () { + readfromUpload(this); + }); +}); + +// Shows whichever avatar the gallery is pointing at. function showAvatar() { - if (file.selectedIndex == -1) + var chosen = this.options[this.selectedIndex]; + + if (!chosen || chosen.value == '') return; - document.getElementById("avatar").src = avatardir + file.options[file.selectedIndex].value; - document.getElementById("avatar").alt = file.options[file.selectedIndex].text; - document.getElementById("avatar").alt += file.options[file.selectedIndex].text == size ? "!" : ""; - document.getElementById("avatar").style.width = ""; - document.getElementById("avatar").style.height = ""; + var preview = document.getElementById('avatar'); + + preview.src = this.dataset.avatardir + chosen.value; + preview.alt = chosen.text; + preview.style.width = ''; + preview.style.height = ''; } function previewExternalAvatar(src)