Skip to content

Commit

Permalink
WIP - begone base_index
Browse files Browse the repository at this point in the history
  • Loading branch information
mvollmer committed Sep 27, 2024
1 parent ff33dfe commit 8df035d
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 75 deletions.
2 changes: 1 addition & 1 deletion pkg/shell/active-pages-modal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const ActivePagesDialog = ({ dialogResult, state }) => {
for (const n in state.frames) {
const f = state.frames[n];
if (f.url) {
const active = (f == state.current_frame || state.last_path_for_host(f.host) == f.path);
const active = (f == state.current_frame || state.get_last_path_for_host(f.host) == f.path);
result.push({
frame: f,
active,
Expand Down
10 changes: 0 additions & 10 deletions pkg/shell/base_index.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,6 @@ function Index() {
};

self.ready = function () {
window.addEventListener("popstate", ev => {
console.log("POP!");
self.navigate();
self.ensure_connection();
});

self.navigate();
self.ensure_connection();
cockpit.translate();
document.body.removeAttribute("hidden");
};
}

Expand Down
8 changes: 4 additions & 4 deletions pkg/shell/hosts.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export class CockpitHosts extends React.Component {
// XXX - Only because trigger_connection_flow isn't available
// until we are mounted. If that is fixed, remove this
// here.
this.props.state.index.ensure_connection();
this.props.state.ensure_connection();
}

componentWillUnmount() {
Expand Down Expand Up @@ -151,7 +151,7 @@ export class CockpitHosts extends React.Component {
const addr = build_href({ host: parts.address });
if (machine == current_machine && parts.address != machine.address) {
state.loader.connect(parts.address);
state.index.jump(addr);
state.jump(addr);
}
}
}
Expand Down Expand Up @@ -223,7 +223,7 @@ export class CockpitHosts extends React.Component {
if (connection_string) {
const parts = state.machines.split_connection_string(connection_string);
const addr = build_href({ host: parts.address });
state.index.jump(addr);
state.jump(addr);
}
}

Expand All @@ -240,7 +240,7 @@ export class CockpitHosts extends React.Component {
if (current_machine === machine) {
// Removing machine underneath ourself - jump to localhost
const addr = build_href({ host: "localhost" });
state.index.jump(addr);
state.jump(addr);
}

if (state.machines.list.length <= 2)
Expand Down
4 changes: 2 additions & 2 deletions pkg/shell/nav.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ export const PageNav = ({ state }) => {
keyword={item.keyword.keyword}
term={term}
to={build_href({ host: current_machine.address, path, hash })}
jump={state.index.jump} />
jump={state.jump} />
);
}

Expand Down Expand Up @@ -368,5 +368,5 @@ export const PageNav = ({ state }) => {
filtering={keyword_filter}
sorting={(a, b) => { return b.keyword.score - a.keyword.score }}
current={current_manifest_item.path}
jump={state.index.jump} />;
jump={state.jump} />;
};
6 changes: 5 additions & 1 deletion pkg/shell/shell.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,13 @@ const _ = cockpit.gettext;

// TODO:

/* In fact, move all of base_index into ShellState.
/* Move jump from base_index into ShellState.
*/

/* Move CompiledComponents into machines/ and make it a property of
the machine objects.
*/

/* Move hash tracking from Router to Frames?
*/

Expand Down
216 changes: 159 additions & 57 deletions pkg/shell/state.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ import cockpit from "cockpit";

import { Router } from "./router.jsx";
import { machines as machines_factory } from "./machines/machines.js";
import { decode_window_location, replace_window_location, CompiledComponents } from "./util.jsx";

import * as base_index from "./base_index";
import {
decode_location, decode_window_location, push_window_location, replace_window_location,
CompiledComponents
} from "./util.jsx";

/* SHELL STATE
Expand All @@ -46,6 +47,10 @@ import * as base_index from "./base_index";
- remove_frame
- jump
- ensure_connection
- ensure_frame_loaded
Signals
- "update" (or "changed"?)
Expand Down Expand Up @@ -176,7 +181,15 @@ export function ShellState(trigger_connection_flow) {
function on_ready() {
if (machines.ready && config_ready) {
self.ready = true;
index.ready();
window.addEventListener("popstate", ev => {
self.update();
self.ensure_frame_loaded();
self.ensure_connection();
});

self.update();
self.ensure_frame_loaded();
self.ensure_connection();
}
}

Expand Down Expand Up @@ -341,7 +354,7 @@ export function ShellState(trigger_connection_flow) {
perform_frame_jump_command: function (frame_name, location) {
console.log("FRAME JUMP", frame_name, location);
if (frame_name == "cockpit1" || (self.current_frame && self.current_frame.name == frame_name)) {
self.index.jump(location);
jump(location);
ensure_connection();
}
},
Expand All @@ -362,7 +375,7 @@ export function ShellState(trigger_connection_flow) {
*/
const location = Object.assign({}, decode_window_location(), { hash });
replace_window_location(location);
index.track_hash(location.host, location.path, location.hash);
track_location(location.host, location.path, location.hash);
update();
}
},
Expand Down Expand Up @@ -406,6 +419,135 @@ export function ShellState(trigger_connection_flow) {

const router = new Router(router_callbacks);

/* NAVIGATION
*
* The main navigation function, JUMP, will change window.location
* as requested and then trigger a general ShellState update. The
* update processing will look at window.location and update the
* various "current_*" properties of the shell state accordingly.
* (The update processing might also change window.location again
* itself, in order to canonicalize it.)
*
* The new location given to JUMP can be partial; the missing
* pieces are filled in from the browsing history in a (almost)
* natural way. If the HOST part is missing, it will be taken from
* the current location. If the PATH part is missing, the last
* path visited on the given host is used. And if the HASH is
* missing, the last one from the given HOST/PATH combination is
* used. But only, and this is a historical quirk, when the new
* host/path differs from the current host/path. Don't rely on
* that, always use "/" as the hash when jumping to the top
* sub-page.
*
* Calling JUMP will also make sure that the (newly) current frame
* will now be loaded again in the case that it was explicitly
* removed earlier. (This also happens when window.location isn't
* actually changed by JUMP.)
*
* But JUMP will never open a new connection to a HOST that is not
* yet connected. If you want that, call ENSURE_CONNECTION right
* after JUMP. However, it is better to first connect to the host
* using XXX and only call JUMP when that has succeeded.
*
* (Hmm, that could also happen inside JUMP, no? It would make
* JUMP async, but that's ok...)
*/

const last_path_for_host = { };
const last_hash_for_host_path = { };

function lookup_path_hash(host, path) {
if (last_hash_for_host_path[host])
return last_hash_for_host_path[host][path] || null;
return null;
}

function track_location(host, path, hash) {
last_path_for_host[host] = path;
if (!last_hash_for_host_path[host])
last_hash_for_host_path[host] = { };
last_hash_for_host_path[host][path] = hash;
}

function jump (location) {
if (typeof (location) === "string")
location = decode_location(location);

console.log("JUMP", JSON.stringify(location));

const current = decode_window_location();

/* Fill in the missing pieces, in order.
*/

if (!location.host)
location.host = current.host || "localhost";

if (!location.path)
location.path = last_path_for_host[location.host] || "";

if (!location.hash) {
// XXX - This extra condition is quirky. We should
// probably change all callers of JUMP to always pass a
// hash of "/" if they want to navigate to the top
// sub-page of a page. Most do, I think, but the tests
// don't, for example.
//
if (location.host != current.host || location.path != current.path)
location.hash = lookup_path_hash(location.host, location.path);
else
console.warn('Shell jump with hash and no frame change. Please use "/" as the hash to jump to the top sub-page.');
}

if (location.host !== current.host ||
location.path !== current.pathframe_change ||
location.hash !== current.hash) {
console.log("PUSH", JSON.stringify(location));
push_window_location(location);
// XXX
const nav_system = document.getElementById("nav-system");
if (nav_system)
nav_system.classList.remove("interact");
update();
ensure_frame_loaded();
return true;
}

self.ensure_frame_loaded();
return false;
}

function ensure_connection() {
const machine = self.current_machine;

if (machine) {
// XXX - trigger_connection_flow doesn't work without a
// host switcher...
if (machine.connection_string == "localhost") {
console.log("CONNECTING local");
loader.connect("localhost");
return;
}

console.log("CONNECTING", machine.address);
trigger_connection_flow(machine);
}
}

function ensure_frame_loaded () {
if (self.current_frame && self.current_frame.url == null) {
console.log("REQUEST TO LOAD", self.current_frame.name);
// Let update() recreate the frame.
delete frames[self.current_frame.name];
self.current_frame = null;
update();
}
}

function get_last_path_for_host (host) {
return last_path_for_host[host];
}

/* ... rest is still messsy
*/

Expand Down Expand Up @@ -434,6 +576,11 @@ export function ShellState(trigger_connection_flow) {
language_direction: cockpit.language_direction,

remove_frame,

jump,
ensure_connection,
ensure_frame_loaded,
get_last_path_for_host,
};

cockpit.event_target(self);
Expand All @@ -444,24 +591,6 @@ export function ShellState(trigger_connection_flow) {
router.hint(frame_name, { hidden });
}

const index_options = {
navigate: function () {
update();
ensure_frame_loaded();
},

ensure_connection: function () {
ensure_connection();
},

ensure_frame_loaded: function () {
ensure_frame_loaded();
},
};

const index = base_index.new_index_from_proto(index_options);
self.index = index;

machines.addEventListener("removed", (ev, machine) => {
remove_machine_frames(machine);
update();
Expand Down Expand Up @@ -518,6 +647,12 @@ export function ShellState(trigger_connection_flow) {
replace_window_location(location);
}

// Remember the most recent history for each host, and each
// host/path combinaton. This is used by JUMP to complete
// partial locations.
//
track_location(location.host, location.path, location.hash);

const item = find_path_manifest_item(location.path, compiled);

self.current_location = location;
Expand All @@ -532,8 +667,6 @@ export function ShellState(trigger_connection_flow) {
self.current_manifest_item.label)
: null);

console.log("CURRENT FRAME", frame);

if (frame != self.current_frame) {
const prev_frame = self.current_frame;
self.current_frame = frame;
Expand All @@ -557,36 +690,5 @@ export function ShellState(trigger_connection_flow) {

self.update = update;

function ensure_connection() {
const machine = self.current_machine;

if (machine) {
// XXX - trigger_connection_flow doesn't work without a
// host switcher...
if (machine.connection_string == "localhost") {
console.log("CONNECTING local");
loader.connect("localhost");
return;
}

console.log("CONNECTING", machine.address);
trigger_connection_flow(machine);
}
}

function ensure_frame_loaded () {
if (self.current_frame && self.current_frame.url == null) {
console.log("REQUEST TO LOAD", self.current_frame.name);
// Let update() recreate the frame.
delete frames[self.current_frame.name];
self.current_frame = null;
update();
}
}

self.last_path_for_host = (host) => {
return index.last_path_for_host[host];
};

return self;
}

0 comments on commit 8df035d

Please sign in to comment.