From dbd1ee46c4c5dbce23a464334daee61d91194a74 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Tue, 6 Oct 2020 21:18:18 +0100 Subject: [PATCH] Add `URLHashDemo` w/ `window.onhashchange` closure (#288) * Add `URLHashDemo` w/ `window.onhashchange` closure Resolves #284 * Assign `.undefined` in HashState.deinit --- Sources/TokamakDemo/TokamakDemo.swift | 1 + Sources/TokamakDemo/URLHashDemo.swift | 52 +++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 Sources/TokamakDemo/URLHashDemo.swift diff --git a/Sources/TokamakDemo/TokamakDemo.swift b/Sources/TokamakDemo/TokamakDemo.swift index 28858b262..23a3756f8 100644 --- a/Sources/TokamakDemo/TokamakDemo.swift +++ b/Sources/TokamakDemo/TokamakDemo.swift @@ -144,6 +144,7 @@ struct TokamakDemoView: View { #if os(WASI) Section(header: Text("TokamakDOM")) { NavItem("DOM reference", destination: DOMRefDemo()) + NavItem("URL hash changes", destination: URLHashDemo()) } #endif } diff --git a/Sources/TokamakDemo/URLHashDemo.swift b/Sources/TokamakDemo/URLHashDemo.swift new file mode 100644 index 000000000..0098d7949 --- /dev/null +++ b/Sources/TokamakDemo/URLHashDemo.swift @@ -0,0 +1,52 @@ +// Copyright 2020 Tokamak contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import JavaScriptKit +import TokamakDOM + +private let location = JSObject.global.location.object! +private let window = JSObject.global.window.object! + +private final class HashState: ObservableObject { + var onHashChange: JSClosure! + + @Published var currentHash = location.hash.string! + + init() { + let onHashChange = JSClosure { [weak self] _ in + self?.currentHash = location.hash.string! + } + + window.onhashchange = .function(onHashChange) + self.onHashChange = onHashChange + } + + deinit { + window.onhashchange = .undefined + onHashChange.release() + } +} + +struct URLHashDemo: View { + @StateObject private var hashState = HashState() + + var body: some View { + VStack { + Button("Assign random location.hash") { + location.hash = .string("\(Int.random(in: 0...1000))") + } + Text("Current location.hash is \(hashState.currentHash)") + } + } +}