Removal of unused components from the previous menu implementation
authorAlexander Ebert <ebert@woltlab.com>
Fri, 31 Dec 2021 14:21:45 +0000 (15:21 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Fri, 31 Dec 2021 14:21:45 +0000 (15:21 +0100)
com.woltlab.wcf/acpTemplateDelete.xml
com.woltlab.wcf/fileDelete.xml
com.woltlab.wcf/templateDelete.xml
com.woltlab.wcf/templates/footer.tpl
com.woltlab.wcf/templates/pageMenuMobile.tpl [deleted file]
ts/WoltLabSuite/Core/Ui/Page/Menu/Abstract.ts [deleted file]
wcfsetup/install/files/acp/templates/footer.tpl
wcfsetup/install/files/acp/templates/pageMenuMobile.tpl [deleted file]
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Menu/Abstract.js [deleted file]
wcfsetup/install/files/style/ui/menuMobile.scss [deleted file]

index ff858ff64421f34acc2b7e07a6e948ef5c8e2f5f..43542e97cc6f6348c1e48c2ff9e27913d307a51b 100644 (file)
@@ -32,6 +32,7 @@
                <template>pageLanding</template>
                <template>pageMenuItemAdd</template>
                <template>pageMenuItemList</template>
+               <template>pageMenuMobile</template>
                <template>reactionTypeIcon</template>
                <template>setupFooter</template>
                <template>setupHeader</template>
index 8556feed1a8207f99594a962ead1c697e0cfc0ab..fc6b6a2a5a93c2ca345e546086857329e3056378 100644 (file)
@@ -88,6 +88,7 @@
                <file>acp/templates/pageLogo.tpl</file>
                <file>acp/templates/pageMenuItemAdd.tpl</file>
                <file>acp/templates/pageMenuItemList.tpl</file>
+               <file>acp/templates/pageMenuMobile.tpl</file>
                <file>acp/templates/pageMenuUser.tpl</file>
                <file>acp/templates/pageSearchArea.tpl</file>
                <file>acp/templates/reactionTypeIcon.tpl</file>
                <file>js/WoltLabSuite/Core/Media/Search.js</file>
                <file>js/WoltLabSuite/Core/Ui/InlineEditor.js</file>
                <file>js/WoltLabSuite/Core/Ui/Page/JumpToTop.js</file>
+               <file>js/WoltLabSuite/Core/Ui/Page/Menu/Abstract.js</file>
                <file>js/WoltLabSuite/Core/Ui/Reaction/ReputationButtons.js</file>
                <file>js/WoltLabSuite/Core/Ui/Redactor/RuntimeStyle.js</file>
                <file>js/closest.js</file>
                <file>style/ui/dialog.less</file>
                <file>style/ui/dropdown.less</file>
                <file>style/ui/dropdownInteractive.less</file>
+               <file>style/ui/menuMobile.scss</file>
                <file>style/ui/message.less</file>
                <file>style/ui/poll.less</file>
                <file>style/ui/popover.less</file>
index f00d6da3d0dc8bb1d36f8deb8c1ae77da99db8eb..b38fa7214cb28ea86756655c727d31ebe7947f1c 100644 (file)
@@ -37,6 +37,7 @@
                <template>multifactorManageEmail</template>
                <template>notificationListOustanding</template>
                <template>pageLogo</template>
+               <template>pageMenuMobile</template>
                <template>pageNavbarBottom</template>
                <template>privacyPolicy</template>
                <template>quoteBBCodeTag</template>
index 0e9a4e229e08dba6ad0a7b9a778a2b6ed730e4b0..30b416fb8d2f755c189467804036c514b25e8078 100644 (file)
        {include file='pageFooter'}
 </div>
 
-{include file='pageMenuMobile'}
-
 {event name='footer'}
 
 <div class="pageFooterStickyNotice">
diff --git a/com.woltlab.wcf/templates/pageMenuMobile.tpl b/com.woltlab.wcf/templates/pageMenuMobile.tpl
deleted file mode 100644 (file)
index 7dc604e..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-{* main menu / page options / breadcrumbs *}
-<div id="pageMainMenuMobile" class="pageMainMenuMobile menuOverlayMobile" data-page-logo="{$__wcf->getStyleHandler()->getStyle()->getPageLogo()}">
-       <ol class="menuOverlayItemList" data-title="{lang}wcf.menu.page{/lang}">
-               {event name='menuBefore'}
-               
-               <li class="menuOverlayTitle">{lang}wcf.menu.page.navigation{/lang}</li>
-               {foreach from=$__wcf->getBoxHandler()->getBoxByIdentifier('com.woltlab.wcf.MainMenu')->getMenu()->getMenuItemNodeList() item=menuItemNode}
-                       {* Does not use `data-identifier` to prevent compatibility issues. See https://github.com/WoltLab/WCF/pull/2813 *}
-                       <li class="menuOverlayItem" data-mobile-identifier="{@$menuItemNode->identifier}">
-                               {assign var=__outstandingItems value=$menuItemNode->getOutstandingItems()}
-                               <a href="{$menuItemNode->getURL()}" class="menuOverlayItemLink{if $__outstandingItems} menuOverlayItemBadge{/if}{if $menuItemNode->isActiveNode()} active{/if}"{if $menuItemNode->isExternalLink() && EXTERNAL_LINK_TARGET_BLANK} target="_blank"{/if}>
-                                       <span class="menuOverlayItemTitle">{$menuItemNode->getTitle()}</span>
-                                       {if $__outstandingItems}
-                                               <span class="badge badgeUpdate">{#$__outstandingItems}</span>
-                                       {/if}
-                               </a>
-                               
-                               {if $menuItemNode->hasChildren()}<ol class="menuOverlayItemList">{else}</li>{/if}
-                                       
-                               {if !$menuItemNode->hasChildren() && $menuItemNode->isLastSibling()}
-                                       {@"</ol></li>"|str_repeat:$menuItemNode->getOpenParentNodes()}
-                               {/if}
-               {/foreach}
-
-                {if $__wcf->getBoxHandler()->getBoxByIdentifier('com.woltlab.wcf.FooterMenu')}
-                       {hascontent}
-                               <li class="menuOverlayItemSpacer"></li>
-                               {content}       
-                                       {foreach from=$__wcf->getBoxHandler()->getBoxByIdentifier('com.woltlab.wcf.FooterMenu')->getMenu()->getMenuItemNodeList() item=menuItemNode}
-                                               {* Does not use `data-identifier` to prevent compatibility issues. See https://github.com/WoltLab/WCF/pull/2813 *}
-                                               <li class="menuOverlayItem" data-mobile-identifier="{@$menuItemNode->identifier}">
-                                                       {assign var=__outstandingItems value=$menuItemNode->getOutstandingItems()}
-                                                       <a href="{$menuItemNode->getURL()}" class="menuOverlayItemLink{if $__outstandingItems} menuOverlayItemBadge{/if}{if $menuItemNode->isActiveNode()} active{/if}"{if $menuItemNode->isExternalLink() && EXTERNAL_LINK_TARGET_BLANK} target="_blank"{/if}>
-                                                               <span class="menuOverlayItemTitle">{$menuItemNode->getTitle()}</span>
-                                                               {if $__outstandingItems}
-                                                                       <span class="badge badgeUpdate">{#$__outstandingItems}</span>
-                                                               {/if}
-                                                       </a>
-                       
-                                                       {if $menuItemNode->hasChildren()}<ol class="menuOverlayItemList">{else}</li>{/if}
-                       
-                                                       {if !$menuItemNode->hasChildren() && $menuItemNode->isLastSibling()}
-                                                               {@"</ol></li>"|str_repeat:$menuItemNode->getOpenParentNodes()}
-                                                       {/if}
-                                       {/foreach}
-                               {/content}
-                       {/hascontent}
-               {/if}
-
-               <li class="menuOverlayItemSpacer"></li>
-               <li class="menuOverlayItem" data-more="com.woltlab.wcf.search">
-                       <a href="#" class="menuOverlayItemLink box24">
-                               <span class="icon icon24 fa-search"></span>
-                               <span class="menuOverlayItemTitle">{lang}wcf.global.search{/lang}</span>
-                       </a>
-               </li>
-               <li class="menuOverlayTitle" id="pageMainMenuMobilePageOptionsTitle">{lang}wcf.menu.page.options{/lang}</li>
-               
-               {event name='menuItems'}
-               
-               {hascontent}
-                       <li class="menuOverlayTitle">{lang}wcf.menu.page.location{/lang}</li>
-                       {content}
-                               {assign var=__breadcrumbsDepth value=0}
-                               {foreach from=$__wcf->getBreadcrumbs() item=$breadcrumb}
-                                       {* skip breadcrumbs that do not expose a visible label *}
-                                       {if $breadcrumb->getLabel()}
-                                               <li class="menuOverlayItem">
-                                                       <a href="{$breadcrumb->getURL()}" class="menuOverlayItemLink">
-                                                               <span{if $__breadcrumbsDepth} style="padding-left: {$__breadcrumbsDepth * 20}px" {/if} class="box24">
-                                                                       <span class="icon icon24 fa-{if $__breadcrumbsDepth}caret-right{else}home{/if}"></span>
-                                                                       <span class="menuOverlayItemTitle">{$breadcrumb->getLabel()}</span>
-                                                               </span>
-                                                       </a>
-                                               </li>
-                                               {assign var=__breadcrumbsDepth value=$__breadcrumbsDepth + 1}
-                                       {/if}
-                               {/foreach}
-                       {/content}
-               {/hascontent}
-               
-               {event name='menuAfter'}
-       </ol>
-</div>
-
-{* user menu *}
-<div id="pageUserMenuMobile" class="pageUserMenuMobile menuOverlayMobile" data-page-logo="{$__wcf->getStyleHandler()->getStyle()->getPageLogo()}">
-       <ol class="menuOverlayItemList" data-title="{lang}wcf.menu.user{/lang}">
-               {event name='userMenuBefore'}
-               
-               {if $__wcf->user->userID}
-                       {* logged-in *}
-                       <li class="menuOverlayTitle">{lang}wcf.menu.user{/lang}</li>
-                       <li class="menuOverlayItem">
-                               <a href="{$__wcf->user->getLink()}" class="menuOverlayItemLink box24">
-                                       {@$__wcf->getUserProfileHandler()->getAvatar()->getImageTag(24)}
-                                       <span class="menuOverlayItemTitle">{$__wcf->user->username}</span>
-                               </a>
-                       </li>
-                       <li class="menuOverlayItem">
-                               <a href="{link controller='Settings'}{/link}" class="menuOverlayItemLink box24">
-                                       <span class="icon icon24 fa-cog"></span>
-                                       <span class="menuOverlayItemTitle">{lang}wcf.user.panel.settings{/lang}</span>
-                               </a>
-                               <ol class="menuOverlayItemList">
-                                       {event name='userMenuItemsBefore'}
-                                       
-                                       {foreach from=$__wcf->getUserMenu()->getMenuItems('') item=menuCategory}
-                                               <li class="menuOverlayTitle">{$menuCategory->getTitle()}</li>
-                                               {foreach from=$__wcf->getUserMenu()->getMenuItems($menuCategory->menuItem) item=menuItem}
-                                                       <li class="menuOverlayItem">
-                                                               <a href="{$menuItem->getProcessor()->getLink()}" class="menuOverlayItemLink">{@$menuItem}</a>
-                                                       </li>
-                                               {/foreach}
-                                       {/foreach}
-                                       
-                                       {event name='userMenuItemsAfter'}
-                               </ol>
-                       </li>
-                       {if $__wcf->session->getPermission('admin.general.canUseAcp')}
-                               <li class="menuOverlayItem">
-                                       <a href="{link isACP=true}{/link}" class="menuOverlayItemLink box24">
-                                               <span class="icon icon24 fa-wrench"></span>
-                                               <span class="menuOverlayItemTitle">{lang}wcf.global.acp.short{/lang}</span>
-                                       </a>
-                               </li>
-                       {/if}
-                       <li class="menuOverlayItemSpacer"></li>
-                       <li class="menuOverlayItem" data-more="com.woltlab.wcf.notifications">
-                               <a href="{link controller='NotificationList'}{/link}" class="menuOverlayItemLink menuOverlayItemBadge box24" data-badge-identifier="userNotifications">
-                                       <span class="icon icon24 fa-bell-o"></span>
-                                       <span class="menuOverlayItemTitle">{lang}wcf.user.notification.notifications{/lang}</span>
-                                       {if $__wcf->getUserNotificationHandler()->getNotificationCount()}<span class="badge badgeUpdate">{#$__wcf->getUserNotificationHandler()->getNotificationCount()}</span>{/if}
-                               </a>
-                       </li>
-                       {if $__wcf->user->userID && $__wcf->session->getPermission('mod.general.canUseModeration')}
-                               <li class="menuOverlayItem" data-more="com.woltlab.wcf.moderation">
-                                       <a href="#" class="menuOverlayItemLink menuOverlayItemBadge box24" data-badge-identifier="outstandingModeration">
-                                               <span class="icon icon24 fa-exclamation-triangle"></span>
-                                               <span class="menuOverlayItemTitle">{lang}wcf.moderation.moderation{/lang}</span>
-                                               {if $__wcf->getModerationQueueManager()->getUnreadModerationCount()}<span class="badge badgeUpdate">{#$__wcf->getModerationQueueManager()->getUnreadModerationCount()}</span>{/if}
-                                       </a>
-                               </li>
-                       {/if}
-                       
-                       {event name='userMenuItems'}
-                       
-                       <li class="menuOverlayItemSpacer"></li>
-                       <li class="menuOverlayItem">
-                               <a href="{link controller='Logout'}t={csrfToken type=url}{/link}" class="menuOverlayItemLink box24">
-                                       <span class="icon icon24 fa-sign-out"></span>
-                                       <span class="menuOverlayItemTitle">{lang}wcf.user.logout{/lang}</span>
-                               </a>
-                       </li>
-               {else}
-                       {* guest *}
-                       <li class="menuOverlayTitle">{lang}wcf.menu.user{/lang}</li>
-                       {if !$__disableLoginLink|isset}
-                               <li class="menuOverlayItem" data-more="com.woltlab.wcf.login">
-                                       <a href="#" class="menuOverlayItemLink box24">
-                                               <span class="icon icon24 fa-sign-in"></span>
-                                               <span class="menuOverlayItemTitle">{lang}wcf.user.loginOrRegister{/lang}</span>
-                                       </a>
-                               </li>
-                       {/if}
-                       
-                       {event name='guestUserMenuItems'}
-                       
-                       {if $__wcf->getLanguage()->getLanguages()|count > 1}
-                               <li class="menuOverlayItemSpacer"></li>
-                               <li class="menuOverlayTitle">{lang}wcf.user.language{/lang}</li>
-                               <li class="menuOverlayItem">
-                                       <a href="#" class="menuOverlayItemLink box24">
-                                               <img src="{$__wcf->getLanguage()->getIconPath()}" alt="">
-                                               <span class="menuOverlayItemTitle">{$__wcf->getLanguage()}</span>
-                                       </a>
-                                       <ol class="menuOverlayItemList" data-title="{lang}wcf.user.language{/lang}">
-                                               {foreach from=$__wcf->getLanguage()->getLanguages() item=_language}
-                                                       <li class="menuOverlayItem" data-more="com.woltlab.wcf.language" data-language-code="{$_language->getFixedLanguageCode()}" data-language-id="{@$_language->languageID}">
-                                                               <a href="#" class="menuOverlayItemLink box24">
-                                                                       <img src="{$_language->getIconPath()}" alt="">
-                                                                       <span class="menuOverlayItemTitle">{$_language}</span>
-                                                               </a>
-                                                       </li>
-                                               {/foreach}
-                                       </ol>
-                               </li>
-                       {/if}
-               {/if}
-               
-               {event name='userMenuAfter'}
-       </ol>
-</div>
diff --git a/ts/WoltLabSuite/Core/Ui/Page/Menu/Abstract.ts b/ts/WoltLabSuite/Core/Ui/Page/Menu/Abstract.ts
deleted file mode 100644 (file)
index 8721682..0000000
+++ /dev/null
@@ -1,586 +0,0 @@
-/**
- * Provides a touch-friendly fullscreen menu.
- *
- * @author  Alexander Ebert
- * @copyright  2001-2019 WoltLab GmbH
- * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module  WoltLabSuite/Core/Ui/Page/Menu/Abstract
- */
-
-import * as Core from "../../../Core";
-import * as Environment from "../../../Environment";
-import * as EventHandler from "../../../Event/Handler";
-import * as Language from "../../../Language";
-import * as DomTraverse from "../../../Dom/Traverse";
-import * as UiScreen from "../../Screen";
-
-const _pageContainer = document.getElementById("pageContainer")!;
-
-const enum TouchPosition {
-  AtEdge = 20,
-  MovedHorizontally = 5,
-  MovedVertically = 20,
-}
-
-/**
- * Which edge of the menu is touched? Empty string
- * if no menu is currently touched.
- *
- * One 'left', 'right' or ''.
- */
-let _androidTouching = "";
-
-interface ItemData {
-  itemList: HTMLOListElement;
-  parentItemList: HTMLOListElement;
-}
-
-abstract class UiPageMenuAbstract {
-  private readonly activeList: HTMLOListElement[] = [];
-  protected readonly button: HTMLElement;
-  private depth = 0;
-  private enabled = true;
-  private readonly eventIdentifier: string;
-  private readonly items = new Map<HTMLAnchorElement, ItemData>();
-  protected readonly menu: HTMLElement;
-  private removeActiveList = false;
-
-  protected constructor(eventIdentifier: string, elementId: string, buttonSelector: string) {
-    if (document.body.dataset.template === "packageInstallationSetup") {
-      // work-around for WCFSetup on mobile
-      return;
-    }
-
-    this.eventIdentifier = eventIdentifier;
-    this.menu = document.getElementById(elementId)!;
-
-    const callbackOpen = this.open.bind(this);
-    this.button = document.querySelector(buttonSelector) as HTMLElement;
-    this.button.addEventListener("click", callbackOpen);
-
-    this.initItems();
-    this.initHeader();
-
-    EventHandler.add(this.eventIdentifier, "open", callbackOpen);
-    EventHandler.add(this.eventIdentifier, "close", this.close.bind(this));
-    EventHandler.add(this.eventIdentifier, "updateButtonState", this.updateButtonState.bind(this));
-
-    this.menu.addEventListener("animationend", () => {
-      if (!this.menu.classList.contains("open")) {
-        this.menu.querySelectorAll(".menuOverlayItemList").forEach((itemList) => {
-          // force the main list to be displayed
-          itemList.classList.remove("active", "hidden");
-        });
-      }
-    });
-
-    this.menu.children[0].addEventListener("transitionend", () => {
-      this.menu.classList.add("allowScroll");
-
-      if (this.removeActiveList) {
-        this.removeActiveList = false;
-
-        const list = this.activeList.pop();
-        if (list) {
-          list.classList.remove("activeList");
-        }
-      }
-    });
-
-    const backdrop = document.createElement("div");
-    backdrop.className = "menuOverlayMobileBackdrop";
-    backdrop.addEventListener("click", this.close.bind(this));
-
-    this.menu.insertAdjacentElement("afterend", backdrop);
-
-    this.menu.parentElement!.insertBefore(backdrop, this.menu.nextSibling);
-
-    this.updateButtonState();
-
-    if (Environment.platform() === "android") {
-      this.initializeAndroid();
-    }
-  }
-
-  /**
-   * Opens the menu.
-   */
-  open(event?: MouseEvent): boolean {
-    if (!this.enabled) {
-      return false;
-    }
-
-    if (event instanceof Event) {
-      event.preventDefault();
-    }
-
-    this.menu.classList.add("open");
-    this.menu.classList.add("allowScroll");
-    this.menu.children[0].classList.add("activeList");
-
-    UiScreen.scrollDisable();
-
-    _pageContainer.classList.add("menuOverlay-" + this.menu.id);
-
-    UiScreen.pageOverlayOpen();
-
-    return true;
-  }
-
-  /**
-   * Closes the menu.
-   */
-  close(event?: Event): boolean {
-    if (event instanceof Event) {
-      event.preventDefault();
-    }
-
-    if (this.menu.classList.contains("open")) {
-      this.menu.classList.remove("open");
-
-      UiScreen.scrollEnable();
-      UiScreen.pageOverlayClose();
-
-      _pageContainer.classList.remove("menuOverlay-" + this.menu.id);
-
-      return true;
-    }
-
-    return false;
-  }
-
-  /**
-   * Enables the touch menu.
-   */
-  enable(): void {
-    this.enabled = true;
-  }
-
-  /**
-   * Disables the touch menu.
-   */
-  disable(): void {
-    this.enabled = false;
-
-    this.close();
-  }
-
-  /**
-   * Initializes the Android Touch Menu.
-   */
-  private initializeAndroid(): void {
-    // specify on which side of the page the menu appears
-    let appearsAt: "left" | "right";
-    switch (this.menu.id) {
-      case "pageUserMenuMobile":
-        appearsAt = "right";
-        break;
-      case "pageMainMenuMobile":
-        appearsAt = "left";
-        break;
-      default:
-        return;
-    }
-
-    const backdrop = this.menu.nextElementSibling as HTMLElement;
-
-    // horizontal position of the touch start
-    let touchStart: { x: number; y: number } | undefined = undefined;
-
-    document.addEventListener("touchstart", (event) => {
-      const touches = event.touches;
-
-      let isLeftEdge: boolean;
-      let isRightEdge: boolean;
-
-      const isOpen = this.menu.classList.contains("open");
-
-      // check whether we touch the edges of the menu
-      if (appearsAt === "left") {
-        isLeftEdge = !isOpen && touches[0].clientX < TouchPosition.AtEdge;
-        isRightEdge = isOpen && Math.abs(this.menu.offsetWidth - touches[0].clientX) < TouchPosition.AtEdge;
-      } else {
-        isLeftEdge =
-          isOpen &&
-          Math.abs(document.body.clientWidth - this.menu.offsetWidth - touches[0].clientX) < TouchPosition.AtEdge;
-        isRightEdge = !isOpen && document.body.clientWidth - touches[0].clientX < TouchPosition.AtEdge;
-      }
-
-      // abort if more than one touch
-      if (touches.length > 1) {
-        if (_androidTouching) {
-          Core.triggerEvent(document, "touchend");
-        }
-        return;
-      }
-
-      // break if a touch is in progress
-      if (_androidTouching) {
-        return;
-      }
-
-      // break if no edge has been touched
-      if (!isLeftEdge && !isRightEdge) {
-        return;
-      }
-
-      // break if a different menu is open
-      if (UiScreen.pageOverlayIsActive()) {
-        const found = _pageContainer.classList.contains(`menuOverlay-${this.menu.id}`);
-        if (!found) {
-          return;
-        }
-      }
-      // break if redactor is in use
-      if (document.documentElement.classList.contains("redactorActive")) {
-        return;
-      }
-
-      touchStart = {
-        x: touches[0].clientX,
-        y: touches[0].clientY,
-      };
-
-      if (isLeftEdge) {
-        _androidTouching = "left";
-      }
-      if (isRightEdge) {
-        _androidTouching = "right";
-      }
-    });
-
-    document.addEventListener("touchend", (event) => {
-      // break if we did not start a touch
-      if (!_androidTouching || !touchStart) {
-        return;
-      }
-
-      // break if the menu did not even start opening
-      if (!this.menu.classList.contains("open")) {
-        // reset
-        touchStart = undefined;
-        _androidTouching = "";
-        return;
-      }
-
-      // last known position of the finger
-      let position: number;
-      if (event) {
-        position = event.changedTouches[0].clientX;
-      } else {
-        position = touchStart.x;
-      }
-
-      // clean up touch styles
-      this.menu.classList.add("androidMenuTouchEnd");
-      this.menu.style.removeProperty("transform");
-      backdrop.style.removeProperty(appearsAt);
-      this.menu.addEventListener(
-        "transitionend",
-        () => {
-          this.menu.classList.remove("androidMenuTouchEnd");
-        },
-        { once: true },
-      );
-
-      // check whether the user moved the finger far enough
-      if (appearsAt === "left") {
-        if (_androidTouching === "left" && position < touchStart.x + 100) {
-          this.close();
-        }
-        if (_androidTouching === "right" && position < touchStart.x - 100) {
-          this.close();
-        }
-      } else {
-        if (_androidTouching === "left" && position > touchStart.x + 100) {
-          this.close();
-        }
-        if (_androidTouching === "right" && position > touchStart.x - 100) {
-          this.close();
-        }
-      }
-
-      // reset
-      touchStart = undefined;
-      _androidTouching = "";
-    });
-
-    document.addEventListener("touchmove", (event) => {
-      // break if we did not start a touch
-      if (!_androidTouching || !touchStart) {
-        return;
-      }
-
-      const touches = event.touches;
-
-      // check whether the user started moving in the correct direction
-      // this avoids false positives, in case the user just wanted to tap
-      let movedFromEdge = false;
-      if (_androidTouching === "left") {
-        movedFromEdge = touches[0].clientX > touchStart.x + TouchPosition.MovedHorizontally;
-      }
-      if (_androidTouching === "right") {
-        movedFromEdge = touches[0].clientX < touchStart.x - TouchPosition.MovedHorizontally;
-      }
-
-      const movedVertically = Math.abs(touches[0].clientY - touchStart.y) > TouchPosition.MovedVertically;
-
-      let isOpen = this.menu.classList.contains("open");
-      if (!isOpen && movedFromEdge && !movedVertically) {
-        // the menu is not yet open, but the user moved into the right direction
-        this.open();
-        isOpen = true;
-      }
-
-      if (isOpen) {
-        // update CSS to the new finger position
-        let position = touches[0].clientX;
-        if (appearsAt === "right") {
-          position = document.body.clientWidth - position;
-        }
-        if (position > this.menu.offsetWidth) {
-          position = this.menu.offsetWidth;
-        }
-        if (position < 0) {
-          position = 0;
-        }
-
-        const offset = (appearsAt === "left" ? 1 : -1) * (position - this.menu.offsetWidth);
-        this.menu.style.setProperty("transform", `translateX(${offset}px)`);
-        backdrop.style.setProperty(appearsAt, Math.min(this.menu.offsetWidth, position).toString() + "px");
-      }
-    });
-  }
-
-  /**
-   * Initializes all menu items.
-   */
-  private initItems(): void {
-    this.menu.querySelectorAll(".menuOverlayItemLink").forEach((element: HTMLAnchorElement) => {
-      this.initItem(element);
-    });
-  }
-
-  /**
-   * Initializes a single menu item.
-   */
-  private initItem(item: HTMLAnchorElement): void {
-    // check if it should contain a 'more' link w/ an external callback
-    const parent = item.parentElement!;
-    const more = parent.dataset.more;
-    if (more) {
-      item.addEventListener("click", (event) => {
-        event.preventDefault();
-        event.stopPropagation();
-
-        EventHandler.fire(this.eventIdentifier, "more", {
-          handler: this,
-          identifier: more,
-          item: item,
-          parent: parent,
-        });
-      });
-
-      return;
-    }
-
-    const itemList = item.nextElementSibling as HTMLOListElement;
-    if (itemList === null) {
-      return;
-    }
-
-    // handle static items with an icon-type button next to it (acp menu)
-    if (itemList.nodeName !== "OL" && itemList.classList.contains("menuOverlayItemLinkIcon")) {
-      // add wrapper
-      const wrapper = document.createElement("span");
-      wrapper.className = "menuOverlayItemWrapper";
-      parent.insertBefore(wrapper, item);
-      wrapper.appendChild(item);
-
-      while (wrapper.nextElementSibling) {
-        wrapper.appendChild(wrapper.nextElementSibling);
-      }
-
-      return;
-    }
-
-    const isLink = item.getAttribute("href") !== "#";
-    const parentItemList = parent.parentElement as HTMLOListElement;
-    let itemTitle = itemList.dataset.title;
-
-    this.items.set(item, {
-      itemList: itemList,
-      parentItemList: parentItemList,
-    });
-
-    if (!itemTitle) {
-      itemTitle = DomTraverse.childByClass(item, "menuOverlayItemTitle")!.textContent!;
-      itemList.dataset.title = itemTitle;
-    }
-
-    const callbackLink = this.showItemList.bind(this, item);
-    if (isLink) {
-      const wrapper = document.createElement("span");
-      wrapper.className = "menuOverlayItemWrapper";
-      parent.insertBefore(wrapper, item);
-      wrapper.appendChild(item);
-
-      const moreLink = document.createElement("a");
-      moreLink.href = "#";
-      moreLink.className = "menuOverlayItemLinkIcon" + (item.classList.contains("active") ? " active" : "");
-      moreLink.innerHTML = '<span class="icon icon24 fa-angle-right"></span>';
-      moreLink.addEventListener("click", callbackLink);
-      wrapper.appendChild(moreLink);
-    } else {
-      item.classList.add("menuOverlayItemLinkMore");
-      item.addEventListener("click", callbackLink);
-    }
-
-    const backLinkItem = document.createElement("li");
-    backLinkItem.className = "menuOverlayHeader";
-
-    const wrapper = document.createElement("span");
-    wrapper.className = "menuOverlayItemWrapper";
-
-    const backLink = document.createElement("a");
-    backLink.href = "#";
-    backLink.className = "menuOverlayItemLink menuOverlayBackLink";
-    backLink.textContent = parentItemList.dataset.title || "";
-    backLink.addEventListener("click", this.hideItemList.bind(this, item));
-
-    const closeLink = document.createElement("a");
-    closeLink.href = "#";
-    closeLink.className = "menuOverlayItemLinkIcon";
-    closeLink.innerHTML = '<span class="icon icon24 fa-times"></span>';
-    closeLink.addEventListener("click", this.close.bind(this));
-
-    wrapper.appendChild(backLink);
-    wrapper.appendChild(closeLink);
-    backLinkItem.appendChild(wrapper);
-
-    itemList.insertBefore(backLinkItem, itemList.firstElementChild);
-
-    if (!backLinkItem.nextElementSibling!.classList.contains("menuOverlayTitle")) {
-      const titleItem = document.createElement("li");
-      titleItem.className = "menuOverlayTitle";
-      const title = document.createElement("span");
-      title.textContent = itemTitle;
-      titleItem.appendChild(title);
-
-      itemList.insertBefore(titleItem, backLinkItem.nextElementSibling);
-    }
-  }
-
-  /**
-   * Renders the menu item list header.
-   */
-  private initHeader(): void {
-    const listItem = document.createElement("li");
-    listItem.className = "menuOverlayHeader";
-
-    const wrapper = document.createElement("span");
-    wrapper.className = "menuOverlayItemWrapper";
-    listItem.appendChild(wrapper);
-
-    const logoWrapper = document.createElement("span");
-    logoWrapper.className = "menuOverlayLogoWrapper";
-    wrapper.appendChild(logoWrapper);
-
-    const logo = document.createElement("span");
-    logo.className = "menuOverlayLogo";
-    const pageLogo = this.menu.dataset.pageLogo!;
-    logo.style.setProperty("background-image", `url("${pageLogo}")`, "");
-    logoWrapper.appendChild(logo);
-
-    const closeLink = document.createElement("a");
-    closeLink.href = "#";
-    closeLink.className = "menuOverlayItemLinkIcon";
-    closeLink.innerHTML = '<span class="icon icon24 fa-times"></span>';
-    closeLink.addEventListener("click", this.close.bind(this));
-    wrapper.appendChild(closeLink);
-
-    const list = DomTraverse.childByClass(this.menu, "menuOverlayItemList")!;
-    list.insertBefore(listItem, list.firstElementChild);
-  }
-
-  /**
-   * Hides an item list, return to the parent item list.
-   */
-  private hideItemList(item: HTMLAnchorElement, event: MouseEvent): void {
-    if (event instanceof Event) {
-      event.preventDefault();
-    }
-
-    this.menu.classList.remove("allowScroll");
-    this.removeActiveList = true;
-
-    const data = this.items.get(item)!;
-    data.parentItemList.classList.remove("hidden");
-
-    this.updateDepth(false);
-  }
-
-  /**
-   * Shows the child item list.
-   */
-  private showItemList(item: HTMLAnchorElement, event: MouseEvent): void {
-    event.preventDefault();
-
-    const data = this.items.get(item)!;
-
-    const load = data.itemList.dataset.load;
-    if (load) {
-      if (!Core.stringToBool(item.dataset.loaded || "")) {
-        const target = event.currentTarget as HTMLElement;
-        const icon = target.firstElementChild!;
-        if (icon.classList.contains("fa-angle-right")) {
-          icon.classList.remove("fa-angle-right");
-          icon.classList.add("fa-spinner");
-        }
-
-        EventHandler.fire(this.eventIdentifier, "load_" + load);
-
-        return;
-      }
-    }
-
-    this.menu.classList.remove("allowScroll");
-
-    data.itemList.classList.add("activeList");
-    data.parentItemList.classList.add("hidden");
-
-    this.activeList.push(data.itemList);
-
-    this.updateDepth(true);
-  }
-
-  private updateDepth(increase: boolean): void {
-    this.depth += increase ? 1 : -1;
-
-    let offset = this.depth * -100;
-    if (Language.get("wcf.global.pageDirection") === "rtl") {
-      // reverse logic for RTL
-      offset *= -1;
-    }
-
-    const child = this.menu.children[0] as HTMLElement;
-    child.style.setProperty("transform", `translateX(${offset}%)`, "");
-  }
-
-  protected updateButtonState(): void {
-    let hasNewContent = false;
-    const itemList = this.menu.querySelector(".menuOverlayItemList");
-    this.menu.querySelectorAll(".badgeUpdate").forEach((badge) => {
-      const value = badge.textContent!;
-      if (~~value > 0 && badge.closest(".menuOverlayItemList") === itemList) {
-        hasNewContent = true;
-      }
-    });
-
-    this.button.classList[hasNewContent ? "add" : "remove"]("pageMenuMobileButtonHasContent");
-  }
-}
-
-Core.enableLegacyInheritance(UiPageMenuAbstract);
-
-export = UiPageMenuAbstract;
index ca15232394a24624985e77c570a21aa31bd68e8a..9ddc8ba8075ba162ac0bf0fa92e24a2a23c4d499 100644 (file)
@@ -6,8 +6,6 @@
        {include file='pageFooter'}
 </div>
 
-{if $__isRescueMode|empty}{include file='pageMenuMobile'}{/if}
-
 {event name='footer'}
 
 <!-- JAVASCRIPT_RELOCATE_POSITION -->
diff --git a/wcfsetup/install/files/acp/templates/pageMenuMobile.tpl b/wcfsetup/install/files/acp/templates/pageMenuMobile.tpl
deleted file mode 100644 (file)
index 1f352ac..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-{if PACKAGE_ID && $__wcf->user->userID}
-       {* main menu *}
-       <div id="pageMainMenuMobile" class="pageMainMenuMobile menuOverlayMobile" data-page-logo="{$__wcf->getPath()}acp/images/woltlabSuite.png">
-               <ol class="menuOverlayItemList" data-title="{lang}wcf.menu.page{/lang}">
-                       <li class="menuOverlayTitle">{lang}wcf.menu.page{/lang}</li>
-                       {foreach from=$__wcf->getACPMenu()->getMenuItems('') item=_sectionMenuItem}
-                               <li class="menuOverlayItem">
-                                       <a href="#" class="menuOverlayItemLink box24{if $_sectionMenuItem->menuItem|in_array:$_activeMenuItems} active{/if}">
-                                               <span class="icon icon24 {$_sectionMenuItem->icon}"></span>
-                                               <span class="menuOverlayItemTitle">{@$_sectionMenuItem}</span>
-                                       </a>
-                                       <ol class="menuOverlayItemList">
-                                               {foreach from=$__wcf->getACPMenu()->getMenuItems($_sectionMenuItem->menuItem) item=_menuItemCategory}
-                                                       <li class="menuOverlayTitle">{@$_menuItemCategory}</li>
-                                                       {foreach from=$__wcf->getACPMenu()->getMenuItems($_menuItemCategory->menuItem) item=_menuItem}
-                                                               {assign var=_subMenuItems value=$__wcf->getACPMenu()->getMenuItems($_menuItem->menuItem)}
-                                                               
-                                                               {if $_subMenuItems|empty}
-                                                                       <li class="menuOverlayItem{if $_menuItem->menuItem|in_array:$_activeMenuItems} active{/if}"><a href="{$_menuItem->getLink()}" class="menuOverlayItemLink">{@$_menuItem}</a></li>
-                                                               {else}
-                                                                       {if $_menuItem->menuItem === 'wcf.acp.menu.link.option.category'}
-                                                                               {* handle special option categories *}
-                                                                               {foreach from=$_subMenuItems item=_subMenuItem}
-                                                                                       <li class="menuOverlayItem{if $_subMenuItem->menuItem|in_array:$_activeMenuItems} active{/if}"><a href="{$_subMenuItem->getLink()}" class="menuOverlayItemLink">{@$_subMenuItem}</a></li>
-                                                                               {/foreach}
-                                                                       {else}
-                                                                               <li class="menuOverlayItem">
-                                                                                       <a href="{$_menuItem->getLink()}" class="menuOverlayItemLink{if $_menuItem->menuItem|in_array:$_activeMenuItems && $_activeMenuItems[0] === $_menuItem->menuItem} active{/if}">{@$_menuItem}</a>
-                                                                                       
-                                                                                       {foreach from=$_subMenuItems item=_subMenuItem}
-                                                                                               <a href="{$_subMenuItem->getLink()}" class="menuOverlayItemLinkIcon{if $_subMenuItem->menuItem|in_array:$_activeMenuItems} active{/if}"><span class="icon icon24 {$_subMenuItem->icon}"></span></a>
-                                                                                       {/foreach}
-                                                                               </li>
-                                                                       {/if}
-                                                               {/if}
-                                                       {/foreach}
-                                               {/foreach}
-                                       </ol>
-                               </li>
-                       {/foreach}
-               </ol>
-       </div>
-       
-       {* user menu *}
-       <div id="pageUserMenuMobile" class="pageUserMenuMobile menuOverlayMobile" data-page-logo="{$__wcf->getPath()}acp/images/woltlabSuite.png">
-               <ol class="menuOverlayItemList" data-title="{lang}wcf.menu.user{/lang}">
-                       {event name='userMenuBefore'}
-                       
-                       <li class="menuOverlayTitle">{lang}wcf.menu.user{/lang}</li>
-                       <li class="menuOverlayItem">
-                               <a href="#" class="menuOverlayItemLink box24">
-                                       <span class="icon icon24 fa-home"></span>
-                                       <span class="menuOverlayItemTitle">{lang}wcf.global.jumpToPage{/lang}</span>
-                               </a>
-                               <ol class="menuOverlayItemList">
-                                       {foreach from=$__wcf->getFrontendMenu()->getMenuItemNodeList() item=_menuItem}
-                                               {if !$_menuItem->parentItemID && $_menuItem->getPage()}
-                                                       <li class="menuOverlayItem"><a href="{$_menuItem->getURL()}" class="menuOverlayItemLink">{$_menuItem->getTitle()}</a></li>
-                                               {/if}
-                                       {/foreach}
-                               </ol>
-                       </li>
-                       <li class="menuOverlayItem">
-                               <a href="#" class="menuOverlayItemLink box24">
-                                       <span class="icon icon24 fa-info"></span>
-                                       <span class="menuOverlayItemTitle">WoltLab&reg;</span>
-                               </a>
-                               <ol class="menuOverlayItemList">
-                                       <li class="menuOverlayItem"><a href="https://www.woltlab.com/{if $__wcf->getLanguage()->getFixedLanguageCode() === 'de'}de/{/if}" class="menuOverlayItemLink"{if EXTERNAL_LINK_TARGET_BLANK} target="_blank" rel="noopener"{/if}>{lang}wcf.acp.index.woltlab.website{/lang}</a></li>
-                                       <li class="menuOverlayItem"><a href="https://manual.woltlab.com/{if $__wcf->getLanguage()->getFixedLanguageCode() === 'de'}de{else}en{/if}/" class="menuOverlayItemLink"{if EXTERNAL_LINK_TARGET_BLANK} target="_blank" rel="noopener"{/if}>{lang}wcf.acp.index.woltlab.manual{/lang}</a></li>
-                                       <li class="menuOverlayItem"><a href="https://community.woltlab.com" class="menuOverlayItemLink"{if EXTERNAL_LINK_TARGET_BLANK} target="_blank" rel="noopener"{/if}>{lang}wcf.acp.index.woltlab.forums{/lang}</a></li>
-                                       <li class="menuOverlayItem"><a href="https://www.woltlab.com/ticket-add/" class="menuOverlayItemLink"{if EXTERNAL_LINK_TARGET_BLANK} target="_blank" rel="noopener"{/if}>{lang}wcf.acp.index.woltlab.tickets{/lang}</a></li>
-                                       <li class="menuOverlayItem"><a href="https://pluginstore.woltlab.com" class="menuOverlayItemLink"{if EXTERNAL_LINK_TARGET_BLANK} target="_blank" rel="noopener"{/if}>{lang}wcf.acp.index.woltlab.pluginStore{/lang}</a></li>
-                               </ol>
-                       </li>
-                       <li class="menuOverlayTitle">{$__wcf->user->username}</li>
-                       <li class="menuOverlayItem">
-                               <a href="{link controller='Logout'}t={csrfToken type=url}{/link}" class="menuOverlayItemLink box24">
-                                       <span class="icon icon24 fa-sign-out"></span>
-                                       <span class="menuOverlayItemTitle">{lang}wcf.user.logout{/lang}</span>
-                               </a>
-                       </li>
-                       
-                       {event name='userMenuAfter'}
-               </ol>
-       </div>
-{/if}
diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Menu/Abstract.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Menu/Abstract.js
deleted file mode 100644 (file)
index c6bc042..0000000
+++ /dev/null
@@ -1,468 +0,0 @@
-/**
- * Provides a touch-friendly fullscreen menu.
- *
- * @author  Alexander Ebert
- * @copyright  2001-2019 WoltLab GmbH
- * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module  WoltLabSuite/Core/Ui/Page/Menu/Abstract
- */
-define(["require", "exports", "tslib", "../../../Core", "../../../Environment", "../../../Event/Handler", "../../../Language", "../../../Dom/Traverse", "../../Screen"], function (require, exports, tslib_1, Core, Environment, EventHandler, Language, DomTraverse, UiScreen) {
-    "use strict";
-    Core = (0, tslib_1.__importStar)(Core);
-    Environment = (0, tslib_1.__importStar)(Environment);
-    EventHandler = (0, tslib_1.__importStar)(EventHandler);
-    Language = (0, tslib_1.__importStar)(Language);
-    DomTraverse = (0, tslib_1.__importStar)(DomTraverse);
-    UiScreen = (0, tslib_1.__importStar)(UiScreen);
-    const _pageContainer = document.getElementById("pageContainer");
-    /**
-     * Which edge of the menu is touched? Empty string
-     * if no menu is currently touched.
-     *
-     * One 'left', 'right' or ''.
-     */
-    let _androidTouching = "";
-    class UiPageMenuAbstract {
-        constructor(eventIdentifier, elementId, buttonSelector) {
-            this.activeList = [];
-            this.depth = 0;
-            this.enabled = true;
-            this.items = new Map();
-            this.removeActiveList = false;
-            if (document.body.dataset.template === "packageInstallationSetup") {
-                // work-around for WCFSetup on mobile
-                return;
-            }
-            this.eventIdentifier = eventIdentifier;
-            this.menu = document.getElementById(elementId);
-            const callbackOpen = this.open.bind(this);
-            this.button = document.querySelector(buttonSelector);
-            this.button.addEventListener("click", callbackOpen);
-            this.initItems();
-            this.initHeader();
-            EventHandler.add(this.eventIdentifier, "open", callbackOpen);
-            EventHandler.add(this.eventIdentifier, "close", this.close.bind(this));
-            EventHandler.add(this.eventIdentifier, "updateButtonState", this.updateButtonState.bind(this));
-            this.menu.addEventListener("animationend", () => {
-                if (!this.menu.classList.contains("open")) {
-                    this.menu.querySelectorAll(".menuOverlayItemList").forEach((itemList) => {
-                        // force the main list to be displayed
-                        itemList.classList.remove("active", "hidden");
-                    });
-                }
-            });
-            this.menu.children[0].addEventListener("transitionend", () => {
-                this.menu.classList.add("allowScroll");
-                if (this.removeActiveList) {
-                    this.removeActiveList = false;
-                    const list = this.activeList.pop();
-                    if (list) {
-                        list.classList.remove("activeList");
-                    }
-                }
-            });
-            const backdrop = document.createElement("div");
-            backdrop.className = "menuOverlayMobileBackdrop";
-            backdrop.addEventListener("click", this.close.bind(this));
-            this.menu.insertAdjacentElement("afterend", backdrop);
-            this.menu.parentElement.insertBefore(backdrop, this.menu.nextSibling);
-            this.updateButtonState();
-            if (Environment.platform() === "android") {
-                this.initializeAndroid();
-            }
-        }
-        /**
-         * Opens the menu.
-         */
-        open(event) {
-            if (!this.enabled) {
-                return false;
-            }
-            if (event instanceof Event) {
-                event.preventDefault();
-            }
-            this.menu.classList.add("open");
-            this.menu.classList.add("allowScroll");
-            this.menu.children[0].classList.add("activeList");
-            UiScreen.scrollDisable();
-            _pageContainer.classList.add("menuOverlay-" + this.menu.id);
-            UiScreen.pageOverlayOpen();
-            return true;
-        }
-        /**
-         * Closes the menu.
-         */
-        close(event) {
-            if (event instanceof Event) {
-                event.preventDefault();
-            }
-            if (this.menu.classList.contains("open")) {
-                this.menu.classList.remove("open");
-                UiScreen.scrollEnable();
-                UiScreen.pageOverlayClose();
-                _pageContainer.classList.remove("menuOverlay-" + this.menu.id);
-                return true;
-            }
-            return false;
-        }
-        /**
-         * Enables the touch menu.
-         */
-        enable() {
-            this.enabled = true;
-        }
-        /**
-         * Disables the touch menu.
-         */
-        disable() {
-            this.enabled = false;
-            this.close();
-        }
-        /**
-         * Initializes the Android Touch Menu.
-         */
-        initializeAndroid() {
-            // specify on which side of the page the menu appears
-            let appearsAt;
-            switch (this.menu.id) {
-                case "pageUserMenuMobile":
-                    appearsAt = "right";
-                    break;
-                case "pageMainMenuMobile":
-                    appearsAt = "left";
-                    break;
-                default:
-                    return;
-            }
-            const backdrop = this.menu.nextElementSibling;
-            // horizontal position of the touch start
-            let touchStart = undefined;
-            document.addEventListener("touchstart", (event) => {
-                const touches = event.touches;
-                let isLeftEdge;
-                let isRightEdge;
-                const isOpen = this.menu.classList.contains("open");
-                // check whether we touch the edges of the menu
-                if (appearsAt === "left") {
-                    isLeftEdge = !isOpen && touches[0].clientX < 20 /* AtEdge */;
-                    isRightEdge = isOpen && Math.abs(this.menu.offsetWidth - touches[0].clientX) < 20 /* AtEdge */;
-                }
-                else {
-                    isLeftEdge =
-                        isOpen &&
-                            Math.abs(document.body.clientWidth - this.menu.offsetWidth - touches[0].clientX) < 20 /* AtEdge */;
-                    isRightEdge = !isOpen && document.body.clientWidth - touches[0].clientX < 20 /* AtEdge */;
-                }
-                // abort if more than one touch
-                if (touches.length > 1) {
-                    if (_androidTouching) {
-                        Core.triggerEvent(document, "touchend");
-                    }
-                    return;
-                }
-                // break if a touch is in progress
-                if (_androidTouching) {
-                    return;
-                }
-                // break if no edge has been touched
-                if (!isLeftEdge && !isRightEdge) {
-                    return;
-                }
-                // break if a different menu is open
-                if (UiScreen.pageOverlayIsActive()) {
-                    const found = _pageContainer.classList.contains(`menuOverlay-${this.menu.id}`);
-                    if (!found) {
-                        return;
-                    }
-                }
-                // break if redactor is in use
-                if (document.documentElement.classList.contains("redactorActive")) {
-                    return;
-                }
-                touchStart = {
-                    x: touches[0].clientX,
-                    y: touches[0].clientY,
-                };
-                if (isLeftEdge) {
-                    _androidTouching = "left";
-                }
-                if (isRightEdge) {
-                    _androidTouching = "right";
-                }
-            });
-            document.addEventListener("touchend", (event) => {
-                // break if we did not start a touch
-                if (!_androidTouching || !touchStart) {
-                    return;
-                }
-                // break if the menu did not even start opening
-                if (!this.menu.classList.contains("open")) {
-                    // reset
-                    touchStart = undefined;
-                    _androidTouching = "";
-                    return;
-                }
-                // last known position of the finger
-                let position;
-                if (event) {
-                    position = event.changedTouches[0].clientX;
-                }
-                else {
-                    position = touchStart.x;
-                }
-                // clean up touch styles
-                this.menu.classList.add("androidMenuTouchEnd");
-                this.menu.style.removeProperty("transform");
-                backdrop.style.removeProperty(appearsAt);
-                this.menu.addEventListener("transitionend", () => {
-                    this.menu.classList.remove("androidMenuTouchEnd");
-                }, { once: true });
-                // check whether the user moved the finger far enough
-                if (appearsAt === "left") {
-                    if (_androidTouching === "left" && position < touchStart.x + 100) {
-                        this.close();
-                    }
-                    if (_androidTouching === "right" && position < touchStart.x - 100) {
-                        this.close();
-                    }
-                }
-                else {
-                    if (_androidTouching === "left" && position > touchStart.x + 100) {
-                        this.close();
-                    }
-                    if (_androidTouching === "right" && position > touchStart.x - 100) {
-                        this.close();
-                    }
-                }
-                // reset
-                touchStart = undefined;
-                _androidTouching = "";
-            });
-            document.addEventListener("touchmove", (event) => {
-                // break if we did not start a touch
-                if (!_androidTouching || !touchStart) {
-                    return;
-                }
-                const touches = event.touches;
-                // check whether the user started moving in the correct direction
-                // this avoids false positives, in case the user just wanted to tap
-                let movedFromEdge = false;
-                if (_androidTouching === "left") {
-                    movedFromEdge = touches[0].clientX > touchStart.x + 5 /* MovedHorizontally */;
-                }
-                if (_androidTouching === "right") {
-                    movedFromEdge = touches[0].clientX < touchStart.x - 5 /* MovedHorizontally */;
-                }
-                const movedVertically = Math.abs(touches[0].clientY - touchStart.y) > 20 /* MovedVertically */;
-                let isOpen = this.menu.classList.contains("open");
-                if (!isOpen && movedFromEdge && !movedVertically) {
-                    // the menu is not yet open, but the user moved into the right direction
-                    this.open();
-                    isOpen = true;
-                }
-                if (isOpen) {
-                    // update CSS to the new finger position
-                    let position = touches[0].clientX;
-                    if (appearsAt === "right") {
-                        position = document.body.clientWidth - position;
-                    }
-                    if (position > this.menu.offsetWidth) {
-                        position = this.menu.offsetWidth;
-                    }
-                    if (position < 0) {
-                        position = 0;
-                    }
-                    const offset = (appearsAt === "left" ? 1 : -1) * (position - this.menu.offsetWidth);
-                    this.menu.style.setProperty("transform", `translateX(${offset}px)`);
-                    backdrop.style.setProperty(appearsAt, Math.min(this.menu.offsetWidth, position).toString() + "px");
-                }
-            });
-        }
-        /**
-         * Initializes all menu items.
-         */
-        initItems() {
-            this.menu.querySelectorAll(".menuOverlayItemLink").forEach((element) => {
-                this.initItem(element);
-            });
-        }
-        /**
-         * Initializes a single menu item.
-         */
-        initItem(item) {
-            // check if it should contain a 'more' link w/ an external callback
-            const parent = item.parentElement;
-            const more = parent.dataset.more;
-            if (more) {
-                item.addEventListener("click", (event) => {
-                    event.preventDefault();
-                    event.stopPropagation();
-                    EventHandler.fire(this.eventIdentifier, "more", {
-                        handler: this,
-                        identifier: more,
-                        item: item,
-                        parent: parent,
-                    });
-                });
-                return;
-            }
-            const itemList = item.nextElementSibling;
-            if (itemList === null) {
-                return;
-            }
-            // handle static items with an icon-type button next to it (acp menu)
-            if (itemList.nodeName !== "OL" && itemList.classList.contains("menuOverlayItemLinkIcon")) {
-                // add wrapper
-                const wrapper = document.createElement("span");
-                wrapper.className = "menuOverlayItemWrapper";
-                parent.insertBefore(wrapper, item);
-                wrapper.appendChild(item);
-                while (wrapper.nextElementSibling) {
-                    wrapper.appendChild(wrapper.nextElementSibling);
-                }
-                return;
-            }
-            const isLink = item.getAttribute("href") !== "#";
-            const parentItemList = parent.parentElement;
-            let itemTitle = itemList.dataset.title;
-            this.items.set(item, {
-                itemList: itemList,
-                parentItemList: parentItemList,
-            });
-            if (!itemTitle) {
-                itemTitle = DomTraverse.childByClass(item, "menuOverlayItemTitle").textContent;
-                itemList.dataset.title = itemTitle;
-            }
-            const callbackLink = this.showItemList.bind(this, item);
-            if (isLink) {
-                const wrapper = document.createElement("span");
-                wrapper.className = "menuOverlayItemWrapper";
-                parent.insertBefore(wrapper, item);
-                wrapper.appendChild(item);
-                const moreLink = document.createElement("a");
-                moreLink.href = "#";
-                moreLink.className = "menuOverlayItemLinkIcon" + (item.classList.contains("active") ? " active" : "");
-                moreLink.innerHTML = '<span class="icon icon24 fa-angle-right"></span>';
-                moreLink.addEventListener("click", callbackLink);
-                wrapper.appendChild(moreLink);
-            }
-            else {
-                item.classList.add("menuOverlayItemLinkMore");
-                item.addEventListener("click", callbackLink);
-            }
-            const backLinkItem = document.createElement("li");
-            backLinkItem.className = "menuOverlayHeader";
-            const wrapper = document.createElement("span");
-            wrapper.className = "menuOverlayItemWrapper";
-            const backLink = document.createElement("a");
-            backLink.href = "#";
-            backLink.className = "menuOverlayItemLink menuOverlayBackLink";
-            backLink.textContent = parentItemList.dataset.title || "";
-            backLink.addEventListener("click", this.hideItemList.bind(this, item));
-            const closeLink = document.createElement("a");
-            closeLink.href = "#";
-            closeLink.className = "menuOverlayItemLinkIcon";
-            closeLink.innerHTML = '<span class="icon icon24 fa-times"></span>';
-            closeLink.addEventListener("click", this.close.bind(this));
-            wrapper.appendChild(backLink);
-            wrapper.appendChild(closeLink);
-            backLinkItem.appendChild(wrapper);
-            itemList.insertBefore(backLinkItem, itemList.firstElementChild);
-            if (!backLinkItem.nextElementSibling.classList.contains("menuOverlayTitle")) {
-                const titleItem = document.createElement("li");
-                titleItem.className = "menuOverlayTitle";
-                const title = document.createElement("span");
-                title.textContent = itemTitle;
-                titleItem.appendChild(title);
-                itemList.insertBefore(titleItem, backLinkItem.nextElementSibling);
-            }
-        }
-        /**
-         * Renders the menu item list header.
-         */
-        initHeader() {
-            const listItem = document.createElement("li");
-            listItem.className = "menuOverlayHeader";
-            const wrapper = document.createElement("span");
-            wrapper.className = "menuOverlayItemWrapper";
-            listItem.appendChild(wrapper);
-            const logoWrapper = document.createElement("span");
-            logoWrapper.className = "menuOverlayLogoWrapper";
-            wrapper.appendChild(logoWrapper);
-            const logo = document.createElement("span");
-            logo.className = "menuOverlayLogo";
-            const pageLogo = this.menu.dataset.pageLogo;
-            logo.style.setProperty("background-image", `url("${pageLogo}")`, "");
-            logoWrapper.appendChild(logo);
-            const closeLink = document.createElement("a");
-            closeLink.href = "#";
-            closeLink.className = "menuOverlayItemLinkIcon";
-            closeLink.innerHTML = '<span class="icon icon24 fa-times"></span>';
-            closeLink.addEventListener("click", this.close.bind(this));
-            wrapper.appendChild(closeLink);
-            const list = DomTraverse.childByClass(this.menu, "menuOverlayItemList");
-            list.insertBefore(listItem, list.firstElementChild);
-        }
-        /**
-         * Hides an item list, return to the parent item list.
-         */
-        hideItemList(item, event) {
-            if (event instanceof Event) {
-                event.preventDefault();
-            }
-            this.menu.classList.remove("allowScroll");
-            this.removeActiveList = true;
-            const data = this.items.get(item);
-            data.parentItemList.classList.remove("hidden");
-            this.updateDepth(false);
-        }
-        /**
-         * Shows the child item list.
-         */
-        showItemList(item, event) {
-            event.preventDefault();
-            const data = this.items.get(item);
-            const load = data.itemList.dataset.load;
-            if (load) {
-                if (!Core.stringToBool(item.dataset.loaded || "")) {
-                    const target = event.currentTarget;
-                    const icon = target.firstElementChild;
-                    if (icon.classList.contains("fa-angle-right")) {
-                        icon.classList.remove("fa-angle-right");
-                        icon.classList.add("fa-spinner");
-                    }
-                    EventHandler.fire(this.eventIdentifier, "load_" + load);
-                    return;
-                }
-            }
-            this.menu.classList.remove("allowScroll");
-            data.itemList.classList.add("activeList");
-            data.parentItemList.classList.add("hidden");
-            this.activeList.push(data.itemList);
-            this.updateDepth(true);
-        }
-        updateDepth(increase) {
-            this.depth += increase ? 1 : -1;
-            let offset = this.depth * -100;
-            if (Language.get("wcf.global.pageDirection") === "rtl") {
-                // reverse logic for RTL
-                offset *= -1;
-            }
-            const child = this.menu.children[0];
-            child.style.setProperty("transform", `translateX(${offset}%)`, "");
-        }
-        updateButtonState() {
-            let hasNewContent = false;
-            const itemList = this.menu.querySelector(".menuOverlayItemList");
-            this.menu.querySelectorAll(".badgeUpdate").forEach((badge) => {
-                const value = badge.textContent;
-                if (~~value > 0 && badge.closest(".menuOverlayItemList") === itemList) {
-                    hasNewContent = true;
-                }
-            });
-            this.button.classList[hasNewContent ? "add" : "remove"]("pageMenuMobileButtonHasContent");
-        }
-    }
-    Core.enableLegacyInheritance(UiPageMenuAbstract);
-    return UiPageMenuAbstract;
-});
diff --git a/wcfsetup/install/files/style/ui/menuMobile.scss b/wcfsetup/install/files/style/ui/menuMobile.scss
deleted file mode 100644 (file)
index 85f4de5..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-/* menu container */
-.menuOverlayMobile {
-       background-color: $wcfHeaderMenuBackground;
-       bottom: 0;
-       display: none;
-       overflow: hidden;
-       position: absolute;
-       top: 0;
-       z-index: 320;
-
-       &.open {
-               display: block;
-
-               @include screen-sm-up {
-                       + .menuOverlayMobileBackdrop {
-                               display: block;
-                       }
-               }
-       }
-
-       &.androidMenuTouchEnd {
-               display: block;
-               position: fixed;
-               transition: transform 0.24s cubic-bezier(0.25, 0.46, 0.45, 0.94);
-
-               &.pageMainMenuMobile:not(.open) {
-                       transform: translateX(-100vw);
-               }
-               &.pageUserMenuMobile:not(.open) {
-                       transform: translateX(100vw);
-               }
-
-               @include screen-sm-up {
-                       &.pageMainMenuMobile:not(.open) {
-                               transform: translateX(-350px);
-                       }
-                       &.pageUserMenuMobile:not(.open) {
-                               transform: translateX(350px);
-                       }
-
-                       + .menuOverlayMobileBackdrop {
-                               transition: left 0.24s cubic-bezier(0.25, 0.46, 0.45, 0.94),
-                                       right 0.24s cubic-bezier(0.25, 0.46, 0.45, 0.94);
-                       }
-               }
-       }
-
-       > .menuOverlayItemList {
-               // we use `transform: translateX()` for performance reasons
-               transition: transform 0.24s cubic-bezier(0.25, 0.46, 0.45, 0.94);
-
-               /* work-around to avoid setting explicit visibility */
-               visibility: visible;
-       }
-
-       &.allowScroll {
-               .menuOverlayItemList:not(.hidden) {
-                       overflow: auto;
-                       -webkit-overflow-scrolling: touch;
-               }
-       }
-
-       &:not(.allowScroll) {
-               // block UI while switching between menus
-               &::before {
-                       bottom: 0;
-                       content: "";
-                       left: 0;
-                       position: absolute;
-                       right: 0;
-                       top: 0;
-                       z-index: 500;
-               }
-       }
-
-       @include screen-xs {
-               left: 0;
-               max-width: 100vw;
-               right: 0;
-
-               .menuOverlayItemList {
-                       right: 0;
-               }
-       }
-
-       @include screen-sm-up {
-               width: 350px;
-
-               &.pageMainMenuMobile {
-                       left: 0;
-
-                       & + .menuOverlayMobileBackdrop {
-                               box-shadow: inset 5px 0 10px -5px rgba(0, 0, 0, 0.6);
-                               left: 350px;
-                       }
-
-                       .menuOverlayItemList {
-                               left: 0;
-                       }
-               }
-
-               &.pageUserMenuMobile {
-                       right: 0;
-
-                       & + .menuOverlayMobileBackdrop {
-                               box-shadow: inset -5px 0 10px -5px rgba(0, 0, 0, 0.6);
-                               right: 350px;
-                       }
-
-                       .menuOverlayItemList {
-                               right: 0;
-                       }
-               }
-       }
-}
-
-.menuOverlayMobileBackdrop {
-       background-color: rgba(0, 0, 0, 0.4);
-       bottom: 0;
-       display: none;
-       left: 0;
-       position: fixed;
-       right: 0;
-       top: 0;
-       z-index: 395;
-}
-
-.menuOverlayItemWrapper {
-       display: flex;
-       justify-content: flex-end;
-
-       > .menuOverlayItemLink {
-               flex: 1 1 auto;
-       }
-}
-
-.menuOverlayItemList {
-       background-color: $wcfHeaderMenuBackground;
-       height: 100%;
-       list-style-type: none;
-       margin: 0;
-       padding: 5px 0;
-       position: absolute;
-       top: 0;
-       left: -1px;
-       bottom: 0;
-       width: calc(100vw + 1px);
-       z-index: 450;
-
-       @include screen-sm-up {
-               width: 350px;
-       }
-
-       &:not(.activeList) {
-               display: none;
-       }
-}
-
-.menuOverlayItemSpacer {
-       margin-top: 25px;
-
-       /* avoid successive spacers piling up */
-       & + .menuOverlayItemSpacer {
-               display: none;
-       }
-}
-
-.menuOverlayItem {
-       &:not(:last-child) {
-               margin-bottom: 1px;
-       }
-
-       /* nested item list */
-       > .menuOverlayItemList {
-               margin-left: 100%;
-               z-index: 500;
-       }
-}
-
-.menuOverlayItemLink,
-.menuOverlayTitle,
-.menuOverlayBackLink {
-       color: $wcfHeaderMenuLink;
-       display: block;
-       font-size: 14px;
-       padding: 10px 30px;
-       position: relative;
-}
-
-.menuOverlayItemLink {
-       align-items: center;
-       background-color: $wcfHeaderMenuLinkBackground;
-       display: flex;
-       overflow: hidden;
-       text-overflow: ellipsis;
-       white-space: nowrap;
-
-       .icon::before {
-               color: $wcfHeaderMenuLink;
-       }
-
-       &:hover {
-               color: $wcfHeaderMenuLinkActive;
-       }
-
-       /* wrapper class for links containing an additional badge */
-       &.menuOverlayItemBadge {
-               align-items: center;
-               display: flex;
-               padding-right: 10px;
-
-               /* different padding if there is no additional icon after the link,
-                  ensures proper alignment for links with badges containing a child
-                  item list */
-               &:last-child {
-                       /* 55px = 10px padding + 1px margin + icon */
-                       /* icon = 2x 10px padding + 16px width */
-                       padding-right: 55px;
-               }
-
-               > .menuOverlayItemTitle {
-                       flex: 1 1 auto;
-               }
-
-               > .badge {
-                       flex: 0 0 auto;
-               }
-       }
-
-       &.menuOverlayItemLinkMore::after {
-               color: $wcfHeaderMenuLink;
-               content: $fa-var-angle-right;
-               display: block;
-               font-family: FontAwesome;
-               font-size: 18px;
-               position: absolute;
-               right: 18px;
-               top: 50%;
-               transform: translateY(-50%);
-       }
-
-       .menuOverlayItemTitle {
-               overflow: hidden;
-               text-overflow: ellipsis;
-       }
-}
-
-/* fix icons in rtl design */
-html[dir="rtl"] .menuOverlayItemLink.menuOverlayItemLinkMore::after {
-       content: $fa-var-angle-left;
-}
-
-.pageUserMenuMobile .menuOverlayItemBadge:last-child {
-       padding-right: 10px !important;
-}
-
-.menuOverlayItemLink.active,
-.menuOverlayItemLinkIcon.active {
-       background-color: $wcfHeaderMenuLinkBackgroundActive;
-       color: $wcfHeaderMenuLinkActive;
-}
-
-.menuOverlayItemLinkIcon.active > .icon::before {
-       color: $wcfHeaderMenuLinkActive;
-}
-
-.menuOverlayTitle {
-       color: rgba($wcfHeaderMenuLink, 0.7);
-       overflow: hidden;
-       text-overflow: ellipsis;
-       white-space: nowrap;
-
-       &:not(:first-child) {
-               margin-top: 10px;
-       }
-}
-
-/* icon link sharing the space with a link or (header only) the logo */
-.menuOverlayItemLinkIcon {
-       background-color: $wcfHeaderMenuLinkBackground;
-       flex: 0 0 auto;
-       margin-left: 1px;
-       padding: 10px;
-
-       /* force explicit dimensions because no each .icon24 is of equal height/width */
-       height: 44px;
-       width: 44px;
-
-       > .icon::before {
-               color: $wcfHeaderMenuLink;
-       }
-}
-
-.menuOverlayBackLink::before {
-       color: rgba($wcfHeaderMenuLink, 0.7);
-       content: $fa-var-angle-left;
-       display: block;
-       font-family: FontAwesome;
-       font-size: 18px;
-       position: absolute;
-       left: 12px;
-       top: 50%;
-       transform: translateY(-50%);
-}
-
-.menuOverlayLogoWrapper {
-       flex: 1 1 auto;
-       padding: 5px;
-       display: flex;
-
-       .menuOverlayLogo {
-               flex: 1 1 auto;
-               background-size: contain;
-               background-repeat: no-repeat;
-               background-position: center;
-       }
-}