1+ ( function ( ) {
2+ class Store {
3+ static _options = { }
4+ static getOptions ( ) {
5+ const options = localStorage . getItem ( 'GiteaToolkit_options' )
6+ if ( ! options ) return { }
7+ try {
8+ return JSON . parse ( options ) || { }
9+ } catch ( err ) {
10+ console . log ( err )
11+ return { }
12+ }
13+ }
14+ static setOption ( options ) {
15+ localStorage . setItem ( 'GiteaToolkit_options' , JSON . stringify ( options ) )
16+ }
17+ }
18+ class ToolkitModule {
19+ /**
20+ * 页面元素
21+ */
22+ static DOM_NAVBAR = null
23+ static DOM_MAIN = null
24+ static DOM_FORK_LINK = null
25+ static get DOM_BRANCH_LIST ( ) { return document . querySelector ( '.ui.container .ui.stackable .menu.transition.visible .scrolling.menu' ) }
26+ static get INFO_USER_NAME ( ) { const d = document . querySelector ( '.right.stackable.menu .ui.header strong' ) ; return d ? d . innerText : null }
27+ static get DOM_MERGE_BTN ( ) { return document . querySelector ( '#new-pull-request' ) }
28+ static get INFO_FORK_LINK ( ) { const d = document . querySelector ( '.fork-flag > a' ) ; return d ? d . innerText : null }
29+ static get INFO_REPOSTORY_NAME ( ) {
30+ const nameDom = document . querySelector ( '.ui.huge.breadcrumb.repo-title' )
31+ if ( nameDom ) {
32+ const titleParts = document . title
33+ return titleParts . split ( ' ' ) [ 0 ]
34+ } else {
35+ return null
36+ }
37+ }
38+ // onload () { throw new Error('must implemention') }
39+ onload ( ctx ) {
40+ if ( ctx . debug ) console . log ( '获取页面元素' )
41+ const [ navbar , main ] = document . querySelectorAll ( 'body>div:first-of-type>div' )
42+ if ( navbar ) ToolkitModule . DOM_NAVBAR = navbar
43+ if ( main ) ToolkitModule . DOM_MAIN = main
44+ }
45+ }
46+ class BatchMergeBranchToolkitModule extends ToolkitModule {
47+ constructor ( ) { super ( ) }
48+ name = 'BatchMergeBranchToolkit'
49+ _currentBranchList = [ ]
50+
51+ onload ( ctx ) {
52+ super . onload ( ctx )
53+ if ( ! ToolkitModule . DOM_MERGE_BTN || ! ToolkitModule . INFO_FORK_LINK ) return
54+ ctx . log ( '获取分支列表, 显示所有分支' )
55+ setTimeout ( ( ) => {
56+ this . _showBranchSelector ( ctx )
57+ } , 100 ) ;
58+ }
59+ _showBranchSelector ( ctx ) {
60+ const branchBtn = document . querySelector ( '.ui.basic.small.compact.button' )
61+ branchBtn . click ( )
62+ // 修改创建合并请求按钮
63+ ToolkitModule . DOM_MERGE_BTN . innerText = '🚗🚕🚙🚓🚑🚒 批量创建合并请求'
64+ ToolkitModule . DOM_MERGE_BTN . parentNode . href = 'javascript:;'
65+ ToolkitModule . DOM_MERGE_BTN . addEventListener ( 'click' , async evt => {
66+ evt . stopPropagation ( )
67+ // such as: https://gitxxxxxxxx.com/vue_web/shanshou_vue/compare/oem.food.1060...sven:yss.retail.1040.electron
68+ const urlList = [ ]
69+ const basePath = location . protocol + '//' + location . host + '/'
70+ const branches = this . _getCurrentRepostorySelectedBranches ( )
71+ const forkLink = ToolkitModule . INFO_FORK_LINK
72+ for ( const b of branches ) {
73+ urlList . push ( basePath + forkLink + '/compare/' + b + '...' + ToolkitModule . INFO_USER_NAME + ':' + b )
74+ }
75+ for ( const u of urlList ) {
76+ await Toolkit . delay ( )
77+ window . open ( u )
78+ }
79+ } )
80+ setTimeout ( ( ) => {
81+ // 处理分支数据并显示分支选择框
82+ const branchListDom = ToolkitModule . DOM_BRANCH_LIST
83+ const branchList = [ ]
84+ for ( const b of branchListDom . children ) {
85+ branchList . push ( b . innerText )
86+ }
87+ this . _currentBranchList = branchList
88+ branchBtn . click ( )
89+ console . log ( this . _currentBranchList )
90+ branchBtn . addEventListener ( 'click' , evt => {
91+ setTimeout ( ( ) => {
92+ if ( ! ToolkitModule . DOM_BRANCH_LIST ) return
93+ const selectedList = this . _getCurrentRepostorySelectedBranches ( )
94+ for ( const item of ToolkitModule . DOM_BRANCH_LIST . children ) {
95+ const branchName = item . innerText
96+ const isSelect = selectedList . includes ( branchName )
97+ const checkboxDom = document . createElement ( 'input' )
98+ checkboxDom . type = 'checkbox'
99+ checkboxDom . checked = isSelect
100+ checkboxDom . style . width = '20px'
101+ checkboxDom . style . height = '20px'
102+ item . appendChild ( checkboxDom )
103+ checkboxDom . addEventListener ( 'click' , evt => {
104+ this . _toggleBranch ( evt . target . checked , evt . target . parentNode . innerText )
105+ evt . stopPropagation ( )
106+ } )
107+ }
108+ } , 100 )
109+ } )
110+ } , 100 )
111+ }
112+ _getCurrentRepostorySelectedBranches ( ) {
113+ const name = ToolkitModule . INFO_REPOSTORY_NAME
114+ const options = Store . getOptions ( )
115+ const selectedList = ( options . selectedList && options . selectedList [ name ] ) || [ ]
116+ return selectedList
117+ }
118+ _setCurrentRepostorySelectedBranches ( list ) {
119+ const name = ToolkitModule . INFO_REPOSTORY_NAME
120+ const options = Store . getOptions ( )
121+ if ( ! options . selectedList ) options . selectedList = { }
122+ options . selectedList [ name ] = list
123+ Store . setOption ( options )
124+ }
125+ _toggleBranch ( checked , branchName ) {
126+ const selectedList = this . _getCurrentRepostorySelectedBranches ( )
127+ const index = selectedList . indexOf ( branchName )
128+ if ( checked && index === - 1 ) {
129+ selectedList . push ( branchName )
130+ } else if ( ! checked && index !== - 1 ) {
131+ selectedList . splice ( index , 1 )
132+ }
133+ this . _setCurrentRepostorySelectedBranches ( selectedList )
134+ console . log ( )
135+ }
136+ }
137+ class Toolkit {
138+ debug = true
139+ options = { }
140+ constructor ( options = { } ) {
141+ Object . assign ( this . options , options )
142+ this . emitHook ( 'init' )
143+ }
144+ /**
145+ * 工具集
146+ */
147+ static modules = [ ]
148+ /**
149+ * 注册工具模块
150+ */
151+ static use ( moduleItem ) {
152+ Array . isArray ( moduleItem ) ? moduleItem . map ( item => Toolkit . use ( item ) ) : Toolkit . modules . push ( moduleItem )
153+ }
154+ /**
155+ * 触发钩子函数
156+ * @param {string }} hook 钩子函数名
157+ */
158+ emitHook ( hook ) {
159+ Toolkit . modules . map ( module => module [ hook ] && typeof module [ hook ] === 'function' && module [ hook ] ( this ) )
160+ }
161+ log ( ...args ) {
162+ console . log ( '%c[Gitea Toolkit] LOG: ' , 'color:teal' , ...args )
163+ }
164+ static delay ( timeout = 200 ) {
165+ return new Promise ( resolve => setTimeout ( resolve , timeout ) )
166+ }
167+ }
168+
169+ Toolkit . use ( new BatchMergeBranchToolkitModule ( ) )
170+ window . _$Toolkit = new Toolkit ( )
171+ window . addEventListener ( 'DOMContentLoaded' , ( ) => window . _$Toolkit . emitHook ( 'onload' ) )
172+ } ) ( ) ;
0 commit comments