Skip to content

Fix dynamic content loading init problem #33748

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions templates/repo/diff/box.tmpl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{{$showFileTree := (and (not .DiffNotAvailable) (gt .Diff.NumFiles 1))}}
<div>
<div class="diff-detail-box diff-box">
<div class="diff-detail-box">
<div class="tw-flex tw-items-center tw-flex-wrap tw-gap-2 tw-ml-0.5">
{{if $showFileTree}}
<button class="diff-toggle-file-tree-button not-mobile btn interact-fg" data-show-text="{{ctx.Locale.Tr "repo.diff.show_file_tree"}}" data-hide-text="{{ctx.Locale.Tr "repo.diff.hide_file_tree"}}">
Expand Down Expand Up @@ -80,7 +80,7 @@
{{$showFileViewToggle := or $isImage (and (not $file.IsIncomplete) $isCsv)}}
{{$isExpandable := or (gt $file.Addition 0) (gt $file.Deletion 0) $file.IsBin}}
{{$isReviewFile := and $.IsSigned $.PageIsPullFiles (not $.Repository.IsArchived) $.IsShowingAllCommits}}
<div class="diff-file-box diff-box file-content {{TabSizeClass $.Editorconfig $file.Name}} tw-mt-0" id="diff-{{$file.NameHash}}" data-old-filename="{{$file.OldName}}" data-new-filename="{{$file.Name}}" {{if or ($file.ShouldBeHidden) (not $isExpandable)}}data-folded="true"{{end}}>
<div class="diff-file-box file-content {{TabSizeClass $.Editorconfig $file.Name}} tw-mt-0" id="diff-{{$file.NameHash}}" data-old-filename="{{$file.OldName}}" data-new-filename="{{$file.Name}}" {{if or ($file.ShouldBeHidden) (not $isExpandable)}}data-folded="true"{{end}}>
<h4 class="diff-file-header sticky-2nd-row ui top attached header">
<div class="diff-file-name tw-flex tw-flex-1 tw-items-center tw-gap-1 tw-flex-wrap">
<button class="fold-file btn interact-bg tw-p-1{{if not $isExpandable}} tw-invisible{{end}}">
Expand Down Expand Up @@ -209,7 +209,7 @@
{{end}}

{{if .Diff.IsIncomplete}}
<div class="diff-file-box diff-box file-content tw-mt-2" id="diff-incomplete">
<div class="diff-file-box file-content tw-mt-2" id="diff-incomplete">
<h4 class="ui top attached header tw-font-normal tw-flex tw-items-center tw-justify-between">
{{ctx.Locale.Tr "repo.diff.too_many_files"}}
<a class="ui basic tiny button" id="diff-show-more-files" data-href="?skip-to={{.Diff.End}}&file-only=true">{{ctx.Locale.Tr "repo.diff.show_more"}}</a>
Expand Down
2 changes: 1 addition & 1 deletion templates/repo/issue/view_content/add_reaction.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<a class="muted">{{svg "octicon-smiley"}}</a>
<div class="menu">
{{range $value := AllowedReactions}}
<a class="item emoji comment-reaction-button" data-tooltip-content="{{$value}}" aria-label="{{$value}}" data-reaction-content="{{$value}}">{{ReactionToEmoji $value}}</a>
<a class="item emoji" data-tooltip-content="{{$value}}" aria-label="{{$value}}" data-reaction-content="{{$value}}" data-global-click="onCommentReactionButtonClick">{{ReactionToEmoji $value}}</a>
{{end}}
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion templates/repo/issue/view_content/conversation.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
{{if $diff}}
{{$file := (index $diff.Files 0)}}
<div id="code-preview-{{$comment.ID}}" class="ui table segment{{if $resolved}} tw-hidden{{end}}">
<div class="diff-file-box diff-box file-content {{TabSizeClass $.Editorconfig $file.Name}}">
<div class="diff-file-box file-content {{TabSizeClass $.Editorconfig $file.Name}}">
<div class="file-body file-code code-view code-diff code-diff-unified unicode-escaped">
<table>
<tbody>
Expand Down
6 changes: 3 additions & 3 deletions templates/repo/issue/view_content/reactions.tmpl
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<div class="bottom-reactions" data-action-url="{{$.ActionURL}}">
{{range $key, $value := .Reactions}}
{{$hasReacted := $value.HasUser ctx.RootData.SignedUserID}}
<a role="button" class="ui label basic{{if $hasReacted}} primary{{end}}{{if not ctx.RootData.IsSigned}} disabled{{end}} comment-reaction-button"
data-tooltip-content
title="{{$value.GetFirstUsers}}{{if gt ($value.GetMoreUserCount) 0}} {{ctx.Locale.Tr "repo.reactions_more" $value.GetMoreUserCount}}{{end}}"
<a role="button" class="ui label basic{{if $hasReacted}} primary{{end}}{{if not ctx.RootData.IsSigned}} disabled{{end}}"
data-global-click="onCommentReactionButtonClick"
data-tooltip-content title="{{$value.GetFirstUsers}}{{if gt ($value.GetMoreUserCount) 0}} {{ctx.Locale.Tr "repo.reactions_more" $value.GetMoreUserCount}}{{end}}"
aria-label="{{$value.GetFirstUsers}}{{if gt ($value.GetMoreUserCount) 0}} {{ctx.Locale.Tr "repo.reactions_more" $value.GetMoreUserCount}}{{end}}"
data-tooltip-placement="bottom-start"
data-reaction-content="{{$key}}" data-has-reacted="{{$hasReacted}}">
Expand Down
2 changes: 1 addition & 1 deletion templates/shared/search/code/results.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<div class="repository search">
{{range $result := .SearchResults}}
{{$repo := or $.Repo (index $.RepoMaps .RepoID)}}
<div class="diff-file-box diff-box file-content non-diff-file-content repo-search-result">
<div class="diff-file-box file-content non-diff-file-content repo-search-result">
<h4 class="ui top attached header tw-font-normal tw-flex tw-flex-wrap">
{{if not $.Repo}}
<span class="file tw-flex-1">
Expand Down
4 changes: 0 additions & 4 deletions web_src/css/repo.css
Original file line number Diff line number Diff line change
Expand Up @@ -1085,10 +1085,6 @@ td .commit-summary {
height: 30px;
}

.repository .diff-box .resolved-placeholder .button {
padding: 8px 12px;
}

.repository .diff-file-box .header {
background-color: var(--color-box-header);
}
Expand Down
79 changes: 42 additions & 37 deletions web_src/js/features/common-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {GET} from '../modules/fetch.ts';
import {showGlobalErrorMessage} from '../bootstrap.ts';
import {fomanticQuery} from '../modules/fomantic/base.ts';
import {queryElems} from '../utils/dom.ts';
import {observeAddedElement} from '../modules/observer.ts';

const {appUrl} = window.config;

Expand All @@ -28,47 +29,51 @@ export function initFootLanguageMenu() {
}

export function initGlobalDropdown() {
// Semantic UI modules.
const $uiDropdowns = fomanticQuery('.ui.dropdown');

// do not init "custom" dropdowns, "custom" dropdowns are managed by their own code.
$uiDropdowns.filter(':not(.custom)').dropdown({hideDividers: 'empty'});
observeAddedElement('.ui.dropdown:not(.custom)', (el) => {
const $dropdown = fomanticQuery(el);
if ($dropdown.data('module-dropdown')) return; // do not re-init if other code has already initialized it.

// The "jump" means this dropdown is mainly used for "menu" purpose,
// clicking an item will jump to somewhere else or trigger an action/function.
// When a dropdown is used for non-refresh actions with tippy,
// it must have this "jump" class to hide the tippy when dropdown is closed.
$uiDropdowns.filter('.jump').dropdown('setting', {
action: 'hide',
onShow() {
// hide associated tooltip while dropdown is open
this._tippy?.hide();
this._tippy?.disable();
},
onHide() {
this._tippy?.enable();
// eslint-disable-next-line unicorn/no-this-assignment
const elDropdown = this;
$dropdown.dropdown('setting', {hideDividers: 'empty'});

// hide all tippy elements of items after a while. eg: use Enter to click "Copy Link" in the Issue Context Menu
setTimeout(() => {
const $dropdown = fomanticQuery(elDropdown);
if ($dropdown.dropdown('is hidden')) {
queryElems(elDropdown, '.menu > .item', (el) => el._tippy?.hide());
}
}, 2000);
},
});
if (el.classList.contains('jump')) {
// The "jump" means this dropdown is mainly used for "menu" purpose,
// clicking an item will jump to somewhere else or trigger an action/function.
// When a dropdown is used for non-refresh actions with tippy,
// it must have this "jump" class to hide the tippy when dropdown is closed.
$dropdown.dropdown('setting', {
action: 'hide',
onShow() {
// hide associated tooltip while dropdown is open
this._tippy?.hide();
this._tippy?.disable();
},
onHide() {
this._tippy?.enable();
// eslint-disable-next-line unicorn/no-this-assignment
const elDropdown = this;

// Special popup-directions, prevent Fomantic from guessing the popup direction.
// With default "direction: auto", if the viewport height is small, Fomantic would show the popup upward,
// if the dropdown is at the beginning of the page, then the top part would be clipped by the window view.
// eg: Issue List "Sort" dropdown
// But we can not set "direction: downward" for all dropdowns, because there is a bug in dropdown menu positioning when calculating the "left" position,
// which would make some dropdown popups slightly shift out of the right viewport edge in some cases.
// eg: the "Create New Repo" menu on the navbar.
$uiDropdowns.filter('.upward').dropdown('setting', 'direction', 'upward');
$uiDropdowns.filter('.downward').dropdown('setting', 'direction', 'downward');
// hide all tippy elements of items after a while. eg: use Enter to click "Copy Link" in the Issue Context Menu
setTimeout(() => {
const $dropdown = fomanticQuery(elDropdown);
if ($dropdown.dropdown('is hidden')) {
queryElems(elDropdown, '.menu > .item', (el) => el._tippy?.hide());
}
}, 2000);
},
});
}

// Special popup-directions, prevent Fomantic from guessing the popup direction.
// With default "direction: auto", if the viewport height is small, Fomantic would show the popup upward,
// if the dropdown is at the beginning of the page, then the top part would be clipped by the window view.
// eg: Issue List "Sort" dropdown
// But we can not set "direction: downward" for all dropdowns, because there is a bug in dropdown menu positioning when calculating the "left" position,
// which would make some dropdown popups slightly shift out of the right viewport edge in some cases.
// eg: the "Create New Repo" menu on the navbar.
if (el.classList.contains('upward')) $dropdown.dropdown('setting', 'direction', 'upward');
if (el.classList.contains('downward')) $dropdown.dropdown('setting', 'direction', 'downward');
});
}

export function initGlobalTabularMenu() {
Expand Down
48 changes: 21 additions & 27 deletions web_src/js/features/comp/ReactionSelector.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,31 @@
import {POST} from '../../modules/fetch.ts';
import {fomanticQuery} from '../../modules/fomantic/base.ts';
import type {DOMEvent} from '../../utils/dom.ts';
import {registerGlobalEventFunc} from '../../modules/observer.ts';

export function initCompReactionSelector(parent: ParentNode = document) {
for (const container of parent.querySelectorAll<HTMLElement>('.issue-content, .diff-file-body')) {
container.addEventListener('click', async (e: DOMEvent<MouseEvent>) => {
// there are 2 places for the "reaction" buttons, one is the top-right reaction menu, one is the bottom of the comment
const target = e.target.closest('.comment-reaction-button');
if (!target) return;
e.preventDefault();
export function initCompReactionSelector() {
registerGlobalEventFunc('click', 'onCommentReactionButtonClick', async (target: HTMLElement, e: DOMEvent<MouseEvent>) => {
// there are 2 places for the "reaction" buttons, one is the top-right reaction menu, one is the bottom of the comment
e.preventDefault();

if (target.classList.contains('disabled')) return;
if (target.classList.contains('disabled')) return;

const actionUrl = target.closest('[data-action-url]').getAttribute('data-action-url');
const reactionContent = target.getAttribute('data-reaction-content');
const actionUrl = target.closest('[data-action-url]').getAttribute('data-action-url');
const reactionContent = target.getAttribute('data-reaction-content');

const commentContainer = target.closest('.comment-container');
const commentContainer = target.closest('.comment-container');

const bottomReactions = commentContainer.querySelector('.bottom-reactions'); // may not exist if there is no reaction
const bottomReactionBtn = bottomReactions?.querySelector(`a[data-reaction-content="${CSS.escape(reactionContent)}"]`);
const hasReacted = bottomReactionBtn?.getAttribute('data-has-reacted') === 'true';
const bottomReactions = commentContainer.querySelector('.bottom-reactions'); // may not exist if there is no reaction
const bottomReactionBtn = bottomReactions?.querySelector(`a[data-reaction-content="${CSS.escape(reactionContent)}"]`);
const hasReacted = bottomReactionBtn?.getAttribute('data-has-reacted') === 'true';

const res = await POST(`${actionUrl}/${hasReacted ? 'unreact' : 'react'}`, {
data: new URLSearchParams({content: reactionContent}),
});

const data = await res.json();
bottomReactions?.remove();
if (data.html) {
commentContainer.insertAdjacentHTML('beforeend', data.html);
const bottomReactionsDropdowns = commentContainer.querySelectorAll('.bottom-reactions .dropdown.select-reaction');
fomanticQuery(bottomReactionsDropdowns).dropdown(); // re-init the dropdown
}
const res = await POST(`${actionUrl}/${hasReacted ? 'unreact' : 'react'}`, {
data: new URLSearchParams({content: reactionContent}),
});
}

const data = await res.json();
bottomReactions?.remove();
if (data.html) {
commentContainer.insertAdjacentHTML('beforeend', data.html);
}
});
}
15 changes: 5 additions & 10 deletions web_src/js/features/repo-diff.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {initCompReactionSelector} from './comp/ReactionSelector.ts';
import {initRepoIssueContentHistory} from './repo-issue-content.ts';
import {initDiffFileTree} from './repo-diff-filetree.ts';
import {initDiffCommitSelect} from './repo-diff-commitselect.ts';
Expand All @@ -8,17 +7,16 @@ import {initImageDiff} from './imagediff.ts';
import {showErrorToast} from '../modules/toast.ts';
import {submitEventSubmitter, queryElemSiblings, hideElem, showElem, animateOnce, addDelegatedEventListener, createElementFromHTML, queryElems} from '../utils/dom.ts';
import {POST, GET} from '../modules/fetch.ts';
import {fomanticQuery} from '../modules/fomantic/base.ts';
import {createTippy} from '../modules/tippy.ts';
import {invertFileFolding} from './file-fold.ts';
import {parseDom} from '../utils.ts';
import {observeAddedElement} from '../modules/observer.ts';

const {i18n} = window.config;

function initRepoDiffFileViewToggle() {
function initRepoDiffFileBox(el: HTMLElement) {
// switch between "rendered" and "source", for image and CSV files
// FIXME: this event listener is not correctly added to "load more files"
queryElems(document, '.file-view-toggle', (btn) => btn.addEventListener('click', () => {
queryElems(el, '.file-view-toggle', (btn) => btn.addEventListener('click', () => {
queryElemSiblings(btn, '.file-view-toggle', (el) => el.classList.remove('active'));
btn.classList.add('active');

Expand Down Expand Up @@ -75,7 +73,6 @@ function initRepoDiffConversationForm() {
el.classList.add('tw-invisible');
}
}
fomanticQuery(newConversationHolder.querySelectorAll('.ui.dropdown')).dropdown();

// the default behavior is to add a pending review, so if no submitter, it also means "pending_review"
if (!submitter || submitter?.matches('button[name="pending_review"]')) {
Expand Down Expand Up @@ -110,8 +107,6 @@ function initRepoDiffConversationForm() {
if (elConversationHolder) {
const elNewConversation = createElementFromHTML(data);
elConversationHolder.replaceWith(elNewConversation);
queryElems(elConversationHolder, '.ui.dropdown:not(.custom)', (el) => fomanticQuery(el).dropdown());
initCompReactionSelector(elNewConversation);
} else {
window.location.reload();
}
Expand Down Expand Up @@ -149,7 +144,7 @@ function initDiffHeaderPopup() {

// Will be called when the show more (files) button has been pressed
function onShowMoreFiles() {
// FIXME: here the init calls are incomplete: at least it misses dropdown & initCompReactionSelector & initRepoDiffFileViewToggle
// TODO: replace these calls with the "observer.ts" methods
initRepoIssueContentHistory();
initViewedCheckboxListenerFor();
countAndUpdateViewedFiles();
Expand Down Expand Up @@ -255,11 +250,11 @@ export function initRepoDiffView() {
initDiffCommitSelect();
initRepoDiffShowMore();
initDiffHeaderPopup();
initRepoDiffFileViewToggle();
initViewedCheckboxListenerFor();
initExpandAndCollapseFilesButton();
initRepoDiffHashChangeListener();

observeAddedElement('#diff-file-boxes .diff-file-box', initRepoDiffFileBox);
addDelegatedEventListener(document, 'click', '.fold-file', (el) => {
invertFileFolding(el.closest('.file-content'), el);
});
Expand Down
5 changes: 3 additions & 2 deletions web_src/js/features/repo-graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ export function initRepoGraphGit() {
}

const flowSelectRefsDropdown = document.querySelector('#flow-select-refs-dropdown');
fomanticQuery(flowSelectRefsDropdown).dropdown('set selected', dropdownSelected);
fomanticQuery(flowSelectRefsDropdown).dropdown({
const $dropdown = fomanticQuery(flowSelectRefsDropdown);
$dropdown.dropdown({
clearable: true,
fullTextSeach: 'exact',
onRemove(toRemove: string) {
Expand All @@ -110,6 +110,7 @@ export function initRepoGraphGit() {
updateGraph();
},
});
$dropdown.dropdown('set selected', dropdownSelected);

graphContainer.addEventListener('mouseenter', (e: DOMEvent<MouseEvent>) => {
if (e.target.matches('#rev-list li')) {
Expand Down
4 changes: 2 additions & 2 deletions web_src/js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ import {initRepoContributors} from './features/contributors.ts';
import {initRepoCodeFrequency} from './features/code-frequency.ts';
import {initRepoRecentCommits} from './features/recent-commits.ts';
import {initRepoDiffCommitBranchesAndTags} from './features/repo-diff-commit.ts';
import {initDirAuto} from './modules/dirauto.ts';
import {initAddedElementObserver} from './modules/observer.ts';
import {initRepositorySearch} from './features/repo-search.ts';
import {initColorPickers} from './features/colorpicker.ts';
import {initAdminSelfCheck} from './features/admin/selfcheck.ts';
Expand All @@ -86,7 +86,7 @@ import {
} from './features/common-form.ts';

initGiteaFomantic();
initDirAuto();
initAddedElementObserver();
initSubmitEventPolyfill();

function callInitFunctions(functions: (() => any)[]) {
Expand Down
44 changes: 0 additions & 44 deletions web_src/js/modules/dirauto.ts

This file was deleted.

Loading
Loading