mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
add basic support for mobile mode
This commit is contained in:
@@ -51,3 +51,35 @@ export function memoize<R, T extends (...args: any[]) => R>(
|
|||||||
}
|
}
|
||||||
return memoizedFunction as T;
|
return memoizedFunction as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a function, that, as long as it continues to be invoked, will not
|
||||||
|
* be triggered. The function will be called after it stops being called for
|
||||||
|
* N milliseconds. If `immediate` is passed, trigger the function on the
|
||||||
|
* leading edge, instead of the trailing.
|
||||||
|
*
|
||||||
|
* Inspired by https://davidwalsh.name/javascript-debounce-function
|
||||||
|
*/
|
||||||
|
export function debounce(
|
||||||
|
func: Function,
|
||||||
|
wait: number,
|
||||||
|
immediate?: boolean
|
||||||
|
): Function {
|
||||||
|
let timeout;
|
||||||
|
return function(this: any) {
|
||||||
|
const context = this;
|
||||||
|
const args = arguments;
|
||||||
|
function later() {
|
||||||
|
timeout = null;
|
||||||
|
if (!immediate) {
|
||||||
|
func.apply(context, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const callNow = immediate && !timeout;
|
||||||
|
clearTimeout(timeout);
|
||||||
|
timeout = setTimeout(later, wait);
|
||||||
|
if (callNow) {
|
||||||
|
func.apply(context, args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -74,6 +74,6 @@ export const makeEnvironment = memoize(function(): Env {
|
|||||||
|
|
||||||
rpc: ajax.rpc,
|
rpc: ajax.rpc,
|
||||||
debug: false,
|
debug: false,
|
||||||
isMobile: false
|
isMobile: window.innerWidth <= 768
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { makeEnvironment } from "./env";
|
|||||||
import { registry } from "./registry";
|
import { registry } from "./registry";
|
||||||
import { Discuss } from "./widgets/discuss";
|
import { Discuss } from "./widgets/discuss";
|
||||||
import { Root } from "./root";
|
import { Root } from "./root";
|
||||||
|
import { debounce } from "./core/utils";
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Prepare application registry
|
// Prepare application registry
|
||||||
@@ -17,4 +18,12 @@ document.addEventListener("DOMContentLoaded", async function() {
|
|||||||
const env = makeEnvironment();
|
const env = makeEnvironment();
|
||||||
const rootWidget = new Root(env);
|
const rootWidget = new Root(env);
|
||||||
await rootWidget.mount(document.body);
|
await rootWidget.mount(document.body);
|
||||||
|
|
||||||
|
window.addEventListener("resize", <any>debounce(() => {
|
||||||
|
const isMobile = window.innerWidth <= 768;
|
||||||
|
if (isMobile !== env.isMobile) {
|
||||||
|
env.isMobile = isMobile;
|
||||||
|
rootWidget.render();
|
||||||
|
}
|
||||||
|
}, 100));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Env, Menu } from "../env";
|
|||||||
|
|
||||||
const template = `
|
const template = `
|
||||||
<div class="o_navbar">
|
<div class="o_navbar">
|
||||||
<span class="title">Odoo</span>
|
<span class="title">Odoo<t t-if="env.isMobile"> MOBILE</t></span>
|
||||||
<ul>
|
<ul>
|
||||||
<li t-foreach="env.menus" t-as="menu">
|
<li t-foreach="env.menus" t-as="menu">
|
||||||
<a t-att-href="getUrl(menu)">
|
<a t-att-href="getUrl(menu)">
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import {
|
|||||||
escape,
|
escape,
|
||||||
htmlTrim,
|
htmlTrim,
|
||||||
idGenerator,
|
idGenerator,
|
||||||
memoize
|
memoize,
|
||||||
|
debounce
|
||||||
} from "../../src/ts/core/utils";
|
} from "../../src/ts/core/utils";
|
||||||
|
|
||||||
describe("escape", () => {
|
describe("escape", () => {
|
||||||
@@ -59,3 +60,20 @@ describe("memoize", () => {
|
|||||||
expect(nCalls).toBe(1);
|
expect(nCalls).toBe(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("debounce", () => {
|
||||||
|
test("works as expected", () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
let n = 0;
|
||||||
|
let f = debounce(() => n++, 100);
|
||||||
|
expect(n).toBe(0);
|
||||||
|
f();
|
||||||
|
expect(n).toBe(0);
|
||||||
|
f();
|
||||||
|
expect(n).toBe(0);
|
||||||
|
jest.advanceTimersByTime(90);
|
||||||
|
expect(n).toBe(0);
|
||||||
|
jest.advanceTimersByTime(20);
|
||||||
|
expect(n).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -21,3 +21,12 @@ exports[`can render one menu item 1`] = `
|
|||||||
</ul>
|
</ul>
|
||||||
</div>"
|
</div>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`mobile mode: navbar is different 1`] = `
|
||||||
|
"<div class=\\"o_navbar\\">
|
||||||
|
<span class=\\"title\\">Odoo MOBILE</span>
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>"
|
||||||
|
`;
|
||||||
|
|||||||
@@ -34,3 +34,10 @@ test("can render one menu item", async () => {
|
|||||||
await navbar.mount(fixture);
|
await navbar.mount(fixture);
|
||||||
expect(fixture.innerHTML).toMatchSnapshot();
|
expect(fixture.innerHTML).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("mobile mode: navbar is different", async () => {
|
||||||
|
env.isMobile = true;
|
||||||
|
const navbar = new Navbar(env);
|
||||||
|
await navbar.mount(fixture);
|
||||||
|
expect(fixture.innerHTML).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user