mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-12-14 15:28:57 +00:00
add NavigationActivation
This commit is contained in:
@@ -530,7 +530,7 @@ fn pageDoneCallback(ctx: *anyopaque) !void {
|
||||
self.clearTransferArena();
|
||||
|
||||
//We need to handle different navigation types differently.
|
||||
try self._session.navigation.processNavigation(self);
|
||||
try self._session.navigation.commitNavigation(self);
|
||||
|
||||
defer if (comptime IS_DEBUG) {
|
||||
log.debug(.page, "page.load.complete", .{ .url = self.url });
|
||||
@@ -567,9 +567,6 @@ fn pageDoneCallback(ctx: *anyopaque) !void {
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
// We need to handle different navigation types differently.
|
||||
// @ZIGDOM
|
||||
// try self._session.navigation.processNavigation(self);
|
||||
}
|
||||
|
||||
fn pageErrorCallback(ctx: *anyopaque, err: anyerror) void {
|
||||
|
||||
@@ -605,4 +605,5 @@ pub const JsApis = flattenTypes(&.{
|
||||
@import("../webapi/navigation/Navigation.zig"),
|
||||
@import("../webapi/navigation/NavigationEventTarget.zig"),
|
||||
@import("../webapi/navigation/NavigationHistoryEntry.zig"),
|
||||
@import("../webapi/navigation/NavigationActivation.zig"),
|
||||
});
|
||||
|
||||
@@ -29,10 +29,11 @@ const EventTarget = @import("../EventTarget.zig");
|
||||
const Navigation = @This();
|
||||
|
||||
const NavigationKind = @import("root.zig").NavigationKind;
|
||||
const NavigationHistoryEntry = @import("NavigationHistoryEntry.zig");
|
||||
const NavigationActivation = @import("NavigationActivation.zig");
|
||||
const NavigationTransition = @import("root.zig").NavigationTransition;
|
||||
const NavigationState = @import("root.zig").NavigationState;
|
||||
|
||||
const NavigationHistoryEntry = @import("NavigationHistoryEntry.zig");
|
||||
const NavigationCurrentEntryChangeEvent = @import("../event/NavigationCurrentEntryChangeEvent.zig");
|
||||
const NavigationEventTarget = @import("NavigationEventTarget.zig");
|
||||
|
||||
@@ -44,6 +45,7 @@ _index: usize = 0,
|
||||
// Need to be stable pointers, because Events can reference entries.
|
||||
_entries: std.ArrayList(*NavigationHistoryEntry) = .empty,
|
||||
_next_entry_id: usize = 0,
|
||||
_activation: ?NavigationActivation = null,
|
||||
|
||||
pub fn init(arena: std.mem.Allocator) Navigation {
|
||||
return Navigation{ ._arena = arena };
|
||||
@@ -63,6 +65,10 @@ pub fn onNewPage(self: *Navigation, page: *Page) !void {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn getActivation(self: *const Navigation) ?NavigationActivation {
|
||||
return self._activation;
|
||||
}
|
||||
|
||||
pub fn getCanGoBack(self: *const Navigation) bool {
|
||||
return self._index > 0;
|
||||
}
|
||||
@@ -71,12 +77,18 @@ pub fn getCanGoForward(self: *const Navigation) bool {
|
||||
return self._entries.items.len > self._index + 1;
|
||||
}
|
||||
|
||||
pub fn getCurrentEntryOrNull(self: *Navigation) ?*NavigationHistoryEntry {
|
||||
if (self._entries.items.len > self._index) {
|
||||
return self._entries.items[self._index];
|
||||
} else return null;
|
||||
}
|
||||
|
||||
pub fn getCurrentEntry(self: *Navigation) *NavigationHistoryEntry {
|
||||
// This should never fail. An entry should always be created before
|
||||
// we run the scripts on the page we are loading.
|
||||
std.debug.assert(self._entries.items.len > 0);
|
||||
|
||||
return self._entries.items[self._index];
|
||||
return self.getCurrentEntryOrNull().?;
|
||||
}
|
||||
|
||||
pub fn getTransition(_: *const Navigation) ?NavigationTransition {
|
||||
@@ -117,8 +129,8 @@ pub fn forward(self: *Navigation, page: *Page) !NavigationReturn {
|
||||
|
||||
pub fn updateEntries(self: *Navigation, url: [:0]const u8, kind: NavigationKind, page: *Page, dispatch: bool) !void {
|
||||
switch (kind) {
|
||||
.replace => {
|
||||
_ = try self.replaceEntry(url, .{ .source = .navigation, .value = null }, page, dispatch);
|
||||
.replace => |state| {
|
||||
_ = try self.replaceEntry(url, .{ .source = .navigation, .value = state }, page, dispatch);
|
||||
},
|
||||
.push => |state| {
|
||||
_ = try self.pushEntry(url, .{ .source = .navigation, .value = state }, page, dispatch);
|
||||
@@ -131,14 +143,23 @@ pub fn updateEntries(self: *Navigation, url: [:0]const u8, kind: NavigationKind,
|
||||
}
|
||||
|
||||
// This is for after true navigation processing, where we need to ensure that our entries are up to date.
|
||||
// This is only really safe to run in the `pageDoneCallback` where we can guarantee that the URL and NavigationKind are correct.
|
||||
pub fn processNavigation(self: *Navigation, page: *Page) !void {
|
||||
//
|
||||
// This is only really safe to run in the `pageDoneCallback`
|
||||
// where we can guarantee that the URL and NavigationKind are correct.
|
||||
pub fn commitNavigation(self: *Navigation, page: *Page) !void {
|
||||
const url = page.url;
|
||||
|
||||
const kind: NavigationKind = self._current_navigation_kind orelse .{ .push = null };
|
||||
defer self._current_navigation_kind = null;
|
||||
|
||||
const from_entry = self.getCurrentEntryOrNull();
|
||||
try self.updateEntries(url, kind, page, false);
|
||||
|
||||
self._activation = NavigationActivation{
|
||||
._from = from_entry,
|
||||
._entry = self.getCurrentEntry(),
|
||||
._type = kind.toNavigationType(),
|
||||
};
|
||||
}
|
||||
|
||||
/// Pushes an entry into the Navigation stack WITHOUT actually navigating to it.
|
||||
@@ -401,6 +422,7 @@ pub const JsApi = struct {
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
};
|
||||
|
||||
pub const activation = bridge.accessor(Navigation.getActivation, null, .{});
|
||||
pub const canGoBack = bridge.accessor(Navigation.getCanGoBack, null, .{});
|
||||
pub const canGoForward = bridge.accessor(Navigation.getCanGoForward, null, .{});
|
||||
pub const currentEntry = bridge.accessor(Navigation.getCurrentEntry, null, .{});
|
||||
|
||||
56
src/browser/webapi/navigation/NavigationActivation.zig
Normal file
56
src/browser/webapi/navigation/NavigationActivation.zig
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2023-2025 Lightpanda (Selecy SAS)
|
||||
//
|
||||
// Francis Bouvier <francis@lightpanda.io>
|
||||
// Pierre Tachoire <pierre@lightpanda.io>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const js = @import("../../js/js.zig");
|
||||
|
||||
const NavigationType = @import("root.zig").NavigationType;
|
||||
const NavigationHistoryEntry = @import("NavigationHistoryEntry.zig");
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/NavigationActivation
|
||||
const NavigationActivation = @This();
|
||||
|
||||
_entry: *NavigationHistoryEntry,
|
||||
_from: ?*NavigationHistoryEntry = null,
|
||||
_type: NavigationType,
|
||||
|
||||
pub fn getEntry(self: *const NavigationActivation) *NavigationHistoryEntry {
|
||||
return self._entry;
|
||||
}
|
||||
|
||||
pub fn getFrom(self: *const NavigationActivation) ?*NavigationHistoryEntry {
|
||||
return self._from;
|
||||
}
|
||||
|
||||
pub fn getNavigationType(self: *const NavigationActivation) []const u8 {
|
||||
return @tagName(self._type);
|
||||
}
|
||||
|
||||
pub const JsApi = struct {
|
||||
pub const bridge = js.Bridge(NavigationActivation);
|
||||
|
||||
pub const Meta = struct {
|
||||
pub const name = "NavigationActivation";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
};
|
||||
|
||||
pub const entry = bridge.accessor(NavigationActivation.getEntry, null, .{});
|
||||
pub const from = bridge.accessor(NavigationActivation.getFrom, null, .{});
|
||||
pub const navigationType = bridge.accessor(NavigationActivation.getNavigationType, null, .{});
|
||||
};
|
||||
@@ -38,6 +38,10 @@ pub const NavigationKind = union(NavigationType) {
|
||||
replace: ?[]const u8,
|
||||
traverse: usize,
|
||||
reload,
|
||||
|
||||
pub fn toNavigationType(self: NavigationKind) NavigationType {
|
||||
return std.meta.activeTag(self);
|
||||
}
|
||||
};
|
||||
|
||||
pub const NavigationState = struct {
|
||||
@@ -45,25 +49,6 @@ pub const NavigationState = struct {
|
||||
value: ?[]const u8,
|
||||
};
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/NavigationActivation
|
||||
pub const NavigationActivation = struct {
|
||||
entry: NavigationHistoryEntry,
|
||||
from: ?NavigationHistoryEntry = null,
|
||||
type: NavigationType,
|
||||
|
||||
pub fn get_entry(self: *const NavigationActivation) NavigationHistoryEntry {
|
||||
return self.entry;
|
||||
}
|
||||
|
||||
pub fn get_from(self: *const NavigationActivation) ?NavigationHistoryEntry {
|
||||
return self.from;
|
||||
}
|
||||
|
||||
pub fn get_navigationType(self: *const NavigationActivation) NavigationType {
|
||||
return self.type;
|
||||
}
|
||||
};
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/NavigationTransition
|
||||
pub const NavigationTransition = struct {
|
||||
finished: js.Promise,
|
||||
|
||||
Reference in New Issue
Block a user