Set up documentation
This commit is contained in:
parent
83a03441b5
commit
2551c0a14d
29
.github/ISSUE_TEMPLATE/component_request.yml
vendored
29
.github/ISSUE_TEMPLATE/component_request.yml
vendored
@ -1,29 +0,0 @@
|
||||
name: Components request
|
||||
description: Suggest an idea for a new component
|
||||
title: Description of the component request
|
||||
labels: enhancement
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Why would you like to add a new component?
|
||||
placeholder: >-
|
||||
A clear and concise description of why the component should be added.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe your idea for the implementation.
|
||||
placeholder: >-
|
||||
What could the implementation be like in Adwaita?
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
placeholder: >-
|
||||
Add any other context about the component request here.
|
||||
validations:
|
||||
required: false
|
||||
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,5 +1,4 @@
|
||||
## Steps
|
||||
- [ ] Add your name or username and a link to your GitHub profile into the [Contributors.md][1] file.
|
||||
- [ ] Build the project on your machine. If it does not compile, fix the errors.
|
||||
- [ ] Describe the purpose and approach of your pull request below.
|
||||
- [ ] Submit the pull request. Thank you very much for your contribution!
|
||||
@ -10,5 +9,3 @@ _If there is a related issue, add the link._
|
||||
|
||||
## Approach
|
||||
_Describe how this pull request solves the problem or adds the feature._
|
||||
|
||||
[1]: /Contributors.md
|
||||
|
||||
24
.github/workflows/docs.yml
vendored
24
.github/workflows/docs.yml
vendored
@ -3,7 +3,6 @@ name: Deploy Docs
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@ -22,31 +21,20 @@ jobs:
|
||||
runs-on: macos-14
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Libadwaita
|
||||
run: |
|
||||
brew update
|
||||
brew install libadwaita
|
||||
sed -i '' 's/-I..includedir.//g' $(brew --prefix)/Library/Homebrew/os/mac/pkgconfig/*/libffi.pc
|
||||
- name: Clone DocC Repo
|
||||
run: |
|
||||
git clone https://github.com/AparokshaUI/Adwaita.docc Sources/Adwaita/Adwaita.docc
|
||||
rm Sources/Adwaita/Adwaita.docc/LICENSE.md
|
||||
rm Sources/Adwaita/Adwaita.docc/README.md
|
||||
y | rm -r Sources/Adwaita/Adwaita.docc/.git
|
||||
- name: Build Docs
|
||||
run: |
|
||||
xcrun xcodebuild docbuild \
|
||||
-scheme Adwaita \
|
||||
-scheme Meta \
|
||||
-destination 'generic/platform=macOS' \
|
||||
-derivedDataPath "$PWD/.derivedData"
|
||||
-derivedDataPath "$PWD/.derivedData" \
|
||||
-skipPackagePluginValidation
|
||||
xcrun docc process-archive transform-for-static-hosting \
|
||||
"$PWD/.derivedData/Build/Products/Debug/Adwaita.doccarchive" \
|
||||
"$PWD/.derivedData/Build/Products/Debug/Meta.doccarchive" \
|
||||
--output-path "docs" \
|
||||
--hosting-base-path "adwaita-swift"
|
||||
--hosting-base-path "Meta"
|
||||
- name: Modify Docs
|
||||
run: |
|
||||
echo "<script>window.location.href += \"/documentation/adwaita\"</script>" > docs/index.html;
|
||||
sed -i '' 's/#06f/#ea3358/g' docs/css/documentation-topic~topic~tutorials-overview.d6f5411c.css
|
||||
echo "<script>window.location.href += \"/documentation/meta\"</script>" > docs/index.html;
|
||||
sed -i '' 's/,2px/,10px/g' docs/css/index.038e887c.css
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// swift-tools-version: 5.10
|
||||
// swift-tools-version: 5.9
|
||||
//
|
||||
// Package.swift
|
||||
// Meta
|
||||
|
||||
134
README.md
134
README.md
@ -1,141 +1,57 @@
|
||||
<p align="center">
|
||||
<img width="256" alt="Adwaita Icon" src="Icons/AdwaitaIcon.png">
|
||||
<h1 align="center">Adwaita for Swift</h1>
|
||||
<h1 align="center">Meta</h1>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://aparokshaui.github.io/adwaita-swift/">
|
||||
<a href="https://aparokshaui.github.io/meta/">
|
||||
Documentation
|
||||
</a>
|
||||
·
|
||||
<a href="https://github.com/AparokshaUI/Adwaita">
|
||||
<a href="https://github.com/AparokshaUI/Meta">
|
||||
GitHub
|
||||
</a>
|
||||
</p>
|
||||
|
||||
_Adwaita_ is a framework for creating user interfaces for GNOME with an API similar to SwiftUI.
|
||||
|
||||
The following code:
|
||||
|
||||
```swift
|
||||
struct Counter: View {
|
||||
|
||||
@State private var count = 0
|
||||
|
||||
var view: Body {
|
||||
HStack {
|
||||
Button(icon: .default(icon: .goPrevious)) {
|
||||
count -= 1
|
||||
}
|
||||
Text("\(count)")
|
||||
.style("title-1")
|
||||
.frame(minWidth: 100)
|
||||
Button(icon: .default(icon: .goNext)) {
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Describes a simple counter view:
|
||||
|
||||
![Counter Example][image-1]
|
||||
|
||||
More examples are available in the [demo app][1].
|
||||
_Meta_ is a framework allowing the creation of user interface (UI) frameworks in Swift.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Goals][2]
|
||||
- [Widgets][3]
|
||||
- [Installation][4]
|
||||
- [Usage][5]
|
||||
- [Thanks][6]
|
||||
- [Overview](#overview)
|
||||
- [Usage](#usage)
|
||||
- [Thanks](#thanks)
|
||||
|
||||
## Goals
|
||||
## Overview
|
||||
|
||||
_Adwaita_’s main goal is to provide an easy-to-use interface for creating GNOME apps. The backend should stay as simple as possible, while not limiting the possibilities there are with [Libadwaita][7] and [GTK][8].
|
||||
_Meta_ follows the following principles:
|
||||
|
||||
If you want to use _Adwaita_ in a project, but there are widgets missing, open an [issue on GitHub][9].
|
||||
- It is a **declarative** framework, meaning that instead of writing _how_ to construct a user interface, you write _what_ it looks like.
|
||||
- The user interface is treated as a function of its **state**. Instead of directly modifying the UI, modify its state to update views.
|
||||
- Multiple UI frameworks can be used in the same code, but the **selection of the framework** happens when executing the app. This enables the creation of cross-platform UI frameworks combining several UI frameworks rendering always with the same backend.
|
||||
|
||||
Find more information about the project's motivation in [this blog post](https://www.swift.org/blog/adwaita-swift/).
|
||||
It knows the following layers of UI:
|
||||
|
||||
## Widgets
|
||||
- An app is the entry point of the executable, containing the windows.
|
||||
- A window is a container holding one or multiple views.
|
||||
- A view is a part of the actual UI inside a window, another view or a menu.
|
||||
- A menu is a list of buttons, other menus, and views. Certain views (such as menu buttons) allow menus to be used.
|
||||
|
||||
An overview of the widgets supported by _Adwaita_ is available [here](user-manual/Information/Widgets.md).
|
||||
Detailed information can be found in the [docs](https://aparokshaui.github.io/meta/).
|
||||
|
||||
## Installation
|
||||
### Dependencies
|
||||
#### Flatpak
|
||||
## Usage
|
||||
|
||||
It is recommended to develop apps inside of a Flatpak.
|
||||
That way, you don't have to install Swift or any of the dependencies on your system, and you always have access to the latest versions.
|
||||
Take a look at the [template repository](https://github.com/AparokshaUI/AdwaitaTemplate).
|
||||
This works on Linux only.
|
||||
_Meta_ can be used for creating UI frameworks in Swift which can then be used to create apps.
|
||||
|
||||
#### Directly on System
|
||||
Follow those steps if you want to create a UI framework.
|
||||
|
||||
You can also run your apps directly on the system.
|
||||
|
||||
If you are using a Linux distribution, install `libadwaita-devel` or `libadwaita` (or something similar, based on the package manager) as well as `gtk4-devel`, `gtk4` or similar.
|
||||
|
||||
On macOS, follow these steps:
|
||||
1. Install [Homebrew][11].
|
||||
2. Install Libadwaita (and thereby GTK 4):
|
||||
```
|
||||
brew install libadwaita
|
||||
```
|
||||
|
||||
### Swift Package
|
||||
1. Open your Swift package in GNOME Builder, Xcode, or any other IDE.
|
||||
2. Open the `Package.swift` file.
|
||||
3. Into the `Package` initializer, under `dependencies`, paste:
|
||||
```swift
|
||||
.package(url: "https://github.com/AparokshaUI/Adwaita", from: "0.1.0")
|
||||
.package(url: "https://github.com/AparokshaUI/Meta", from: "0.1.0")
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
I recommend using the [template repository](https://github.com/AparokshaUI/AdwaitaTemplate) as a starting point.
|
||||
|
||||
Follow the [interactive tutorial](https://aparokshaui.github.io/adwaita-swift/tutorials/table-of-contents) or [read the docs](https://aparokshaui.github.io/adwaita-swift/documentation/adwaita) in order to get to know _Adwaita for Swift_.
|
||||
|
||||
## Thanks
|
||||
|
||||
### Dependencies
|
||||
- [XMLCoder][18] licensed under the [MIT license][19]
|
||||
- [Levenshtein Transformations](https://github.com/david-swift/LevenshteinTransformations) licensed under the [MIT license](https://github.com/david-swift/LevenshteinTransformations/blob/main/LICENSE.md)
|
||||
|
||||
### Other Thanks
|
||||
- The [contributors][20]
|
||||
- The auto-generation of widgets is based on [Swift Cross UI](https://github.com/stackotter/swift-cross-ui)
|
||||
- [SwiftLint][21] for checking whether code style conventions are violated
|
||||
- The programming language [Swift][22]
|
||||
|
||||
[1]: Tests/
|
||||
[2]: #goals
|
||||
[3]: #widgets
|
||||
[4]: #installation
|
||||
[5]: #usage
|
||||
[6]: #thanks
|
||||
[7]: https://gnome.pages.gitlab.gnome.org/libadwaita/doc/1-latest/index.html
|
||||
[8]: https://docs.gtk.org/gtk4/
|
||||
[9]: https://github.com/AparokshaUI/Adwaita/issues
|
||||
[10]: https://github.com/AparokshaUI/Libadwaita
|
||||
[11]: https://brew.sh
|
||||
[12]: user-manual/GettingStarted.md
|
||||
[13]: user-manual/Basics/HelloWorld.md
|
||||
[14]: user-manual/Basics/CreatingViews.md
|
||||
[15]: user-manual/Basics/Windows.md
|
||||
[16]: user-manual/Basics/KeyboardShortcuts.md
|
||||
[17]: user-manual/Advanced/CreatingWidgets.md
|
||||
[18]: https://github.com/CoreOffice/XMLCoder
|
||||
[19]: https://github.com/CoreOffice/XMLCoder/blob/main/LICENSE
|
||||
[20]: Contributors.md
|
||||
[21]: https://github.com/realm/SwiftLint
|
||||
[22]: https://github.com/apple/swift
|
||||
[23]: https://github.com/SourceDocs/SourceDocs
|
||||
|
||||
[image-1]: Icons/Counter.png
|
||||
[image-2]: Icons/Demo.png
|
||||
- [DocC](https://github.com/apple/swift-docc) used for the documentation
|
||||
- [SwiftLint](https://github.com/realm/SwiftLint) for checking whether code style conventions are violated
|
||||
- The programming language [Swift](https://github.com/swiftlang/swift)
|
||||
|
||||
18
Sources/Meta.docc/Meta.md
Normal file
18
Sources/Meta.docc/Meta.md
Normal file
@ -0,0 +1,18 @@
|
||||
# ``Meta``
|
||||
|
||||
_Meta_ is a framework allowing the creation of user interface (UI) frameworks in Swift.
|
||||
|
||||
## Overview
|
||||
|
||||
_Meta_ follows the following principles:
|
||||
|
||||
- It is a **declarative** framework, meaning that instead of writing _how_ to construct a user interface, you write _what_ it looks like.
|
||||
- The user interface is treated as a function of its **state**. Instead of directly modifying the UI, modify its state to update views.
|
||||
- Multiple UI frameworks can be used in the same code, but the **selection of the framework** happens when executing the app. This enables the creation of cross-platform UI frameworks combining several UI frameworks rendering always with the same backend.
|
||||
|
||||
It knows the following layers of UI:
|
||||
|
||||
- An app is the entry point of the executable, containing the windows.
|
||||
- A window is a container holding one or multiple views.
|
||||
- A view is a part of the actual UI inside a window, another view or a menu.
|
||||
- A menu is a list of buttons, other menus, and views. Certain views (such as menu buttons) allow menus to be used.
|
||||
46
Sources/Meta.docc/theme-settings.json
Normal file
46
Sources/Meta.docc/theme-settings.json
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"theme": {
|
||||
"border-radius": "10px",
|
||||
"button": {
|
||||
"border-radius": "20px"
|
||||
},
|
||||
"color": {
|
||||
"button-background": "#ea3358",
|
||||
"button-background-active": "#ea3358",
|
||||
"button-background-hover": "#fc557a",
|
||||
"button-text": "#ffffff",
|
||||
"header": "#7f313b",
|
||||
"documentation-intro-accent": "var(--color-header)",
|
||||
"documentation-intro-fill": "radial-gradient(circle at top, var(--color-header) 30%, #000 100%)",
|
||||
"link": "#ea3358",
|
||||
"nav-link-color": "#ea3358",
|
||||
"nav-dark-link-color": "#ea3358",
|
||||
"tutorials-overview-link": "#fb4469",
|
||||
"step-background": {
|
||||
"light": "#fffaff",
|
||||
"dark": "#302c2d"
|
||||
},
|
||||
"step-focused": "#ea3358",
|
||||
"tabnav-item-border-color": "#ea3358",
|
||||
"tutorial-background": {
|
||||
"light": "",
|
||||
"dark": "#1d1d1f"
|
||||
},
|
||||
"tutorials-overview-background": "linear-gradient(180deg, rgba(43,20,23,1) 0%, rgba(41, 3, 8, 0.808) 60%, rgba(0,0,0,1) 100%)",
|
||||
"fill-light-blue-secondary": "#ea3358",
|
||||
"fill-blue": "#ea3358",
|
||||
"figure-blue": "#ea3358",
|
||||
"standard-blue-documentation-intro-fill": "#ea3358",
|
||||
"figure-blue": "#ea3358",
|
||||
"tutorial-hero-background": "#100a0b",
|
||||
"navigator-item-hover": {
|
||||
"light": "#ea335815",
|
||||
"dark": "#7f313b"
|
||||
}
|
||||
},
|
||||
"additionalProperties": "#ea3358",
|
||||
"tutorial-step": {
|
||||
"border-radius": "15px"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -71,7 +71,7 @@ public struct Binding<Value> {
|
||||
private var handlers: [(Value) -> Void] = []
|
||||
|
||||
/// Get a property of any content of a `Binding` as a `Binding`.
|
||||
/// - Parameter dynamicMember: The path to the member.
|
||||
/// - Parameter keyPath: The path to the member.
|
||||
/// - Returns: The binding.
|
||||
public subscript<Subject>(dynamicMember keyPath: WritableKeyPath<Value, Subject>) -> Binding<Subject> {
|
||||
.init {
|
||||
|
||||
@ -54,6 +54,7 @@ extension Array: AnyView where Element == AnyView {
|
||||
/// - Parameters:
|
||||
/// - modifiers: Modify views before generating the storages.
|
||||
/// - type: The type of the widgets.
|
||||
/// - Returns: The storages.
|
||||
public func storages<WidgetType>(
|
||||
modifiers: [(AnyView) -> AnyView],
|
||||
type: WidgetType.Type
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
//
|
||||
// DefaultStringInterpolation.swift
|
||||
// Meta
|
||||
//
|
||||
// Created by david-swift on 26.05.24.
|
||||
//
|
||||
// Thanks to Eneko Alonso, Pyry Jahkola, cukr for the comments in this Swift forum discussion:
|
||||
// "Multi-line string nested indentation with interpolation"
|
||||
// https://forums.swift.org/t/multi-line-string-nested-indentation-with-interpolation/36933
|
||||
//
|
||||
|
||||
extension DefaultStringInterpolation {
|
||||
|
||||
/// Preserve the indentation in a multi line string.
|
||||
/// - Parameter string: The string.
|
||||
///
|
||||
/// Use it the following way:
|
||||
/// """
|
||||
/// Hello
|
||||
/// \(indented: "World\n Test")
|
||||
/// """
|
||||
public mutating func appendInterpolation(indented string: String) {
|
||||
// swiftlint:disable compiler_protocol_init
|
||||
let indent = String(stringInterpolation: self).reversed().prefix { " \t".contains($0) }
|
||||
// swiftlint:enable compiler_protocol_init
|
||||
if indent.isEmpty {
|
||||
appendInterpolation(string)
|
||||
} else {
|
||||
appendLiteral(
|
||||
string.split(separator: "\n", omittingEmptySubsequences: false).joined(separator: "\n" + indent)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
extension String {
|
||||
|
||||
/// A label for main content in a view storage.
|
||||
static var mainContent: Self { "main" }
|
||||
/// An identifier for main content in a view storage.
|
||||
public static var mainContent: Self { "main" }
|
||||
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ extension AnyView {
|
||||
/// Wrap the view into a widget.
|
||||
/// - Parameter modifiers: Modify views before being updated.
|
||||
/// - Returns: The widget.
|
||||
public func widget(modifiers: [(AnyView) -> AnyView]) -> Widget {
|
||||
func widget(modifiers: [(AnyView) -> AnyView]) -> Widget {
|
||||
let modified = getModified(modifiers: modifiers)
|
||||
if let peer = modified as? Widget {
|
||||
return peer
|
||||
|
||||
@ -11,7 +11,7 @@ import Foundation
|
||||
@resultBuilder
|
||||
public enum ViewBuilder {
|
||||
|
||||
/// A component used in the ``ArrayBuilder``.
|
||||
/// A component used in the ``ViewBuilder``.
|
||||
public enum Component {
|
||||
|
||||
/// A view as a component.
|
||||
|
||||
@ -5,19 +5,22 @@
|
||||
// Created by david-swift on 26.05.24.
|
||||
//
|
||||
|
||||
/// Store a rendered view in a view storage.
|
||||
/// Store a reference to a rendered view in a view storage.
|
||||
public class ViewStorage {
|
||||
|
||||
/// The pointer.
|
||||
///
|
||||
/// It can be a C pointer, a Swift class, or other information depending on the backend.
|
||||
/// Some convenience widgets do not need a pointer to a native framework at all.
|
||||
public var pointer: Any?
|
||||
/// The view's content.
|
||||
/// The view's content for container widgets.
|
||||
public var content: [String: [ViewStorage]]
|
||||
/// The view's state (used in `StateWrapper`).
|
||||
var state: [String: StateProtocol] = [:]
|
||||
/// Other properties.
|
||||
/// Various properties of a widget.
|
||||
public var fields: [String: Any] = [:]
|
||||
|
||||
/// The pointer as an opaque pointer.
|
||||
/// The pointer as an opaque pointer, as this is needed with backends interoperating with C or C++.
|
||||
public var opaquePointer: OpaquePointer? {
|
||||
get {
|
||||
pointer as? OpaquePointer
|
||||
@ -30,7 +33,7 @@ public class ViewStorage {
|
||||
/// Initialize a view storage.
|
||||
/// - Parameters:
|
||||
/// - pointer: The pointer to the widget, its type depends on the backend.
|
||||
/// - content: The view's content.
|
||||
/// - content: The view's content for container widgets.
|
||||
public init(
|
||||
_ pointer: Any?,
|
||||
content: [String: [ViewStorage]] = [:]
|
||||
|
||||
@ -5,7 +5,10 @@
|
||||
// Created by david-swift on 26.05.24.
|
||||
//
|
||||
|
||||
/// A widget is a view that know about its GTUI widget.
|
||||
/// A widget is a view that know about its native backend widget.
|
||||
///
|
||||
/// It enables the translation from the declarative definition to the creation
|
||||
/// and updating of widgets in an imperative way.
|
||||
public protocol Widget: AnyView {
|
||||
|
||||
/// The view storage.
|
||||
|
||||
@ -8,19 +8,16 @@
|
||||
import Observation
|
||||
|
||||
/// A storage for `@State` properties.
|
||||
public struct StateWrapper: ConvenienceWidget {
|
||||
struct StateWrapper: ConvenienceWidget {
|
||||
|
||||
/// The content.
|
||||
var content: () -> Body
|
||||
/// The state information (from properties with the `State` wrapper).
|
||||
var state: [String: StateProtocol] = [:]
|
||||
|
||||
/// The identifier of the field storing whether to update the wrapper's content.
|
||||
private var updateID: String { "update" }
|
||||
|
||||
/// Initialize a `StateWrapper`.
|
||||
/// - Parameter content: The view content.
|
||||
public init(@ViewBuilder content: @escaping () -> Body) {
|
||||
init(@ViewBuilder content: @escaping () -> Body) {
|
||||
self.content = content
|
||||
}
|
||||
|
||||
@ -39,14 +36,13 @@ public struct StateWrapper: ConvenienceWidget {
|
||||
/// - modifiers: Modify views before being updated.
|
||||
/// - updateProperties: Whether to update properties.
|
||||
/// - type: The type of the widgets.
|
||||
public func update<WidgetType>(
|
||||
func update<WidgetType>(
|
||||
_ storage: ViewStorage,
|
||||
modifiers: [(AnyView) -> AnyView],
|
||||
updateProperties: Bool,
|
||||
type: WidgetType.Type
|
||||
) {
|
||||
var updateProperties = updateProperties ? true : (storage.fields[updateID] as? Bool ?? false)
|
||||
storage.fields[updateID] = false
|
||||
var updateProperties = updateProperties
|
||||
for property in state {
|
||||
if let oldID = storage.state[property.key]?.id {
|
||||
StateManager.changeID(old: oldID, new: property.value.id)
|
||||
@ -68,7 +64,7 @@ public struct StateWrapper: ConvenienceWidget {
|
||||
/// - modifiers: Modify views before being updated.
|
||||
/// - type: The type of the widgets.
|
||||
/// - Returns: The view storage.
|
||||
public func container<WidgetType>(modifiers: [(AnyView) -> AnyView], type: WidgetType.Type) -> ViewStorage {
|
||||
func container<WidgetType>(modifiers: [(AnyView) -> AnyView], type: WidgetType.Type) -> ViewStorage {
|
||||
let content = content().storages(modifiers: modifiers, type: type)
|
||||
let storage = ViewStorage(nil, content: [.mainContent: content])
|
||||
storage.state = state
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
// Created by david-swift on 27.05.24.
|
||||
//
|
||||
|
||||
/// Wrap a view into a single widget.
|
||||
/// Wrap a body into a single widget.
|
||||
public struct Wrapper: ConvenienceWidget {
|
||||
|
||||
/// The content.
|
||||
|
||||
@ -65,12 +65,11 @@ struct DemoApp {
|
||||
DemoView().updateStorage(storage, modifiers: [], updateProperties: true, type: backendType)
|
||||
}
|
||||
|
||||
StateManager.addUpdateHandler { _ in
|
||||
DemoView().updateStorage(storage, modifiers: [], updateProperties: false, type: backendType)
|
||||
StateManager.addUpdateHandler { force in
|
||||
DemoView().updateStorage(storage, modifiers: [], updateProperties: force, type: backendType)
|
||||
}
|
||||
|
||||
sleep(2)
|
||||
DemoView().updateStorage(storage, modifiers: [], updateProperties: true, type: backendType)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user