fix(ui): body data-bs-no-jquery (real Fomantic fix) + login/navbar favicon (#719 #819) #859

Merged
jmiller merged 3 commits from feat/mobile-retheme into dev 2026-07-21 20:09:30 +00:00
5 changed files with 6 additions and 40 deletions
+1 -1
View File
@@ -36,7 +36,7 @@
}
</script>
</head>
<body>
<body data-bs-no-jquery>
{{template "custom/body_outer_pre" .}}
<div class="full height">
+1 -1
View File
@@ -2,7 +2,7 @@
<div class="navbar-left">
<!-- the logo -->
<a class="item" id="navbar-logo" href="{{AppSubUrl}}/" aria-label="{{if .IsSigned}}{{ctx.Locale.Tr "dashboard"}}{{else}}{{ctx.Locale.Tr "home_title"}}{{end}}">
<img width="30" height="30" src="{{AssetUrlPrefix}}/img/logo.svg" alt="{{ctx.Locale.Tr "logo"}}" aria-hidden="true" onerror="this.src='{{AssetUrlPrefix}}/img/logo.png'">
<img width="30" height="30" src="{{AssetUrlPrefix}}/img/favicon.svg" alt="{{ctx.Locale.Tr "logo"}}" aria-hidden="true" onerror="this.src='{{AssetUrlPrefix}}/img/favicon.png'">
</a>
<!-- mobile right menu, it must be here because in mobile view, each item is a flex column, the first item is a full row column -->
+1 -1
View File
@@ -1,6 +1,6 @@
<div class="ui container fluid">
<div class="tw-text-center tw-mb-4">
<img src="{{AssetUrlPrefix}}/img/login-logo.png" style="max-width: 220px; max-height: 80px; object-fit: contain;" onerror="this.style.display='none'">
<img src="{{AssetUrlPrefix}}/img/favicon.svg" alt="{{AppName}}" style="max-width: 220px; max-height: 80px; object-fit: contain;" onerror="if(!this.dataset.fb){this.dataset.fb=1;this.src='{{AssetUrlPrefix}}/img/favicon.png';}else{this.style.display='none';}">
</div>
{{if or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeSignIn)}}
{{template "base/alert" .}}
+3 -4
View File
@@ -1,11 +1,10 @@
import '../fomantic/build/fomantic.js';
import '../css/index.css';
// MokoGIT: vendored Bootstrap 5.3.3 JS bundle (incl. Popper; registers the data-bs-* API).
// `<body data-bs-no-jquery>` (templates/base/head.tmpl) makes Bootstrap's getjQuery() return
// null, so it never registers jQuery plugins and never clobbers Fomantic's $.fn.{dropdown,
// modal,tab,...}. Bootstrap's data-bs-* data-API keeps working (it's bound independently).
import './vendor/bootstrap/bootstrap.bundle.min.js';
// Hand Fomantic's jQuery plugin names back after Bootstrap's defineJQueryPlugin clobbers
// them (dropdown/modal/tab/…); keeps Bootstrap's data-bs-* API working. MUST stay right
// after the bundle import above.
import './vendor/bootstrap/noconflict.ts';
import {initDashboardRepoList} from './features/dashboard.ts';
import {initGlobalCopyToClipboardListener} from './features/clipboard.ts';
-33
View File
@@ -1,33 +0,0 @@
// MokoGIT: Bootstrap 5 / Fomantic-UI jQuery-plugin no-conflict shim.
//
// Bootstrap 5 dropped its own jQuery dependency but still registers jQuery plugins
// (via `defineJQueryPlugin`) when it detects jQuery on the page. Those plugin names
// — dropdown, modal, tab, collapse, tooltip, popover, toast, button, … — collide with
// Fomantic-UI, which Gitea drives through the very same `$.fn.*` names. The clobber
// makes `$.fn.dropdown.settings` undefined, so Gitea's Fomantic init throws
// (`Cannot set properties of undefined (setting 'fullTextSearch')`) and aborts the
// whole client init pipeline.
//
// Bootstrap keeps the previous implementation on each plugin's `.noConflict()`. Calling
// it hands the name back to Fomantic. We do NOT lose Bootstrap behavior: the mobile
// rewrite drives Bootstrap purely through the `data-bs-*` data-API (collapse drawers,
// table-responsive is CSS-only), which is bound to document-level event handlers at
// bundle load and does not depend on the jQuery interface.
//
// This module MUST be imported immediately AFTER the Bootstrap bundle in index.ts so it
// runs after `defineJQueryPlugin` has clobbered the names.
import $ from 'jquery';
const collidingPlugins = [
'alert', 'button', 'carousel', 'collapse', 'dropdown', 'modal',
'offcanvas', 'popover', 'scrollspy', 'tab', 'toast', 'tooltip',
];
for (const name of collidingPlugins) {
const plugin = ($.fn as Record<string, any>)[name];
if (plugin && typeof plugin.noConflict === 'function') {
// Restores the pre-Bootstrap implementation (Fomantic's, or undefined if Fomantic
// never defined it — harmless, since nothing uses the jQuery interface for it).
plugin.noConflict();
}
}