# Patch TCP vol/pan: move onWheel+onDoubleClick from 4px input to whole row div # Áp dụng cho app.jsx (formatted, CRLF) và app.precompiled.js (minified) # Cách làm: (1) xóa wheel handlers khỏi input, (2) chèn chúng vào props của row div. # Row vol mở đầu "}, " (con đầu flex-col), row pan mở đầu "), " (con thứ hai). import io def patch_file(path, spots): with io.open(path, 'r', encoding='utf-8', newline='') as f: s = f.read() for i, spot in enumerate(spots): anchor = spot['anchor'] n = s.count(anchor) assert n == 1, f"{path}: anchor count {n} for {anchor[:60]}" p_anchor = s.index(anchor) p_wheel = s.rfind(spot['wheel_marker'], 0, p_anchor + len(anchor) + 1) assert p_wheel != -1, f"{path}: wheel_marker not found for {anchor[:40]}" p_class = s.index(spot['class_marker'], p_wheel) wheel_props = s[p_wheel:p_class].rstrip() # (1) xóa handlers khỏi input (giữ dấu phẩy trước className) del_start = p_wheel - spot['pre_wheel'] del_end = p_class - spot['pre_class'] s = s[:del_start] + s[del_end:] # (2) chèn handlers vào props row div p_row = s.rfind(spot['row_open'], 0, del_start) assert p_row != -1, f"{path}: row_open not found for spot {i} ({anchor[:40]})" p_insert = spot['insert_pos'](s, p_row) s = s[:p_insert] + spot['insert_prefix'] + wheel_props + s[p_insert:] with io.open(path, 'w', encoding='utf-8', newline='') as f: f.write(s) print(f"patched {path}") def spots_formatted(): NL = '\r\n' def row_open(pre): return (pre + '/*#__PURE__*/React.createElement("div", {' + NL + ' className: "flex items-center gap-1"' + NL + ' }, /*#__PURE__*/React.createElement("span", {') def spot(anchor, class_marker, pre): return dict( anchor=anchor, wheel_marker='onWheel: e => {', class_marker=class_marker, pre_wheel=10, # '\r\n' + 8 spaces trước onWheel (bỏ dấu phẩy trước nó? KHÔNG: giữ phẩy sau onChange) pre_class=10, # '\r\n' + 8 spaces trước className (xóa cả phẩy sau onDoubleClick) row_open=row_open(pre), insert_pos=lambda s, p_row: s.index('className: "flex items-center gap-1"', p_row) + len('className: "flex items-center gap-1"'), insert_prefix=',\r\n ', ) return [ spot("wheelSteps('vol:' + track.id,", 'className: "flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-cyan-500"', '}, '), spot("wheelSteps('pan:' + track.id,", 'className: "flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-purple-500"', '), '), spot("wheelSteps('vol:' + vTrack.id,", 'className: "flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-cyan-500"', '}, '), spot("wheelSteps('pan:' + vTrack.id,", 'className: "flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-purple-500"', '), '), ] def spots_minified(): def spot(anchor, wheel_marker, class_marker, row_open): return dict( anchor=anchor, wheel_marker=wheel_marker, class_marker=class_marker, pre_wheel=1, # ',' trước onWheel pre_class=1, # ',' trước className row_open=row_open, insert_pos=lambda s, p_row: s.index('},/*#__PURE__*/React.createElement("span",{', p_row), insert_prefix=',', ) return [ spot("wheelSteps('vol:'+track.id", "onWheel:e=>{e.preventDefault();const steps=wheelSteps('vol:'+track.id", 'className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-cyan-500"', 'React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-xs"},"Vol:"),'), spot("wheelSteps('pan:'+track.id", "onWheel:e=>{e.preventDefault();const steps=wheelSteps('pan:'+track.id", 'className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-purple-500"', 'React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-xs"},"Pan:"),'), spot("wheelSteps('vol:'+vTrack.id", "onWheel:e=>{e.preventDefault();const steps=wheelSteps('vol:'+vTrack.id", 'className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-cyan-500"', 'React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-10 text-right text-zinc-500 text-[14px]"},"Vol:"),'), spot("wheelSteps('pan:'+vTrack.id", "onWheel:e=>{e.preventDefault();const steps=wheelSteps('pan:'+vTrack.id", 'className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-purple-500"', 'React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-10 text-right text-zinc-500 text-[14px]"},"Pan:"),'), ] if __name__ == '__main__': patch_file('app/static/js/app.jsx', spots_formatted()) patch_file('app/static/js/app.precompiled.js', spots_minified())