diff options
author | wxiaoguang <wxiaoguang@gmail.com> | 2023-05-30 18:53:15 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-30 18:53:15 +0800 |
commit | ee99cf6313ba565523b3c43f61ffda4b71e2c39b (patch) | |
tree | 176d0044803285f2cdbcf04cbf87edd2f0d07a1a /web_src | |
parent | 32185efc1484c1d6ea3a5262a3c9779e8edb0b09 (diff) | |
download | gitea-ee99cf6313ba565523b3c43f61ffda4b71e2c39b.tar.gz gitea-ee99cf6313ba565523b3c43f61ffda4b71e2c39b.zip |
Refactor diffFileInfo / DiffTreeStore (#24998)
Follow #21012, #22399
Replace #24983, fix #24938
Help #24956
Now, the `window.config.pageData.diffFileInfo` itself is a reactive
store, so it's quite easy to sync values/states by it, no need to do
"doLoadMoreFiles" or "callback".
Screenshot: these two buttons both work. After complete loading, the UI
is also right.
<details>
![image](https://github.com/go-gitea/gitea/assets/2114189/cc6310fd-7f27-45ea-ab4f-24952a87b421)
![image](https://github.com/go-gitea/gitea/assets/2114189/4c11dd67-ac03-4568-8541-91204d27a4e3)
![image](https://github.com/go-gitea/gitea/assets/2114189/38a22cec-41be-41e6-a209-f347b7a4c1de)
</details>
Diffstat (limited to 'web_src')
-rw-r--r-- | web_src/js/components/DiffFileList.vue | 28 | ||||
-rw-r--r-- | web_src/js/components/DiffFileTree.vue | 42 | ||||
-rw-r--r-- | web_src/js/components/DiffFileTreeItem.vue | 4 | ||||
-rw-r--r-- | web_src/js/features/repo-diff.js | 39 | ||||
-rw-r--r-- | web_src/js/modules/stores.js | 11 |
5 files changed, 51 insertions, 73 deletions
diff --git a/web_src/js/components/DiffFileList.vue b/web_src/js/components/DiffFileList.vue index 658357a887..131be01811 100644 --- a/web_src/js/components/DiffFileList.vue +++ b/web_src/js/components/DiffFileList.vue @@ -1,10 +1,10 @@ <template> - <ol class="diff-detail-box diff-stats gt-m-0" ref="root" v-if="fileListIsVisible"> - <li v-for="file in files" :key="file.NameHash"> + <ol class="diff-detail-box diff-stats gt-m-0" ref="root" v-if="store.fileListIsVisible"> + <li v-for="file in store.files" :key="file.NameHash"> <div class="gt-font-semibold gt-df gt-ac pull-right"> - <span v-if="file.IsBin" class="gt-ml-1 gt-mr-3">{{ binaryFileMessage }}</span> + <span v-if="file.IsBin" class="gt-ml-1 gt-mr-3">{{ store.binaryFileMessage }}</span> {{ file.IsBin ? '' : file.Addition + file.Deletion }} - <span v-if="!file.IsBin" class="diff-stats-bar gt-mx-3" :data-tooltip-content="statisticsMessage.replace('%d', (file.Addition + file.Deletion)).replace('%d', file.Addition).replace('%d', file.Deletion)"> + <span v-if="!file.IsBin" class="diff-stats-bar gt-mx-3" :data-tooltip-content="store.statisticsMessage.replace('%d', (file.Addition + file.Deletion)).replace('%d', file.Addition).replace('%d', file.Deletion)"> <div class="diff-stats-add-bar" :style="{ 'width': diffStatsWidth(file.Addition, file.Deletion) }"/> </span> </div> @@ -12,22 +12,21 @@ <span :class="['status', diffTypeToString(file.Type)]" :data-tooltip-content="diffTypeToString(file.Type)"> </span> <a class="file gt-mono" :href="'#diff-' + file.NameHash">{{ file.Name }}</a> </li> - <li v-if="isIncomplete" id="diff-too-many-files-stats" class="gt-pt-2"> - <span class="file gt-df gt-ac gt-sb">{{ tooManyFilesMessage }} - <a :class="['ui', 'basic', 'tiny', 'button', isLoadingNewData === true ? 'disabled' : '']" id="diff-show-more-files-stats" @click.stop="loadMoreData">{{ showMoreMessage }}</a> + <li v-if="store.isIncomplete" class="gt-pt-2"> + <span class="file gt-df gt-ac gt-sb">{{ store.tooManyFilesMessage }} + <a :class="['ui', 'basic', 'tiny', 'button', store.isLoadingNewData ? 'disabled' : '']" @click.stop="loadMoreData">{{ store.showMoreMessage }}</a> </span> </li> </ol> </template> <script> -import {doLoadMoreFiles} from '../features/repo-diff.js'; - -const {pageData} = window.config; +import {loadMoreFiles} from '../features/repo-diff.js'; +import {diffTreeStore} from '../modules/stores.js'; export default { data: () => { - return pageData.diffFileInfo; + return {store: diffTreeStore()}; }, mounted() { document.getElementById('show-file-list-btn').addEventListener('click', this.toggleFileList); @@ -37,7 +36,7 @@ export default { }, methods: { toggleFileList() { - this.fileListIsVisible = !this.fileListIsVisible; + this.store.fileListIsVisible = !this.store.fileListIsVisible; }, diffTypeToString(pType) { const diffTypes = { @@ -53,10 +52,7 @@ export default { return `${adds / (adds + dels) * 100}%`; }, loadMoreData() { - this.isLoadingNewData = true; - doLoadMoreFiles(this.link, this.diffEnd, () => { - this.isLoadingNewData = false; - }); + loadMoreFiles(this.store.linkLoadMore); } }, }; diff --git a/web_src/js/components/DiffFileTree.vue b/web_src/js/components/DiffFileTree.vue index 6ac16def99..734ad80e8b 100644 --- a/web_src/js/components/DiffFileTree.vue +++ b/web_src/js/components/DiffFileTree.vue @@ -1,42 +1,33 @@ <template> - <div - v-if="fileTreeIsVisible" - class="gt-mr-3 gt-mt-3 diff-detail-box" - > + <div v-if="store.fileTreeIsVisible" class="gt-mr-3 gt-mt-3 diff-detail-box"> <!-- only render the tree if we're visible. in many cases this is something that doesn't change very often --> <div class="ui list"> <DiffFileTreeItem v-for="item in fileTree" :key="item.name" :item="item"/> </div> - <div v-if="isIncomplete" id="diff-too-many-files-stats" class="gt-pt-2"> - <span class="gt-mr-2">{{ tooManyFilesMessage }}</span><a :class="['ui', 'basic', 'tiny', 'button', isLoadingNewData === true ? 'disabled' : '']" id="diff-show-more-files-stats" @click.stop="loadMoreData">{{ showMoreMessage }}</a> + <div v-if="store.isIncomplete" class="gt-pt-2"> + <a :class="['ui', 'basic', 'tiny', 'button', store.isLoadingNewData ? 'disabled' : '']" @click.stop="loadMoreData">{{ store.showMoreMessage }}</a> </div> </div> </template> <script> import DiffFileTreeItem from './DiffFileTreeItem.vue'; -import {doLoadMoreFiles} from '../features/repo-diff.js'; +import {loadMoreFiles} from '../features/repo-diff.js'; import {toggleElem} from '../utils/dom.js'; -import {DiffTreeStore} from '../modules/stores.js'; +import {diffTreeStore} from '../modules/stores.js'; import {setFileFolding} from '../features/file-fold.js'; -const {pageData} = window.config; const LOCAL_STORAGE_KEY = 'diff_file_tree_visible'; export default { components: {DiffFileTreeItem}, data: () => { - const fileTreeIsVisible = localStorage.getItem(LOCAL_STORAGE_KEY) === 'true'; - pageData.diffFileInfo.fileTreeIsVisible = fileTreeIsVisible; - return { - ...pageData.diffFileInfo, - store: DiffTreeStore, - }; + return {store: diffTreeStore()}; }, computed: { fileTree() { const result = []; - for (const file of this.files) { + for (const file of this.store.files) { // Split file into directories const splits = file.Name.split('/'); let index = 0; @@ -98,9 +89,7 @@ export default { } }, mounted() { - // replace the pageData.diffFileInfo.files with our watched data so we get updates - pageData.diffFileInfo.files = this.files; - + this.store.fileTreeIsVisible = localStorage.getItem(LOCAL_STORAGE_KEY) === 'true'; document.querySelector('.diff-toggle-file-tree-button').addEventListener('click', this.toggleVisibility); this.hashChangeListener = () => { @@ -124,12 +113,12 @@ export default { } }, toggleVisibility() { - this.updateVisibility(!this.fileTreeIsVisible); + this.updateVisibility(!this.store.fileTreeIsVisible); }, updateVisibility(visible) { - this.fileTreeIsVisible = visible; - localStorage.setItem(LOCAL_STORAGE_KEY, this.fileTreeIsVisible); - this.updateState(this.fileTreeIsVisible); + this.store.fileTreeIsVisible = visible; + localStorage.setItem(LOCAL_STORAGE_KEY, this.store.fileTreeIsVisible); + this.updateState(this.store.fileTreeIsVisible); }, updateState(visible) { const btn = document.querySelector('.diff-toggle-file-tree-button'); @@ -142,12 +131,7 @@ export default { toggleElem(toHide, visible); }, loadMoreData() { - this.isLoadingNewData = true; - doLoadMoreFiles(this.link, this.diffEnd, () => { - this.isLoadingNewData = false; - const {pageData} = window.config; - this.diffEnd = pageData.diffFileInfo.diffEnd; - }); + loadMoreFiles(this.store.linkLoadMore); }, }, }; diff --git a/web_src/js/components/DiffFileTreeItem.vue b/web_src/js/components/DiffFileTreeItem.vue index baaa01b782..916b8cdc73 100644 --- a/web_src/js/components/DiffFileTreeItem.vue +++ b/web_src/js/components/DiffFileTreeItem.vue @@ -40,7 +40,7 @@ <script> import {SvgIcon} from '../svg.js'; -import {DiffTreeStore} from '../modules/stores.js'; +import {diffTreeStore} from '../modules/stores.js'; export default { components: {SvgIcon}, @@ -56,7 +56,7 @@ export default { }, }, data: () => ({ - store: DiffTreeStore, + store: diffTreeStore(), collapsed: false, }), methods: { diff --git a/web_src/js/features/repo-diff.js b/web_src/js/features/repo-diff.js index d0622254bf..1d3c24e342 100644 --- a/web_src/js/features/repo-diff.js +++ b/web_src/js/features/repo-diff.js @@ -5,7 +5,7 @@ import {initDiffFileTree} from './repo-diff-filetree.js'; import {validateTextareaNonEmpty} from './comp/ComboMarkdownEditor.js'; import {initViewedCheckboxListenerFor, countAndUpdateViewedFiles, initExpandAndCollapseFilesButton} from './pull-view-file.js'; -const {csrfToken} = window.config; +const {csrfToken, pageData} = window.config; function initRepoDiffReviewButton() { const $reviewBox = $('#review-box'); @@ -119,37 +119,29 @@ function onShowMoreFiles() { countAndUpdateViewedFiles(); } -export function doLoadMoreFiles(link, diffEnd, callback) { - const url = `${link}?skip-to=${diffEnd}&file-only=true`; - loadMoreFiles(url, callback); -} - -function loadMoreFiles(url, callback) { +export function loadMoreFiles(url) { const $target = $('a#diff-show-more-files'); - if ($target.hasClass('disabled')) { - callback(); + if ($target.hasClass('disabled') || pageData.diffFileInfo.isLoadingNewData) { return; } + + pageData.diffFileInfo.isLoadingNewData = true; $target.addClass('disabled'); $.ajax({ type: 'GET', url, }).done((resp) => { - if (!resp) { - $target.removeClass('disabled'); - callback(resp); - return; - } - $('#diff-incomplete').replaceWith($(resp).find('#diff-file-boxes').children()); - // By simply rerunning the script we add the new data to our existing - // pagedata object. this triggers vue and the filetree and filelist will - // render the new elements. - $('body').append($(resp).find('script#diff-data-script')); + const $resp = $(resp); + // the response is a full HTML page, we need to extract the relevant contents: + // 1. append the newly loaded file list items to the existing list + $('#diff-incomplete').replaceWith($resp.find('#diff-file-boxes').children()); + // 2. re-execute the script to append the newly loaded items to the JS variables to refresh the DiffFileTree + $('body').append($resp.find('script#diff-data-script')); + onShowMoreFiles(); - callback(resp); - }).fail(() => { + }).always(() => { $target.removeClass('disabled'); - callback(); + pageData.diffFileInfo.isLoadingNewData = false; }); } @@ -158,7 +150,8 @@ function initRepoDiffShowMore() { e.preventDefault(); const $target = $(e.target); - loadMoreFiles($target.data('href'), () => {}); + const linkLoadMore = $target.attr('data-href'); + loadMoreFiles(linkLoadMore); }); $(document).on('click', 'a.diff-load-button', (e) => { diff --git a/web_src/js/modules/stores.js b/web_src/js/modules/stores.js index 24b913ce11..1a0ed7eda1 100644 --- a/web_src/js/modules/stores.js +++ b/web_src/js/modules/stores.js @@ -1,5 +1,10 @@ import {reactive} from 'vue'; -export const DiffTreeStore = reactive({ - selectedItem: '', -}); +let diffTreeStoreReactive; +export function diffTreeStore() { + if (!diffTreeStoreReactive) { + diffTreeStoreReactive = reactive(window.config.pageData.diffFileInfo); + window.config.pageData.diffFileInfo = diffTreeStoreReactive; + } + return diffTreeStoreReactive; +} |