From c238ec5e770d461c310c4e560eabb7b0740faf7f Mon Sep 17 00:00:00 2001 From: Suherdy Yacob Date: Mon, 16 Mar 2026 09:07:33 +0700 Subject: [PATCH] upgrade to odoo19 --- __manifest__.py | 19 +++++++ .../order_display/order_display_patch.js | 45 ++++++++++++++++ .../order_display/order_display_patch.xml | 8 +++ .../product_screen/product_screen_patch.js | 54 +++++++++++++++++++ .../product_screen/product_screen_patch.xml | 8 +++ 5 files changed, 134 insertions(+) create mode 100644 __manifest__.py create mode 100644 static/src/app/components/order_display/order_display_patch.js create mode 100644 static/src/app/components/order_display/order_display_patch.xml create mode 100644 static/src/app/screens/product_screen/product_screen_patch.js create mode 100644 static/src/app/screens/product_screen/product_screen_patch.xml diff --git a/__manifest__.py b/__manifest__.py new file mode 100644 index 0000000..00d8cbc --- /dev/null +++ b/__manifest__.py @@ -0,0 +1,19 @@ +{ + 'name': 'POS UI Optimization', + 'version': '1.0', + 'category': 'Sales/Point of Sale', + 'summary': 'Optimize POS UI for low-RAM devices with incremental rendering (Odoo 19).', + 'depends': ['point_of_sale'], + 'data': [], + 'assets': { + 'point_of_sale._assets_pos': [ + 'pos_ui_optimization/static/src/app/components/order_display/order_display_patch.js', + 'pos_ui_optimization/static/src/app/components/order_display/order_display_patch.xml', + 'pos_ui_optimization/static/src/app/screens/product_screen/product_screen_patch.js', + 'pos_ui_optimization/static/src/app/screens/product_screen/product_screen_patch.xml', + ], + }, + 'installable': True, + 'application': False, + 'license': 'LGPL-3', +} diff --git a/static/src/app/components/order_display/order_display_patch.js b/static/src/app/components/order_display/order_display_patch.js new file mode 100644 index 0000000..89e932c --- /dev/null +++ b/static/src/app/components/order_display/order_display_patch.js @@ -0,0 +1,45 @@ +/** @odoo-module **/ + +import { OrderDisplay } from "@point_of_sale/app/components/order_display/order_display"; +import { patch } from "@web/core/utils/patch"; +import { useState, onMounted, onWillUnmount } from "@odoo/owl"; + +patch(OrderDisplay.prototype, { + setup() { + super.setup(); + this.state = useState({ displayedCount: 20 }); + + onMounted(() => { + const scrollable = this.scrollableRef.el; + if (!scrollable) { + return; + } + + this.onScroll = () => { + if ( + scrollable.scrollTop + scrollable.clientHeight >= + scrollable.scrollHeight - 100 + ) { + if (this.state.displayedCount < this.comboSortedLines.length) { + this.state.displayedCount += 20; + } + } + }; + scrollable.addEventListener("scroll", this.onScroll); + + // Ensure selected line is visible by expanding displayedCount if needed + const selectedLineIndex = this.comboSortedLines.findIndex(l => l.selected); + if (selectedLineIndex >= this.state.displayedCount) { + this.state.displayedCount = selectedLineIndex + 1; + } + }); + + onWillUnmount(() => { + this.scrollableRef.el?.removeEventListener("scroll", this.onScroll); + }); + }, + + get linesToDisplay() { + return this.comboSortedLines.slice(0, this.state.displayedCount); + } +}); diff --git a/static/src/app/components/order_display/order_display_patch.xml b/static/src/app/components/order_display/order_display_patch.xml new file mode 100644 index 0000000..a010c53 --- /dev/null +++ b/static/src/app/components/order_display/order_display_patch.xml @@ -0,0 +1,8 @@ + + + + + linesToDisplay + + + diff --git a/static/src/app/screens/product_screen/product_screen_patch.js b/static/src/app/screens/product_screen/product_screen_patch.js new file mode 100644 index 0000000..9c2b64c --- /dev/null +++ b/static/src/app/screens/product_screen/product_screen_patch.js @@ -0,0 +1,54 @@ +/** @odoo-module **/ + +import { ProductScreen } from "@point_of_sale/app/screens/product_screen/product_screen"; +import { patch } from "@web/core/utils/patch"; +import { useEffect } from "@odoo/owl"; + +patch(ProductScreen.prototype, { + setup() { + super.setup(); + this.state.displayedProductsCount = 40; + + const originalOnScroll = this.onScroll; + this.onScroll = (ev) => { + if (originalOnScroll) { + originalOnScroll(ev); + } + const el = ev.target; + if (el && el.scrollTop + el.clientHeight >= el.scrollHeight - 200) { + const totalCount = this.pos.productToDisplayByCateg.reduce((acc, cat) => acc + cat[1].length, 0); + if (this.state.displayedProductsCount < totalCount) { + this.state.displayedProductsCount += 40; + } + } + }; + + useEffect( + () => { + this.state.displayedProductsCount = 40; + }, + () => [this.pos.searchProductWord, this.pos.selectedCategory] + ); + }, + + get productToDisplayByCategLimited() { + const fullList = this.pos.productToDisplayByCateg; + let count = 0; + const limitedList = []; + for (const [categ, products] of fullList) { + const remaining = this.state.displayedProductsCount - count; + if (remaining <= 0) { + break; + } + if (products.length <= remaining) { + limitedList.push([categ, products]); + count += products.length; + } else { + limitedList.push([categ, products.slice(0, remaining)]); + count += remaining; + break; + } + } + return limitedList; + } +}); diff --git a/static/src/app/screens/product_screen/product_screen_patch.xml b/static/src/app/screens/product_screen/product_screen_patch.xml new file mode 100644 index 0000000..4250eb1 --- /dev/null +++ b/static/src/app/screens/product_screen/product_screen_patch.xml @@ -0,0 +1,8 @@ + + + + + productToDisplayByCategLimited + + +