initial commit

This commit is contained in:
2026-07-27 14:42:23 +02:00
commit 833c68a189
257 changed files with 17947 additions and 0 deletions
+45
View File
@@ -0,0 +1,45 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
/coverage/
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
+45
View File
@@ -0,0 +1,45 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "ff37bef603469fb030f2b72995ab929ccfc227f0"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
- platform: android
create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
- platform: ios
create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
- platform: linux
create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
- platform: macos
create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
- platform: web
create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
- platform: windows
create_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
base_revision: ff37bef603469fb030f2b72995ab929ccfc227f0
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
+161
View File
@@ -0,0 +1,161 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## What this is
NodeMaster Manager — a Flutter GUI client for the NodeMaster API, a Go/Beego
backend that lives in the sibling repo `../nodemaster` (i.e.
`/home/yves/Documents/code/PROJECTS/nodemaster/nodemaster` if this repo is
checked out at `/home/yves/Documents/code/PROJECTS/nodemaster/manager`).
NodeMaster manages a homelab-style host: docker-compose "services" (start/
stop/backup), restic/rsync backup targets, OS update history, and a fleet of
other NodeMaster nodes. This app is the multi-platform (Linux/macOS/Windows/
web/Android/iOS) desktop-first UI over that API's REST endpoints under `/v1`.
**The Go API is the source of truth for wire shapes.** Every Dart model in
`lib/core/models/` mirrors a Go struct in `../nodemaster/models/`, field for
field, including `@JsonKey` renames for snake_case. When the API changes,
re-read the actual Go source (`models/*.go`, `controllers/*.go`) rather than
trusting existing Dart models or prior assumptions — they can drift, and
swagger docs in that repo have been observed stale relative to the
controllers. Neither repo currently has authentication; the API is meant to
sit behind a VPN/reverse proxy (see the `NoAuthCallout` banner on Settings).
## Commands
```bash
flutter pub get # install deps
dart run build_runner build --delete-conflicting-outputs # regenerate *.freezed.dart / *.g.dart
dart run build_runner watch --delete-conflicting-outputs # regenerate on save, for long edit sessions
flutter analyze # static analysis (must be clean)
flutter test # full test suite
flutter test test/core/models/service_test.dart # single test file
flutter test --plain-name "parses a fully-populated service" # single test by name
flutter run -d chrome # run as web app
flutter run -d linux # run as Linux desktop app
flutter build linux --debug # build the Linux bundle (build/linux/x64/debug/bundle/manager)
```
**Any change to a `@freezed` or `@riverpod`/`@Riverpod` class requires a
`build_runner build` afterward** — the `.freezed.dart`/`.g.dart` companion
files are committed generated code, not build artifacts recreated from
scratch each time, so a source edit without regeneration leaves the app
compiling against stale generated code (or plain compile errors if fields
changed). If a diagnostics pass immediately after a `build_runner` run shows
errors referencing symbols you didn't touch, it's very likely IDE/analyzer
staleness from the file swap — rerun `flutter analyze` fresh before
concluding something is actually broken.
To run the app against a live API, start the sibling Go repo first
(`cd ../nodemaster && go run main.go`, default port `8080`, config at
`~/.nodemaster.conf`), then add a connection in Settings pointing at it (or a
pre-seeded `SharedPreferences` `connections` value in tests — see
`test/widget_test.dart`).
## Architecture
### Layering: `core/network` → `data/repositories` → `features/*/providers` → screens
- **`lib/core/network/node_master_api_client.dart`** — one `NodeMasterApiClient`
class, one method per REST endpoint, thin (dio call in, typed model out).
Every method funnels through `_guard`, which enforces a hard 20s request
budget (`Future.timeout`, not just Dio's own timeouts — needed because
Dio's web/browser adapter has no connect-phase timeout hook) and maps every
failure mode to a typed `ApiException` via `dio_error_mapper.dart`. This is
the *only* place that touches `Dio`/`DioException` directly.
- **`lib/data/repositories/*_repository.dart`** — one repository per REST
resource group (`NodeRepository`, `ServicesRepository`, `NodesRepository`),
each a thin pass-through over `NodeMasterApiClient`. Each repository has a
paired `@riverpod` provider (e.g. `nodeRepositoryProvider`) that returns
**null when there's no active connection** — this null-propagation pattern
is used consistently up through `apiClientProvider` so every downstream
provider gets the same "no connection" signal without re-deriving it.
- **`lib/features/<name>/`** — one folder per nav destination (`dashboard`,
`services`, `backups`, `fleet`, `updates`, `settings`), each with a
top-level `<name>_screen.dart`, a `widgets/` subfolder for
feature-local dialogs/rows, and a `providers/` subfolder where the screen
needs bespoke async state beyond a bare repository call.
### State management: Riverpod 3 with code generation
All providers use `@riverpod`/`@Riverpod(...)` annotations + generated `.g.dart`
companions (not the older manual `Provider`/`StateNotifierProvider` syntax).
`main.dart` disables Riverpod 3's container-wide auto-retry
(`retry: (retryCount, error) => null`) because the app already has its own
explicit refresh model (manual pull-to-refresh + `PollingMixin` for two
screens) — a blanket retry-with-backoff would silently fight that. Widget
tests must pass the same `retry: null` override or a deliberately-unreachable
test connection won't settle into `AsyncError` deterministically.
`lib/core/polling/polling_async_notifier.dart`'s `PollingMixin<T>` is mixed
into an `AutoDisposeAsyncNotifier` to re-fetch on a timer while the provider
has a listener (used by Dashboard's summary and Fleet's aggregated view —
the API has no push/websocket, so this is a deliberate "poll while visible"
model, not a live stream). It never emits an intermediate `AsyncLoading` on
refresh ticks, so a background poll never flashes the UI back to a spinner.
Other list-backed screens (Services, node backup config, updates) are
manual-refresh only, on purpose — a silent background refresh could yank
state out from under an in-progress edit dialog.
### Connections (multi-host support)
`lib/core/connections/` models a list of saved API endpoints
(`Connection { id, name, baseUrl }`), persisted as plain JSON in
`SharedPreferences` via `ConnectionStorage` (explicitly *not* a secret store
— the API has no auth, so a saved base URL isn't sensitive by itself).
`activeConnectionProvider` (in `connection_providers.dart`) is the single
source everything downstream derives from: `apiClientProvider` rebuilds
(never mutates) a fresh `Dio`/`NodeMasterApiClient` whenever it changes, which
cascades through every repository and feature provider automatically.
### Routing
`lib/core/routing/app_router.dart` uses `go_router` with a single
`@Riverpod(keepAlive: true)` `GoRouter`. A `_ConnectionRefreshListenable`
bridges `activeConnectionProvider` into go_router's `refreshListenable` so
removing the active connection redirects to Settings immediately rather than
waiting for the next navigation. All feature screens sit inside one
`ShellRoute` wrapping `NavRailShell` (the persistent side nav).
### Models (`lib/core/models/`)
`@freezed` sealed classes + `json_serializable` (`explicit_to_json: true` in
`build.yaml`), one file per Go struct, with `part 'x.freezed.dart'` /
`part 'x.g.dart'`. Field renames to match the API's snake_case use
`@JsonKey(name: '...')`. Write-only fields the API never echoes back (e.g. a
password) should default to `null`/omitted-on-null (`includeIfNull: false`)
rather than round-tripping a value the server will never actually send.
`lib/core/models/models.dart` is the barrel export — import that, not
individual model files, from feature code.
### Theming
`lib/core/theme/` defines two custom `ThemeExtension`s — `StatusColors`
(good/warning/serious/critical, reserved exclusively for status semantics,
never reused as a brand color) and `AppDataStyles` (monospace styles for
numeric/data display). Access via the `BuildContext` extension in
`theme_x.dart`: `context.status.good`, `context.dataStyles.dataMono`,
`context.colors`, `context.text` — prefer these over raw
`Theme.of(context).extension<...>()!` calls. `StatusPill` (`core/widgets/`)
is the shared good/warning/serious/critical/neutral badge — reuse it rather
than building ad hoc colored chips.
### Error handling
`ApiException` (`core/network/api_exception.dart`) is a sealed/freezed-style
type with variants for timeout, network, cancelled, server (with status code
+ message), parse, and unknown. UI code catches `ApiException` and reads
`.userMessage` for display; it should never need to inspect `DioException` or
raw status codes directly.
## Testing conventions
Widget tests spin up a real `ProviderScope` with `retry: null` and
`SharedPreferences.setMockInitialValues(...)` to seed connection state (see
`test/widget_test.dart`) rather than mocking providers individually — this
exercises the actual router-redirect and provider-null-propagation logic. A
deliberately unreachable connection (`http://127.0.0.1:1`) is used to get a
fast, deterministic connection-refused error without depending on real
network access. `mocktail`/`fake_async` are available as dev dependencies for
narrower unit tests (e.g. `dio_error_mapper_test.dart`).
+17
View File
@@ -0,0 +1,17 @@
# manager
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter)
- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
+36
View File
@@ -0,0 +1,36 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
analyzer:
errors:
# False positive on every freezed class that puts @JsonKey on a factory
# constructor parameter (the standard, documented pattern) — freezed
# forwards the annotation to the generated field correctly; the analyzer
# just doesn't see that at the constructor-parameter site.
invalid_annotation_target: ignore
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at https://dart.dev/lints.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
+14
View File
@@ -0,0 +1,14 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
.cxx/
# Remember to never publicly share your keystore.
# See https://flutter.dev/to/reference-keystore
key.properties
**/*.keystore
**/*.jks
+44
View File
@@ -0,0 +1,44 @@
plugins {
id("com.android.application")
id("kotlin-android")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
}
android {
namespace = "com.example.manager"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.manager"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug")
}
}
}
flutter {
source = "../.."
}
@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
+45
View File
@@ -0,0 +1,45 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="manager"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>
@@ -0,0 +1,5 @@
package com.example.manager
import io.flutter.embedding.android.FlutterActivity
class MainActivity : FlutterActivity()
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
+24
View File
@@ -0,0 +1,24 @@
allprojects {
repositories {
google()
mavenCentral()
}
}
val newBuildDir: Directory =
rootProject.layout.buildDirectory
.dir("../../build")
.get()
rootProject.layout.buildDirectory.value(newBuildDir)
subprojects {
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
project.layout.buildDirectory.value(newSubprojectBuildDir)
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register<Delete>("clean") {
delete(rootProject.layout.buildDirectory)
}
+2
View File
@@ -0,0 +1,2 @@
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
+5
View File
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip
+26
View File
@@ -0,0 +1,26 @@
pluginManagement {
val flutterSdkPath =
run {
val properties = java.util.Properties()
file("local.properties").inputStream().use { properties.load(it) }
val flutterSdkPath = properties.getProperty("flutter.sdk")
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
flutterSdkPath
}
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.11.1" apply false
id("org.jetbrains.kotlin.android") version "2.2.20" apply false
}
include(":app")
+93
View File
@@ -0,0 +1,93 @@
Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
Binary file not shown.
+93
View File
@@ -0,0 +1,93 @@
Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at: https://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
Binary file not shown.
+6
View File
@@ -0,0 +1,6 @@
targets:
$default:
builders:
json_serializable:
options:
explicit_to_json: true
+3
View File
@@ -0,0 +1,3 @@
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:
+34
View File
@@ -0,0 +1,34 @@
**/dgph
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3
+24
View File
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
</dict>
</plist>
+1
View File
@@ -0,0 +1 @@
#include "Generated.xcconfig"
+1
View File
@@ -0,0 +1 @@
#include "Generated.xcconfig"
+620
View File
@@ -0,0 +1,620 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
remoteInfo = Runner;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
331C8082294A63A400263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C807B294A618700263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
);
path = Runner;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
331C8080294A63A400263BE5 /* RunnerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
331C807D294A63A400263BE5 /* Sources */,
331C807F294A63A400263BE5 /* Resources */,
);
buildRules = (
);
dependencies = (
331C8086294A63A400263BE5 /* PBXTargetDependency */,
);
name = RunnerTests;
productName = RunnerTests;
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C8080294A63A400263BE5 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = 97C146ED1CF9000F007C117D;
};
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 1100;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
331C8080294A63A400263BE5 /* RunnerTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
331C807F294A63A400263BE5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
331C807D294A63A400263BE5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 97C146ED1CF9000F007C117D /* Runner */;
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.manager;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
331C8088294A63A400263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.manager.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Debug;
};
331C8089294A63A400263BE5 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.manager.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Release;
};
331C808A294A63A400263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.manager.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.manager;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.manager;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
331C8088294A63A400263BE5 /* Debug */,
331C8089294A63A400263BE5 /* Release */,
331C808A294A63A400263BE5 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "331C8080294A63A400263BE5"
BuildableName = "RunnerTests.xctest"
BlueprintName = "RunnerTests"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
+16
View File
@@ -0,0 +1,16 @@
import Flutter
import UIKit
@main
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
}
}
@@ -0,0 +1,122 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

@@ -0,0 +1,5 @@
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
+70
View File
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Manager</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>manager</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneConfigurationName</key>
<string>flutter</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
+1
View File
@@ -0,0 +1 @@
#import "GeneratedPluginRegistrant.h"
+6
View File
@@ -0,0 +1,6 @@
import Flutter
import UIKit
class SceneDelegate: FlutterSceneDelegate {
}
+12
View File
@@ -0,0 +1,12 @@
import Flutter
import UIKit
import XCTest
class RunnerTests: XCTestCase {
func testExample() {
// If you add code to the Runner application, consider adding tests here.
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
}
}
+25
View File
@@ -0,0 +1,25 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'core/routing/app_router.dart';
import 'core/theme/app_theme.dart';
import 'core/theme/theme_mode_provider.dart';
class App extends ConsumerWidget {
const App({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final router = ref.watch(appRouterProvider);
final themeMode = ref.watch(themeModeControllerProvider);
return MaterialApp.router(
title: 'NodeMaster Manager',
debugShowCheckedModeBanner: false,
theme: AppTheme.light(),
darkTheme: AppTheme.dark(),
themeMode: themeMode,
routerConfig: router,
);
}
}
+19
View File
@@ -0,0 +1,19 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'connection.freezed.dart';
part 'connection.g.dart';
/// A saved NodeMaster API endpoint. Client-side only — has no server-side
/// counterpart. `baseUrl` excludes the `/v1` suffix (added by
/// [NodeMasterApiClient]) and any trailing slash, e.g.
/// `https://edge-01.local:8080`.
@freezed
sealed class Connection with _$Connection {
const factory Connection({
required String id,
required String name,
required String baseUrl,
}) = _Connection;
factory Connection.fromJson(Map<String, dynamic> json) => _$ConnectionFromJson(json);
}
@@ -0,0 +1,277 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'connection.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$Connection {
String get id; String get name; String get baseUrl;
/// Create a copy of Connection
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$ConnectionCopyWith<Connection> get copyWith => _$ConnectionCopyWithImpl<Connection>(this as Connection, _$identity);
/// Serializes this Connection to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is Connection&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.baseUrl, baseUrl) || other.baseUrl == baseUrl));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,name,baseUrl);
@override
String toString() {
return 'Connection(id: $id, name: $name, baseUrl: $baseUrl)';
}
}
/// @nodoc
abstract mixin class $ConnectionCopyWith<$Res> {
factory $ConnectionCopyWith(Connection value, $Res Function(Connection) _then) = _$ConnectionCopyWithImpl;
@useResult
$Res call({
String id, String name, String baseUrl
});
}
/// @nodoc
class _$ConnectionCopyWithImpl<$Res>
implements $ConnectionCopyWith<$Res> {
_$ConnectionCopyWithImpl(this._self, this._then);
final Connection _self;
final $Res Function(Connection) _then;
/// Create a copy of Connection
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? baseUrl = null,}) {
return _then(_self.copyWith(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
as String,baseUrl: null == baseUrl ? _self.baseUrl : baseUrl // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// Adds pattern-matching-related methods to [Connection].
extension ConnectionPatterns on Connection {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _Connection value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _Connection() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _Connection value) $default,){
final _that = this;
switch (_that) {
case _Connection():
return $default(_that);}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _Connection value)? $default,){
final _that = this;
switch (_that) {
case _Connection() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String name, String baseUrl)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _Connection() when $default != null:
return $default(_that.id,_that.name,_that.baseUrl);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String name, String baseUrl) $default,) {final _that = this;
switch (_that) {
case _Connection():
return $default(_that.id,_that.name,_that.baseUrl);}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String name, String baseUrl)? $default,) {final _that = this;
switch (_that) {
case _Connection() when $default != null:
return $default(_that.id,_that.name,_that.baseUrl);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _Connection implements Connection {
const _Connection({required this.id, required this.name, required this.baseUrl});
factory _Connection.fromJson(Map<String, dynamic> json) => _$ConnectionFromJson(json);
@override final String id;
@override final String name;
@override final String baseUrl;
/// Create a copy of Connection
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$ConnectionCopyWith<_Connection> get copyWith => __$ConnectionCopyWithImpl<_Connection>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$ConnectionToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Connection&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.baseUrl, baseUrl) || other.baseUrl == baseUrl));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,name,baseUrl);
@override
String toString() {
return 'Connection(id: $id, name: $name, baseUrl: $baseUrl)';
}
}
/// @nodoc
abstract mixin class _$ConnectionCopyWith<$Res> implements $ConnectionCopyWith<$Res> {
factory _$ConnectionCopyWith(_Connection value, $Res Function(_Connection) _then) = __$ConnectionCopyWithImpl;
@override @useResult
$Res call({
String id, String name, String baseUrl
});
}
/// @nodoc
class __$ConnectionCopyWithImpl<$Res>
implements _$ConnectionCopyWith<$Res> {
__$ConnectionCopyWithImpl(this._self, this._then);
final _Connection _self;
final $Res Function(_Connection) _then;
/// Create a copy of Connection
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? baseUrl = null,}) {
return _then(_Connection(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
as String,baseUrl: null == baseUrl ? _self.baseUrl : baseUrl // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
// dart format on
+20
View File
@@ -0,0 +1,20 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'connection.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_Connection _$ConnectionFromJson(Map<String, dynamic> json) => _Connection(
id: json['id'] as String,
name: json['name'] as String,
baseUrl: json['baseUrl'] as String,
);
Map<String, dynamic> _$ConnectionToJson(_Connection instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
'baseUrl': instance.baseUrl,
};
@@ -0,0 +1,75 @@
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../utils/shared_preferences_provider.dart';
import 'connection.dart';
import 'connection_storage.dart';
part 'connection_providers.g.dart';
@Riverpod(keepAlive: true)
ConnectionStorage connectionStorage(Ref ref) {
return ConnectionStorage(ref.watch(sharedPreferencesProvider));
}
/// The full list of saved connections. Mutations persist immediately.
@Riverpod(keepAlive: true)
class SavedConnections extends _$SavedConnections {
@override
List<Connection> build() => ref.watch(connectionStorageProvider).readConnections();
Future<void> add(Connection connection) async {
state = [...state, connection];
await ref.read(connectionStorageProvider).writeConnections(state);
}
Future<void> update(Connection connection) async {
state = [
for (final c in state)
if (c.id == connection.id) connection else c,
];
await ref.read(connectionStorageProvider).writeConnections(state);
}
Future<void> remove(String id) async {
state = state.where((c) => c.id != id).toList(growable: false);
await ref.read(connectionStorageProvider).writeConnections(state);
final activeId = ref.read(activeConnectionIdProvider);
if (activeId == id) {
await ref.read(activeConnectionIdProvider.notifier).setActive(
state.isEmpty ? null : state.first.id,
);
}
}
}
/// The id of the currently active connection, or null if none is selected
/// (e.g. first launch with nothing configured yet).
@Riverpod(keepAlive: true)
class ActiveConnectionId extends _$ActiveConnectionId {
@override
String? build() {
final stored = ref.watch(connectionStorageProvider).readActiveConnectionId();
final connections = ref.watch(savedConnectionsProvider);
if (stored != null && connections.any((c) => c.id == stored)) return stored;
return connections.isEmpty ? null : connections.first.id;
}
Future<void> setActive(String? id) async {
state = id;
await ref.read(connectionStorageProvider).writeActiveConnectionId(id);
}
}
/// The currently active [Connection], or null if none is configured.
/// Everything in `core/network` derives from this — switching it rebuilds
/// the API client and, transitively, every provider that watches it.
@riverpod
Connection? activeConnection(Ref ref) {
final id = ref.watch(activeConnectionIdProvider);
if (id == null) return null;
final connections = ref.watch(savedConnectionsProvider);
for (final c in connections) {
if (c.id == id) return c;
}
return null;
}
@@ -0,0 +1,232 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'connection_providers.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint, type=warning
@ProviderFor(connectionStorage)
const connectionStorageProvider = ConnectionStorageProvider._();
final class ConnectionStorageProvider
extends
$FunctionalProvider<
ConnectionStorage,
ConnectionStorage,
ConnectionStorage
>
with $Provider<ConnectionStorage> {
const ConnectionStorageProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'connectionStorageProvider',
isAutoDispose: false,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$connectionStorageHash();
@$internal
@override
$ProviderElement<ConnectionStorage> $createElement(
$ProviderPointer pointer,
) => $ProviderElement(pointer);
@override
ConnectionStorage create(Ref ref) {
return connectionStorage(ref);
}
/// {@macro riverpod.override_with_value}
Override overrideWithValue(ConnectionStorage value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<ConnectionStorage>(value),
);
}
}
String _$connectionStorageHash() => r'0faf909e3978260785f2f8ce4bc41f101e27ad66';
/// The full list of saved connections. Mutations persist immediately.
@ProviderFor(SavedConnections)
const savedConnectionsProvider = SavedConnectionsProvider._();
/// The full list of saved connections. Mutations persist immediately.
final class SavedConnectionsProvider
extends $NotifierProvider<SavedConnections, List<Connection>> {
/// The full list of saved connections. Mutations persist immediately.
const SavedConnectionsProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'savedConnectionsProvider',
isAutoDispose: false,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$savedConnectionsHash();
@$internal
@override
SavedConnections create() => SavedConnections();
/// {@macro riverpod.override_with_value}
Override overrideWithValue(List<Connection> value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<List<Connection>>(value),
);
}
}
String _$savedConnectionsHash() => r'2595280b9ef1f5835ecce70b791a901a51aaf8e8';
/// The full list of saved connections. Mutations persist immediately.
abstract class _$SavedConnections extends $Notifier<List<Connection>> {
List<Connection> build();
@$mustCallSuper
@override
void runBuild() {
final created = build();
final ref = this.ref as $Ref<List<Connection>, List<Connection>>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<List<Connection>, List<Connection>>,
List<Connection>,
Object?,
Object?
>;
element.handleValue(ref, created);
}
}
/// The id of the currently active connection, or null if none is selected
/// (e.g. first launch with nothing configured yet).
@ProviderFor(ActiveConnectionId)
const activeConnectionIdProvider = ActiveConnectionIdProvider._();
/// The id of the currently active connection, or null if none is selected
/// (e.g. first launch with nothing configured yet).
final class ActiveConnectionIdProvider
extends $NotifierProvider<ActiveConnectionId, String?> {
/// The id of the currently active connection, or null if none is selected
/// (e.g. first launch with nothing configured yet).
const ActiveConnectionIdProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'activeConnectionIdProvider',
isAutoDispose: false,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$activeConnectionIdHash();
@$internal
@override
ActiveConnectionId create() => ActiveConnectionId();
/// {@macro riverpod.override_with_value}
Override overrideWithValue(String? value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<String?>(value),
);
}
}
String _$activeConnectionIdHash() =>
r'ac8b7d48bc04e6f9245b23c83a15e11a539e1fc8';
/// The id of the currently active connection, or null if none is selected
/// (e.g. first launch with nothing configured yet).
abstract class _$ActiveConnectionId extends $Notifier<String?> {
String? build();
@$mustCallSuper
@override
void runBuild() {
final created = build();
final ref = this.ref as $Ref<String?, String?>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<String?, String?>,
String?,
Object?,
Object?
>;
element.handleValue(ref, created);
}
}
/// The currently active [Connection], or null if none is configured.
/// Everything in `core/network` derives from this — switching it rebuilds
/// the API client and, transitively, every provider that watches it.
@ProviderFor(activeConnection)
const activeConnectionProvider = ActiveConnectionProvider._();
/// The currently active [Connection], or null if none is configured.
/// Everything in `core/network` derives from this — switching it rebuilds
/// the API client and, transitively, every provider that watches it.
final class ActiveConnectionProvider
extends $FunctionalProvider<Connection?, Connection?, Connection?>
with $Provider<Connection?> {
/// The currently active [Connection], or null if none is configured.
/// Everything in `core/network` derives from this — switching it rebuilds
/// the API client and, transitively, every provider that watches it.
const ActiveConnectionProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'activeConnectionProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$activeConnectionHash();
@$internal
@override
$ProviderElement<Connection?> $createElement($ProviderPointer pointer) =>
$ProviderElement(pointer);
@override
Connection? create(Ref ref) {
return activeConnection(ref);
}
/// {@macro riverpod.override_with_value}
Override overrideWithValue(Connection? value) {
return $ProviderOverride(
origin: this,
providerOverride: $SyncValueProvider<Connection?>(value),
);
}
}
String _$activeConnectionHash() => r'544cf6f795b35636cbfc497e6379a84b1e8f5b88';
@@ -0,0 +1,41 @@
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import 'connection.dart';
const _connectionsKey = 'connections';
const _activeConnectionIdKey = 'active_connection_id';
/// Reads/writes the saved connection list and active-connection id to
/// [SharedPreferences] as a plain JSON-encoded array. Not a secret store —
/// the API has no auth, so there's nothing sensitive in a saved base URL.
class ConnectionStorage {
const ConnectionStorage(this._prefs);
final SharedPreferences _prefs;
List<Connection> readConnections() {
final raw = _prefs.getString(_connectionsKey);
if (raw == null || raw.isEmpty) return const [];
final decoded = jsonDecode(raw) as List<dynamic>;
return decoded
.map((e) => Connection.fromJson(e as Map<String, dynamic>))
.toList(growable: false);
}
Future<void> writeConnections(List<Connection> connections) async {
final encoded = jsonEncode(connections.map((c) => c.toJson()).toList());
await _prefs.setString(_connectionsKey, encoded);
}
String? readActiveConnectionId() => _prefs.getString(_activeConnectionIdKey);
Future<void> writeActiveConnectionId(String? id) async {
if (id == null) {
await _prefs.remove(_activeConnectionIdKey);
} else {
await _prefs.setString(_activeConnectionIdKey, id);
}
}
}
@@ -0,0 +1,25 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'remote_node.dart';
import 'service.dart';
part 'aggregated_node_status.freezed.dart';
part 'aggregated_node_status.g.dart';
/// Mirrors the anonymous `nodeServices` struct returned by
/// `GET /nodes/aggregated`: `{node, services?, error?}`. `error` is the
/// *local* API reporting that fetching *this remote* failed (e.g.
/// unreachable) — a per-entry condition, distinct from the outer call
/// itself failing. Render `error` inline per-card; never conflate it with
/// an [ApiException] on the aggregated fetch as a whole.
@freezed
sealed class AggregatedNodeStatus with _$AggregatedNodeStatus {
const factory AggregatedNodeStatus({
required RemoteNode node,
@Default(<Service>[]) List<Service> services,
String? error,
}) = _AggregatedNodeStatus;
factory AggregatedNodeStatus.fromJson(Map<String, dynamic> json) =>
_$AggregatedNodeStatusFromJson(json);
}
@@ -0,0 +1,301 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'aggregated_node_status.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$AggregatedNodeStatus {
RemoteNode get node; List<Service> get services; String? get error;
/// Create a copy of AggregatedNodeStatus
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$AggregatedNodeStatusCopyWith<AggregatedNodeStatus> get copyWith => _$AggregatedNodeStatusCopyWithImpl<AggregatedNodeStatus>(this as AggregatedNodeStatus, _$identity);
/// Serializes this AggregatedNodeStatus to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is AggregatedNodeStatus&&(identical(other.node, node) || other.node == node)&&const DeepCollectionEquality().equals(other.services, services)&&(identical(other.error, error) || other.error == error));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,node,const DeepCollectionEquality().hash(services),error);
@override
String toString() {
return 'AggregatedNodeStatus(node: $node, services: $services, error: $error)';
}
}
/// @nodoc
abstract mixin class $AggregatedNodeStatusCopyWith<$Res> {
factory $AggregatedNodeStatusCopyWith(AggregatedNodeStatus value, $Res Function(AggregatedNodeStatus) _then) = _$AggregatedNodeStatusCopyWithImpl;
@useResult
$Res call({
RemoteNode node, List<Service> services, String? error
});
$RemoteNodeCopyWith<$Res> get node;
}
/// @nodoc
class _$AggregatedNodeStatusCopyWithImpl<$Res>
implements $AggregatedNodeStatusCopyWith<$Res> {
_$AggregatedNodeStatusCopyWithImpl(this._self, this._then);
final AggregatedNodeStatus _self;
final $Res Function(AggregatedNodeStatus) _then;
/// Create a copy of AggregatedNodeStatus
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? node = null,Object? services = null,Object? error = freezed,}) {
return _then(_self.copyWith(
node: null == node ? _self.node : node // ignore: cast_nullable_to_non_nullable
as RemoteNode,services: null == services ? _self.services : services // ignore: cast_nullable_to_non_nullable
as List<Service>,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
as String?,
));
}
/// Create a copy of AggregatedNodeStatus
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$RemoteNodeCopyWith<$Res> get node {
return $RemoteNodeCopyWith<$Res>(_self.node, (value) {
return _then(_self.copyWith(node: value));
});
}
}
/// Adds pattern-matching-related methods to [AggregatedNodeStatus].
extension AggregatedNodeStatusPatterns on AggregatedNodeStatus {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _AggregatedNodeStatus value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _AggregatedNodeStatus() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _AggregatedNodeStatus value) $default,){
final _that = this;
switch (_that) {
case _AggregatedNodeStatus():
return $default(_that);}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _AggregatedNodeStatus value)? $default,){
final _that = this;
switch (_that) {
case _AggregatedNodeStatus() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( RemoteNode node, List<Service> services, String? error)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _AggregatedNodeStatus() when $default != null:
return $default(_that.node,_that.services,_that.error);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( RemoteNode node, List<Service> services, String? error) $default,) {final _that = this;
switch (_that) {
case _AggregatedNodeStatus():
return $default(_that.node,_that.services,_that.error);}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( RemoteNode node, List<Service> services, String? error)? $default,) {final _that = this;
switch (_that) {
case _AggregatedNodeStatus() when $default != null:
return $default(_that.node,_that.services,_that.error);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _AggregatedNodeStatus implements AggregatedNodeStatus {
const _AggregatedNodeStatus({required this.node, final List<Service> services = const <Service>[], this.error}): _services = services;
factory _AggregatedNodeStatus.fromJson(Map<String, dynamic> json) => _$AggregatedNodeStatusFromJson(json);
@override final RemoteNode node;
final List<Service> _services;
@override@JsonKey() List<Service> get services {
if (_services is EqualUnmodifiableListView) return _services;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_services);
}
@override final String? error;
/// Create a copy of AggregatedNodeStatus
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$AggregatedNodeStatusCopyWith<_AggregatedNodeStatus> get copyWith => __$AggregatedNodeStatusCopyWithImpl<_AggregatedNodeStatus>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$AggregatedNodeStatusToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AggregatedNodeStatus&&(identical(other.node, node) || other.node == node)&&const DeepCollectionEquality().equals(other._services, _services)&&(identical(other.error, error) || other.error == error));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,node,const DeepCollectionEquality().hash(_services),error);
@override
String toString() {
return 'AggregatedNodeStatus(node: $node, services: $services, error: $error)';
}
}
/// @nodoc
abstract mixin class _$AggregatedNodeStatusCopyWith<$Res> implements $AggregatedNodeStatusCopyWith<$Res> {
factory _$AggregatedNodeStatusCopyWith(_AggregatedNodeStatus value, $Res Function(_AggregatedNodeStatus) _then) = __$AggregatedNodeStatusCopyWithImpl;
@override @useResult
$Res call({
RemoteNode node, List<Service> services, String? error
});
@override $RemoteNodeCopyWith<$Res> get node;
}
/// @nodoc
class __$AggregatedNodeStatusCopyWithImpl<$Res>
implements _$AggregatedNodeStatusCopyWith<$Res> {
__$AggregatedNodeStatusCopyWithImpl(this._self, this._then);
final _AggregatedNodeStatus _self;
final $Res Function(_AggregatedNodeStatus) _then;
/// Create a copy of AggregatedNodeStatus
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? node = null,Object? services = null,Object? error = freezed,}) {
return _then(_AggregatedNodeStatus(
node: null == node ? _self.node : node // ignore: cast_nullable_to_non_nullable
as RemoteNode,services: null == services ? _self._services : services // ignore: cast_nullable_to_non_nullable
as List<Service>,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
as String?,
));
}
/// Create a copy of AggregatedNodeStatus
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$RemoteNodeCopyWith<$Res> get node {
return $RemoteNodeCopyWith<$Res>(_self.node, (value) {
return _then(_self.copyWith(node: value));
});
}
}
// dart format on
@@ -0,0 +1,27 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'aggregated_node_status.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_AggregatedNodeStatus _$AggregatedNodeStatusFromJson(
Map<String, dynamic> json,
) => _AggregatedNodeStatus(
node: RemoteNode.fromJson(json['node'] as Map<String, dynamic>),
services:
(json['services'] as List<dynamic>?)
?.map((e) => Service.fromJson(e as Map<String, dynamic>))
.toList() ??
const <Service>[],
error: json['error'] as String?,
);
Map<String, dynamic> _$AggregatedNodeStatusToJson(
_AggregatedNodeStatus instance,
) => <String, dynamic>{
'node': instance.node.toJson(),
'services': instance.services.map((e) => e.toJson()).toList(),
'error': instance.error,
};
+25
View File
@@ -0,0 +1,25 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'backup_execution.dart';
import 'backup_target.dart';
part 'backup_config.freezed.dart';
part 'backup_config.g.dart';
/// Mirrors `models.BackupConfig`. Used both at node level (`GET /node/backup`)
/// and per-service (`Service.backup`). `nextRun`/`lastRun` here are
/// aggregates (earliest/latest) across `targets` — each target now tracks
/// its own `schedule`/`lastRun`/`nextRun` too. There's no `frequency` field
/// on the Go side anymore; scheduling moved to a per-target cron `schedule`.
@freezed
sealed class BackupConfig with _$BackupConfig {
const factory BackupConfig({
@JsonKey(name: 'source_path') String? sourcePath,
@Default(<BackupTarget>[]) List<BackupTarget> targets,
@JsonKey(name: 'next_run') DateTime? nextRun,
@JsonKey(name: 'last_run') DateTime? lastRun,
@Default(<BackupExecution>[]) List<BackupExecution> history,
}) = _BackupConfig;
factory BackupConfig.fromJson(Map<String, dynamic> json) => _$BackupConfigFromJson(json);
}
+295
View File
@@ -0,0 +1,295 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'backup_config.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$BackupConfig {
@JsonKey(name: 'source_path') String? get sourcePath; List<BackupTarget> get targets;@JsonKey(name: 'next_run') DateTime? get nextRun;@JsonKey(name: 'last_run') DateTime? get lastRun; List<BackupExecution> get history;
/// Create a copy of BackupConfig
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$BackupConfigCopyWith<BackupConfig> get copyWith => _$BackupConfigCopyWithImpl<BackupConfig>(this as BackupConfig, _$identity);
/// Serializes this BackupConfig to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is BackupConfig&&(identical(other.sourcePath, sourcePath) || other.sourcePath == sourcePath)&&const DeepCollectionEquality().equals(other.targets, targets)&&(identical(other.nextRun, nextRun) || other.nextRun == nextRun)&&(identical(other.lastRun, lastRun) || other.lastRun == lastRun)&&const DeepCollectionEquality().equals(other.history, history));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,sourcePath,const DeepCollectionEquality().hash(targets),nextRun,lastRun,const DeepCollectionEquality().hash(history));
@override
String toString() {
return 'BackupConfig(sourcePath: $sourcePath, targets: $targets, nextRun: $nextRun, lastRun: $lastRun, history: $history)';
}
}
/// @nodoc
abstract mixin class $BackupConfigCopyWith<$Res> {
factory $BackupConfigCopyWith(BackupConfig value, $Res Function(BackupConfig) _then) = _$BackupConfigCopyWithImpl;
@useResult
$Res call({
@JsonKey(name: 'source_path') String? sourcePath, List<BackupTarget> targets,@JsonKey(name: 'next_run') DateTime? nextRun,@JsonKey(name: 'last_run') DateTime? lastRun, List<BackupExecution> history
});
}
/// @nodoc
class _$BackupConfigCopyWithImpl<$Res>
implements $BackupConfigCopyWith<$Res> {
_$BackupConfigCopyWithImpl(this._self, this._then);
final BackupConfig _self;
final $Res Function(BackupConfig) _then;
/// Create a copy of BackupConfig
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? sourcePath = freezed,Object? targets = null,Object? nextRun = freezed,Object? lastRun = freezed,Object? history = null,}) {
return _then(_self.copyWith(
sourcePath: freezed == sourcePath ? _self.sourcePath : sourcePath // ignore: cast_nullable_to_non_nullable
as String?,targets: null == targets ? _self.targets : targets // ignore: cast_nullable_to_non_nullable
as List<BackupTarget>,nextRun: freezed == nextRun ? _self.nextRun : nextRun // ignore: cast_nullable_to_non_nullable
as DateTime?,lastRun: freezed == lastRun ? _self.lastRun : lastRun // ignore: cast_nullable_to_non_nullable
as DateTime?,history: null == history ? _self.history : history // ignore: cast_nullable_to_non_nullable
as List<BackupExecution>,
));
}
}
/// Adds pattern-matching-related methods to [BackupConfig].
extension BackupConfigPatterns on BackupConfig {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _BackupConfig value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _BackupConfig() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _BackupConfig value) $default,){
final _that = this;
switch (_that) {
case _BackupConfig():
return $default(_that);}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _BackupConfig value)? $default,){
final _that = this;
switch (_that) {
case _BackupConfig() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function(@JsonKey(name: 'source_path') String? sourcePath, List<BackupTarget> targets, @JsonKey(name: 'next_run') DateTime? nextRun, @JsonKey(name: 'last_run') DateTime? lastRun, List<BackupExecution> history)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _BackupConfig() when $default != null:
return $default(_that.sourcePath,_that.targets,_that.nextRun,_that.lastRun,_that.history);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function(@JsonKey(name: 'source_path') String? sourcePath, List<BackupTarget> targets, @JsonKey(name: 'next_run') DateTime? nextRun, @JsonKey(name: 'last_run') DateTime? lastRun, List<BackupExecution> history) $default,) {final _that = this;
switch (_that) {
case _BackupConfig():
return $default(_that.sourcePath,_that.targets,_that.nextRun,_that.lastRun,_that.history);}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function(@JsonKey(name: 'source_path') String? sourcePath, List<BackupTarget> targets, @JsonKey(name: 'next_run') DateTime? nextRun, @JsonKey(name: 'last_run') DateTime? lastRun, List<BackupExecution> history)? $default,) {final _that = this;
switch (_that) {
case _BackupConfig() when $default != null:
return $default(_that.sourcePath,_that.targets,_that.nextRun,_that.lastRun,_that.history);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _BackupConfig implements BackupConfig {
const _BackupConfig({@JsonKey(name: 'source_path') this.sourcePath, final List<BackupTarget> targets = const <BackupTarget>[], @JsonKey(name: 'next_run') this.nextRun, @JsonKey(name: 'last_run') this.lastRun, final List<BackupExecution> history = const <BackupExecution>[]}): _targets = targets,_history = history;
factory _BackupConfig.fromJson(Map<String, dynamic> json) => _$BackupConfigFromJson(json);
@override@JsonKey(name: 'source_path') final String? sourcePath;
final List<BackupTarget> _targets;
@override@JsonKey() List<BackupTarget> get targets {
if (_targets is EqualUnmodifiableListView) return _targets;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_targets);
}
@override@JsonKey(name: 'next_run') final DateTime? nextRun;
@override@JsonKey(name: 'last_run') final DateTime? lastRun;
final List<BackupExecution> _history;
@override@JsonKey() List<BackupExecution> get history {
if (_history is EqualUnmodifiableListView) return _history;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_history);
}
/// Create a copy of BackupConfig
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$BackupConfigCopyWith<_BackupConfig> get copyWith => __$BackupConfigCopyWithImpl<_BackupConfig>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$BackupConfigToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _BackupConfig&&(identical(other.sourcePath, sourcePath) || other.sourcePath == sourcePath)&&const DeepCollectionEquality().equals(other._targets, _targets)&&(identical(other.nextRun, nextRun) || other.nextRun == nextRun)&&(identical(other.lastRun, lastRun) || other.lastRun == lastRun)&&const DeepCollectionEquality().equals(other._history, _history));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,sourcePath,const DeepCollectionEquality().hash(_targets),nextRun,lastRun,const DeepCollectionEquality().hash(_history));
@override
String toString() {
return 'BackupConfig(sourcePath: $sourcePath, targets: $targets, nextRun: $nextRun, lastRun: $lastRun, history: $history)';
}
}
/// @nodoc
abstract mixin class _$BackupConfigCopyWith<$Res> implements $BackupConfigCopyWith<$Res> {
factory _$BackupConfigCopyWith(_BackupConfig value, $Res Function(_BackupConfig) _then) = __$BackupConfigCopyWithImpl;
@override @useResult
$Res call({
@JsonKey(name: 'source_path') String? sourcePath, List<BackupTarget> targets,@JsonKey(name: 'next_run') DateTime? nextRun,@JsonKey(name: 'last_run') DateTime? lastRun, List<BackupExecution> history
});
}
/// @nodoc
class __$BackupConfigCopyWithImpl<$Res>
implements _$BackupConfigCopyWith<$Res> {
__$BackupConfigCopyWithImpl(this._self, this._then);
final _BackupConfig _self;
final $Res Function(_BackupConfig) _then;
/// Create a copy of BackupConfig
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? sourcePath = freezed,Object? targets = null,Object? nextRun = freezed,Object? lastRun = freezed,Object? history = null,}) {
return _then(_BackupConfig(
sourcePath: freezed == sourcePath ? _self.sourcePath : sourcePath // ignore: cast_nullable_to_non_nullable
as String?,targets: null == targets ? _self._targets : targets // ignore: cast_nullable_to_non_nullable
as List<BackupTarget>,nextRun: freezed == nextRun ? _self.nextRun : nextRun // ignore: cast_nullable_to_non_nullable
as DateTime?,lastRun: freezed == lastRun ? _self.lastRun : lastRun // ignore: cast_nullable_to_non_nullable
as DateTime?,history: null == history ? _self._history : history // ignore: cast_nullable_to_non_nullable
as List<BackupExecution>,
));
}
}
// dart format on
+37
View File
@@ -0,0 +1,37 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'backup_config.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_BackupConfig _$BackupConfigFromJson(Map<String, dynamic> json) =>
_BackupConfig(
sourcePath: json['source_path'] as String?,
targets:
(json['targets'] as List<dynamic>?)
?.map((e) => BackupTarget.fromJson(e as Map<String, dynamic>))
.toList() ??
const <BackupTarget>[],
nextRun: json['next_run'] == null
? null
: DateTime.parse(json['next_run'] as String),
lastRun: json['last_run'] == null
? null
: DateTime.parse(json['last_run'] as String),
history:
(json['history'] as List<dynamic>?)
?.map((e) => BackupExecution.fromJson(e as Map<String, dynamic>))
.toList() ??
const <BackupExecution>[],
);
Map<String, dynamic> _$BackupConfigToJson(_BackupConfig instance) =>
<String, dynamic>{
'source_path': instance.sourcePath,
'targets': instance.targets.map((e) => e.toJson()).toList(),
'next_run': instance.nextRun?.toIso8601String(),
'last_run': instance.lastRun?.toIso8601String(),
'history': instance.history.map((e) => e.toJson()).toList(),
};
+19
View File
@@ -0,0 +1,19 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'backup_execution.freezed.dart';
part 'backup_execution.g.dart';
/// Mirrors `models.BackupExecution`.
@freezed
sealed class BackupExecution with _$BackupExecution {
const factory BackupExecution({
required String id,
required DateTime timestamp,
required bool success,
@JsonKey(name: 'duration_seconds') required int durationSeconds,
@Default('') String message,
@JsonKey(name: 'target_id') String? targetId,
}) = _BackupExecution;
factory BackupExecution.fromJson(Map<String, dynamic> json) => _$BackupExecutionFromJson(json);
}
@@ -0,0 +1,286 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'backup_execution.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$BackupExecution {
String get id; DateTime get timestamp; bool get success;@JsonKey(name: 'duration_seconds') int get durationSeconds; String get message;@JsonKey(name: 'target_id') String? get targetId;
/// Create a copy of BackupExecution
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$BackupExecutionCopyWith<BackupExecution> get copyWith => _$BackupExecutionCopyWithImpl<BackupExecution>(this as BackupExecution, _$identity);
/// Serializes this BackupExecution to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is BackupExecution&&(identical(other.id, id) || other.id == id)&&(identical(other.timestamp, timestamp) || other.timestamp == timestamp)&&(identical(other.success, success) || other.success == success)&&(identical(other.durationSeconds, durationSeconds) || other.durationSeconds == durationSeconds)&&(identical(other.message, message) || other.message == message)&&(identical(other.targetId, targetId) || other.targetId == targetId));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,timestamp,success,durationSeconds,message,targetId);
@override
String toString() {
return 'BackupExecution(id: $id, timestamp: $timestamp, success: $success, durationSeconds: $durationSeconds, message: $message, targetId: $targetId)';
}
}
/// @nodoc
abstract mixin class $BackupExecutionCopyWith<$Res> {
factory $BackupExecutionCopyWith(BackupExecution value, $Res Function(BackupExecution) _then) = _$BackupExecutionCopyWithImpl;
@useResult
$Res call({
String id, DateTime timestamp, bool success,@JsonKey(name: 'duration_seconds') int durationSeconds, String message,@JsonKey(name: 'target_id') String? targetId
});
}
/// @nodoc
class _$BackupExecutionCopyWithImpl<$Res>
implements $BackupExecutionCopyWith<$Res> {
_$BackupExecutionCopyWithImpl(this._self, this._then);
final BackupExecution _self;
final $Res Function(BackupExecution) _then;
/// Create a copy of BackupExecution
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? timestamp = null,Object? success = null,Object? durationSeconds = null,Object? message = null,Object? targetId = freezed,}) {
return _then(_self.copyWith(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,timestamp: null == timestamp ? _self.timestamp : timestamp // ignore: cast_nullable_to_non_nullable
as DateTime,success: null == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
as bool,durationSeconds: null == durationSeconds ? _self.durationSeconds : durationSeconds // ignore: cast_nullable_to_non_nullable
as int,message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
as String,targetId: freezed == targetId ? _self.targetId : targetId // ignore: cast_nullable_to_non_nullable
as String?,
));
}
}
/// Adds pattern-matching-related methods to [BackupExecution].
extension BackupExecutionPatterns on BackupExecution {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _BackupExecution value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _BackupExecution() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _BackupExecution value) $default,){
final _that = this;
switch (_that) {
case _BackupExecution():
return $default(_that);}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _BackupExecution value)? $default,){
final _that = this;
switch (_that) {
case _BackupExecution() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, DateTime timestamp, bool success, @JsonKey(name: 'duration_seconds') int durationSeconds, String message, @JsonKey(name: 'target_id') String? targetId)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _BackupExecution() when $default != null:
return $default(_that.id,_that.timestamp,_that.success,_that.durationSeconds,_that.message,_that.targetId);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, DateTime timestamp, bool success, @JsonKey(name: 'duration_seconds') int durationSeconds, String message, @JsonKey(name: 'target_id') String? targetId) $default,) {final _that = this;
switch (_that) {
case _BackupExecution():
return $default(_that.id,_that.timestamp,_that.success,_that.durationSeconds,_that.message,_that.targetId);}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, DateTime timestamp, bool success, @JsonKey(name: 'duration_seconds') int durationSeconds, String message, @JsonKey(name: 'target_id') String? targetId)? $default,) {final _that = this;
switch (_that) {
case _BackupExecution() when $default != null:
return $default(_that.id,_that.timestamp,_that.success,_that.durationSeconds,_that.message,_that.targetId);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _BackupExecution implements BackupExecution {
const _BackupExecution({required this.id, required this.timestamp, required this.success, @JsonKey(name: 'duration_seconds') required this.durationSeconds, this.message = '', @JsonKey(name: 'target_id') this.targetId});
factory _BackupExecution.fromJson(Map<String, dynamic> json) => _$BackupExecutionFromJson(json);
@override final String id;
@override final DateTime timestamp;
@override final bool success;
@override@JsonKey(name: 'duration_seconds') final int durationSeconds;
@override@JsonKey() final String message;
@override@JsonKey(name: 'target_id') final String? targetId;
/// Create a copy of BackupExecution
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$BackupExecutionCopyWith<_BackupExecution> get copyWith => __$BackupExecutionCopyWithImpl<_BackupExecution>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$BackupExecutionToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _BackupExecution&&(identical(other.id, id) || other.id == id)&&(identical(other.timestamp, timestamp) || other.timestamp == timestamp)&&(identical(other.success, success) || other.success == success)&&(identical(other.durationSeconds, durationSeconds) || other.durationSeconds == durationSeconds)&&(identical(other.message, message) || other.message == message)&&(identical(other.targetId, targetId) || other.targetId == targetId));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,timestamp,success,durationSeconds,message,targetId);
@override
String toString() {
return 'BackupExecution(id: $id, timestamp: $timestamp, success: $success, durationSeconds: $durationSeconds, message: $message, targetId: $targetId)';
}
}
/// @nodoc
abstract mixin class _$BackupExecutionCopyWith<$Res> implements $BackupExecutionCopyWith<$Res> {
factory _$BackupExecutionCopyWith(_BackupExecution value, $Res Function(_BackupExecution) _then) = __$BackupExecutionCopyWithImpl;
@override @useResult
$Res call({
String id, DateTime timestamp, bool success,@JsonKey(name: 'duration_seconds') int durationSeconds, String message,@JsonKey(name: 'target_id') String? targetId
});
}
/// @nodoc
class __$BackupExecutionCopyWithImpl<$Res>
implements _$BackupExecutionCopyWith<$Res> {
__$BackupExecutionCopyWithImpl(this._self, this._then);
final _BackupExecution _self;
final $Res Function(_BackupExecution) _then;
/// Create a copy of BackupExecution
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? timestamp = null,Object? success = null,Object? durationSeconds = null,Object? message = null,Object? targetId = freezed,}) {
return _then(_BackupExecution(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,timestamp: null == timestamp ? _self.timestamp : timestamp // ignore: cast_nullable_to_non_nullable
as DateTime,success: null == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
as bool,durationSeconds: null == durationSeconds ? _self.durationSeconds : durationSeconds // ignore: cast_nullable_to_non_nullable
as int,message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
as String,targetId: freezed == targetId ? _self.targetId : targetId // ignore: cast_nullable_to_non_nullable
as String?,
));
}
}
// dart format on
+27
View File
@@ -0,0 +1,27 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'backup_execution.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_BackupExecution _$BackupExecutionFromJson(Map<String, dynamic> json) =>
_BackupExecution(
id: json['id'] as String,
timestamp: DateTime.parse(json['timestamp'] as String),
success: json['success'] as bool,
durationSeconds: (json['duration_seconds'] as num).toInt(),
message: json['message'] as String? ?? '',
targetId: json['target_id'] as String?,
);
Map<String, dynamic> _$BackupExecutionToJson(_BackupExecution instance) =>
<String, dynamic>{
'id': instance.id,
'timestamp': instance.timestamp.toIso8601String(),
'success': instance.success,
'duration_seconds': instance.durationSeconds,
'message': instance.message,
'target_id': instance.targetId,
};
+11
View File
@@ -0,0 +1,11 @@
import 'package:json_annotation/json_annotation.dart';
/// Mirrors `models.BackupMethod` in `nodemaster/models/types.go`.
enum BackupMethod {
@JsonValue('rsync')
rsync,
@JsonValue('restic')
restic,
@JsonValue('external')
external,
}
+24
View File
@@ -0,0 +1,24 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'backup_method.dart';
part 'backup_target.freezed.dart';
part 'backup_target.g.dart';
/// Mirrors `models.BackupTarget`. `schedule` is a standard 5-field cron
/// expression; empty means manual-only (no automatic scheduling).
@freezed
sealed class BackupTarget with _$BackupTarget {
const factory BackupTarget({
@Default('') String id,
required String name,
required BackupMethod method,
required String remote,
@Default(<String, String>{}) Map<String, String> params,
String? schedule,
@JsonKey(name: 'last_run') DateTime? lastRun,
@JsonKey(name: 'next_run') DateTime? nextRun,
}) = _BackupTarget;
factory BackupTarget.fromJson(Map<String, dynamic> json) => _$BackupTargetFromJson(json);
}
+298
View File
@@ -0,0 +1,298 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'backup_target.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$BackupTarget {
String get id; String get name; BackupMethod get method; String get remote; Map<String, String> get params; String? get schedule;@JsonKey(name: 'last_run') DateTime? get lastRun;@JsonKey(name: 'next_run') DateTime? get nextRun;
/// Create a copy of BackupTarget
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$BackupTargetCopyWith<BackupTarget> get copyWith => _$BackupTargetCopyWithImpl<BackupTarget>(this as BackupTarget, _$identity);
/// Serializes this BackupTarget to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is BackupTarget&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.method, method) || other.method == method)&&(identical(other.remote, remote) || other.remote == remote)&&const DeepCollectionEquality().equals(other.params, params)&&(identical(other.schedule, schedule) || other.schedule == schedule)&&(identical(other.lastRun, lastRun) || other.lastRun == lastRun)&&(identical(other.nextRun, nextRun) || other.nextRun == nextRun));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,name,method,remote,const DeepCollectionEquality().hash(params),schedule,lastRun,nextRun);
@override
String toString() {
return 'BackupTarget(id: $id, name: $name, method: $method, remote: $remote, params: $params, schedule: $schedule, lastRun: $lastRun, nextRun: $nextRun)';
}
}
/// @nodoc
abstract mixin class $BackupTargetCopyWith<$Res> {
factory $BackupTargetCopyWith(BackupTarget value, $Res Function(BackupTarget) _then) = _$BackupTargetCopyWithImpl;
@useResult
$Res call({
String id, String name, BackupMethod method, String remote, Map<String, String> params, String? schedule,@JsonKey(name: 'last_run') DateTime? lastRun,@JsonKey(name: 'next_run') DateTime? nextRun
});
}
/// @nodoc
class _$BackupTargetCopyWithImpl<$Res>
implements $BackupTargetCopyWith<$Res> {
_$BackupTargetCopyWithImpl(this._self, this._then);
final BackupTarget _self;
final $Res Function(BackupTarget) _then;
/// Create a copy of BackupTarget
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? method = null,Object? remote = null,Object? params = null,Object? schedule = freezed,Object? lastRun = freezed,Object? nextRun = freezed,}) {
return _then(_self.copyWith(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
as String,method: null == method ? _self.method : method // ignore: cast_nullable_to_non_nullable
as BackupMethod,remote: null == remote ? _self.remote : remote // ignore: cast_nullable_to_non_nullable
as String,params: null == params ? _self.params : params // ignore: cast_nullable_to_non_nullable
as Map<String, String>,schedule: freezed == schedule ? _self.schedule : schedule // ignore: cast_nullable_to_non_nullable
as String?,lastRun: freezed == lastRun ? _self.lastRun : lastRun // ignore: cast_nullable_to_non_nullable
as DateTime?,nextRun: freezed == nextRun ? _self.nextRun : nextRun // ignore: cast_nullable_to_non_nullable
as DateTime?,
));
}
}
/// Adds pattern-matching-related methods to [BackupTarget].
extension BackupTargetPatterns on BackupTarget {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _BackupTarget value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _BackupTarget() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _BackupTarget value) $default,){
final _that = this;
switch (_that) {
case _BackupTarget():
return $default(_that);}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _BackupTarget value)? $default,){
final _that = this;
switch (_that) {
case _BackupTarget() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String name, BackupMethod method, String remote, Map<String, String> params, String? schedule, @JsonKey(name: 'last_run') DateTime? lastRun, @JsonKey(name: 'next_run') DateTime? nextRun)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _BackupTarget() when $default != null:
return $default(_that.id,_that.name,_that.method,_that.remote,_that.params,_that.schedule,_that.lastRun,_that.nextRun);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String name, BackupMethod method, String remote, Map<String, String> params, String? schedule, @JsonKey(name: 'last_run') DateTime? lastRun, @JsonKey(name: 'next_run') DateTime? nextRun) $default,) {final _that = this;
switch (_that) {
case _BackupTarget():
return $default(_that.id,_that.name,_that.method,_that.remote,_that.params,_that.schedule,_that.lastRun,_that.nextRun);}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String name, BackupMethod method, String remote, Map<String, String> params, String? schedule, @JsonKey(name: 'last_run') DateTime? lastRun, @JsonKey(name: 'next_run') DateTime? nextRun)? $default,) {final _that = this;
switch (_that) {
case _BackupTarget() when $default != null:
return $default(_that.id,_that.name,_that.method,_that.remote,_that.params,_that.schedule,_that.lastRun,_that.nextRun);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _BackupTarget implements BackupTarget {
const _BackupTarget({this.id = '', required this.name, required this.method, required this.remote, final Map<String, String> params = const <String, String>{}, this.schedule, @JsonKey(name: 'last_run') this.lastRun, @JsonKey(name: 'next_run') this.nextRun}): _params = params;
factory _BackupTarget.fromJson(Map<String, dynamic> json) => _$BackupTargetFromJson(json);
@override@JsonKey() final String id;
@override final String name;
@override final BackupMethod method;
@override final String remote;
final Map<String, String> _params;
@override@JsonKey() Map<String, String> get params {
if (_params is EqualUnmodifiableMapView) return _params;
// ignore: implicit_dynamic_type
return EqualUnmodifiableMapView(_params);
}
@override final String? schedule;
@override@JsonKey(name: 'last_run') final DateTime? lastRun;
@override@JsonKey(name: 'next_run') final DateTime? nextRun;
/// Create a copy of BackupTarget
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$BackupTargetCopyWith<_BackupTarget> get copyWith => __$BackupTargetCopyWithImpl<_BackupTarget>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$BackupTargetToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _BackupTarget&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.method, method) || other.method == method)&&(identical(other.remote, remote) || other.remote == remote)&&const DeepCollectionEquality().equals(other._params, _params)&&(identical(other.schedule, schedule) || other.schedule == schedule)&&(identical(other.lastRun, lastRun) || other.lastRun == lastRun)&&(identical(other.nextRun, nextRun) || other.nextRun == nextRun));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,name,method,remote,const DeepCollectionEquality().hash(_params),schedule,lastRun,nextRun);
@override
String toString() {
return 'BackupTarget(id: $id, name: $name, method: $method, remote: $remote, params: $params, schedule: $schedule, lastRun: $lastRun, nextRun: $nextRun)';
}
}
/// @nodoc
abstract mixin class _$BackupTargetCopyWith<$Res> implements $BackupTargetCopyWith<$Res> {
factory _$BackupTargetCopyWith(_BackupTarget value, $Res Function(_BackupTarget) _then) = __$BackupTargetCopyWithImpl;
@override @useResult
$Res call({
String id, String name, BackupMethod method, String remote, Map<String, String> params, String? schedule,@JsonKey(name: 'last_run') DateTime? lastRun,@JsonKey(name: 'next_run') DateTime? nextRun
});
}
/// @nodoc
class __$BackupTargetCopyWithImpl<$Res>
implements _$BackupTargetCopyWith<$Res> {
__$BackupTargetCopyWithImpl(this._self, this._then);
final _BackupTarget _self;
final $Res Function(_BackupTarget) _then;
/// Create a copy of BackupTarget
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? method = null,Object? remote = null,Object? params = null,Object? schedule = freezed,Object? lastRun = freezed,Object? nextRun = freezed,}) {
return _then(_BackupTarget(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
as String,method: null == method ? _self.method : method // ignore: cast_nullable_to_non_nullable
as BackupMethod,remote: null == remote ? _self.remote : remote // ignore: cast_nullable_to_non_nullable
as String,params: null == params ? _self._params : params // ignore: cast_nullable_to_non_nullable
as Map<String, String>,schedule: freezed == schedule ? _self.schedule : schedule // ignore: cast_nullable_to_non_nullable
as String?,lastRun: freezed == lastRun ? _self.lastRun : lastRun // ignore: cast_nullable_to_non_nullable
as DateTime?,nextRun: freezed == nextRun ? _self.nextRun : nextRun // ignore: cast_nullable_to_non_nullable
as DateTime?,
));
}
}
// dart format on
+45
View File
@@ -0,0 +1,45 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'backup_target.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_BackupTarget _$BackupTargetFromJson(Map<String, dynamic> json) =>
_BackupTarget(
id: json['id'] as String? ?? '',
name: json['name'] as String,
method: $enumDecode(_$BackupMethodEnumMap, json['method']),
remote: json['remote'] as String,
params:
(json['params'] as Map<String, dynamic>?)?.map(
(k, e) => MapEntry(k, e as String),
) ??
const <String, String>{},
schedule: json['schedule'] as String?,
lastRun: json['last_run'] == null
? null
: DateTime.parse(json['last_run'] as String),
nextRun: json['next_run'] == null
? null
: DateTime.parse(json['next_run'] as String),
);
Map<String, dynamic> _$BackupTargetToJson(_BackupTarget instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
'method': _$BackupMethodEnumMap[instance.method]!,
'remote': instance.remote,
'params': instance.params,
'schedule': instance.schedule,
'last_run': instance.lastRun?.toIso8601String(),
'next_run': instance.nextRun?.toIso8601String(),
};
const _$BackupMethodEnumMap = {
BackupMethod.rsync: 'rsync',
BackupMethod.restic: 'restic',
BackupMethod.external: 'external',
};
+12
View File
@@ -0,0 +1,12 @@
export 'aggregated_node_status.dart';
export 'backup_config.dart';
export 'backup_execution.dart';
export 'backup_method.dart';
export 'backup_target.dart';
export 'node_info.dart';
export 'remote_node.dart';
export 'run_state.dart';
export 'scan_result.dart';
export 'service.dart';
export 'service_scan_info.dart';
export 'update_record.dart';
+30
View File
@@ -0,0 +1,30 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'backup_config.dart';
import 'update_record.dart';
part 'node_info.freezed.dart';
part 'node_info.g.dart';
/// Mirrors `models.NodeInfo` — the local/current host's identity + backup
/// config + update log, as served by `GET /node/`.
///
/// `resticPassword` is write-only: the API never echoes the real password
/// back (`GET /node/` sends `restic_password_set` instead, see
/// `controllers/node.go`), so this stays `null` unless the user is actively
/// setting/changing it in the identity form, and is omitted from the PUT
/// body entirely when `null` so an untouched form never clobbers the
/// existing password (mirrors the Go side's "empty string = don't change").
@freezed
sealed class NodeInfo with _$NodeInfo {
const factory NodeInfo({
required String hostname,
String? description,
@JsonKey(name: 'update_history') @Default(<UpdateRecord>[]) List<UpdateRecord> updateHistory,
required BackupConfig backup,
@JsonKey(name: 'restic_password_set') @Default(false) bool resticPasswordSet,
@JsonKey(name: 'restic_password', includeIfNull: false) String? resticPassword,
}) = _NodeInfo;
factory NodeInfo.fromJson(Map<String, dynamic> json) => _$NodeInfoFromJson(json);
}
+310
View File
@@ -0,0 +1,310 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'node_info.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$NodeInfo {
String get hostname; String? get description;@JsonKey(name: 'update_history') List<UpdateRecord> get updateHistory; BackupConfig get backup;@JsonKey(name: 'restic_password_set') bool get resticPasswordSet;@JsonKey(name: 'restic_password', includeIfNull: false) String? get resticPassword;
/// Create a copy of NodeInfo
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$NodeInfoCopyWith<NodeInfo> get copyWith => _$NodeInfoCopyWithImpl<NodeInfo>(this as NodeInfo, _$identity);
/// Serializes this NodeInfo to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is NodeInfo&&(identical(other.hostname, hostname) || other.hostname == hostname)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other.updateHistory, updateHistory)&&(identical(other.backup, backup) || other.backup == backup)&&(identical(other.resticPasswordSet, resticPasswordSet) || other.resticPasswordSet == resticPasswordSet)&&(identical(other.resticPassword, resticPassword) || other.resticPassword == resticPassword));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,hostname,description,const DeepCollectionEquality().hash(updateHistory),backup,resticPasswordSet,resticPassword);
@override
String toString() {
return 'NodeInfo(hostname: $hostname, description: $description, updateHistory: $updateHistory, backup: $backup, resticPasswordSet: $resticPasswordSet, resticPassword: $resticPassword)';
}
}
/// @nodoc
abstract mixin class $NodeInfoCopyWith<$Res> {
factory $NodeInfoCopyWith(NodeInfo value, $Res Function(NodeInfo) _then) = _$NodeInfoCopyWithImpl;
@useResult
$Res call({
String hostname, String? description,@JsonKey(name: 'update_history') List<UpdateRecord> updateHistory, BackupConfig backup,@JsonKey(name: 'restic_password_set') bool resticPasswordSet,@JsonKey(name: 'restic_password', includeIfNull: false) String? resticPassword
});
$BackupConfigCopyWith<$Res> get backup;
}
/// @nodoc
class _$NodeInfoCopyWithImpl<$Res>
implements $NodeInfoCopyWith<$Res> {
_$NodeInfoCopyWithImpl(this._self, this._then);
final NodeInfo _self;
final $Res Function(NodeInfo) _then;
/// Create a copy of NodeInfo
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? hostname = null,Object? description = freezed,Object? updateHistory = null,Object? backup = null,Object? resticPasswordSet = null,Object? resticPassword = freezed,}) {
return _then(_self.copyWith(
hostname: null == hostname ? _self.hostname : hostname // ignore: cast_nullable_to_non_nullable
as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
as String?,updateHistory: null == updateHistory ? _self.updateHistory : updateHistory // ignore: cast_nullable_to_non_nullable
as List<UpdateRecord>,backup: null == backup ? _self.backup : backup // ignore: cast_nullable_to_non_nullable
as BackupConfig,resticPasswordSet: null == resticPasswordSet ? _self.resticPasswordSet : resticPasswordSet // ignore: cast_nullable_to_non_nullable
as bool,resticPassword: freezed == resticPassword ? _self.resticPassword : resticPassword // ignore: cast_nullable_to_non_nullable
as String?,
));
}
/// Create a copy of NodeInfo
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$BackupConfigCopyWith<$Res> get backup {
return $BackupConfigCopyWith<$Res>(_self.backup, (value) {
return _then(_self.copyWith(backup: value));
});
}
}
/// Adds pattern-matching-related methods to [NodeInfo].
extension NodeInfoPatterns on NodeInfo {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _NodeInfo value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _NodeInfo() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _NodeInfo value) $default,){
final _that = this;
switch (_that) {
case _NodeInfo():
return $default(_that);}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _NodeInfo value)? $default,){
final _that = this;
switch (_that) {
case _NodeInfo() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String hostname, String? description, @JsonKey(name: 'update_history') List<UpdateRecord> updateHistory, BackupConfig backup, @JsonKey(name: 'restic_password_set') bool resticPasswordSet, @JsonKey(name: 'restic_password', includeIfNull: false) String? resticPassword)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _NodeInfo() when $default != null:
return $default(_that.hostname,_that.description,_that.updateHistory,_that.backup,_that.resticPasswordSet,_that.resticPassword);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String hostname, String? description, @JsonKey(name: 'update_history') List<UpdateRecord> updateHistory, BackupConfig backup, @JsonKey(name: 'restic_password_set') bool resticPasswordSet, @JsonKey(name: 'restic_password', includeIfNull: false) String? resticPassword) $default,) {final _that = this;
switch (_that) {
case _NodeInfo():
return $default(_that.hostname,_that.description,_that.updateHistory,_that.backup,_that.resticPasswordSet,_that.resticPassword);}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String hostname, String? description, @JsonKey(name: 'update_history') List<UpdateRecord> updateHistory, BackupConfig backup, @JsonKey(name: 'restic_password_set') bool resticPasswordSet, @JsonKey(name: 'restic_password', includeIfNull: false) String? resticPassword)? $default,) {final _that = this;
switch (_that) {
case _NodeInfo() when $default != null:
return $default(_that.hostname,_that.description,_that.updateHistory,_that.backup,_that.resticPasswordSet,_that.resticPassword);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _NodeInfo implements NodeInfo {
const _NodeInfo({required this.hostname, this.description, @JsonKey(name: 'update_history') final List<UpdateRecord> updateHistory = const <UpdateRecord>[], required this.backup, @JsonKey(name: 'restic_password_set') this.resticPasswordSet = false, @JsonKey(name: 'restic_password', includeIfNull: false) this.resticPassword}): _updateHistory = updateHistory;
factory _NodeInfo.fromJson(Map<String, dynamic> json) => _$NodeInfoFromJson(json);
@override final String hostname;
@override final String? description;
final List<UpdateRecord> _updateHistory;
@override@JsonKey(name: 'update_history') List<UpdateRecord> get updateHistory {
if (_updateHistory is EqualUnmodifiableListView) return _updateHistory;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_updateHistory);
}
@override final BackupConfig backup;
@override@JsonKey(name: 'restic_password_set') final bool resticPasswordSet;
@override@JsonKey(name: 'restic_password', includeIfNull: false) final String? resticPassword;
/// Create a copy of NodeInfo
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$NodeInfoCopyWith<_NodeInfo> get copyWith => __$NodeInfoCopyWithImpl<_NodeInfo>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$NodeInfoToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _NodeInfo&&(identical(other.hostname, hostname) || other.hostname == hostname)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other._updateHistory, _updateHistory)&&(identical(other.backup, backup) || other.backup == backup)&&(identical(other.resticPasswordSet, resticPasswordSet) || other.resticPasswordSet == resticPasswordSet)&&(identical(other.resticPassword, resticPassword) || other.resticPassword == resticPassword));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,hostname,description,const DeepCollectionEquality().hash(_updateHistory),backup,resticPasswordSet,resticPassword);
@override
String toString() {
return 'NodeInfo(hostname: $hostname, description: $description, updateHistory: $updateHistory, backup: $backup, resticPasswordSet: $resticPasswordSet, resticPassword: $resticPassword)';
}
}
/// @nodoc
abstract mixin class _$NodeInfoCopyWith<$Res> implements $NodeInfoCopyWith<$Res> {
factory _$NodeInfoCopyWith(_NodeInfo value, $Res Function(_NodeInfo) _then) = __$NodeInfoCopyWithImpl;
@override @useResult
$Res call({
String hostname, String? description,@JsonKey(name: 'update_history') List<UpdateRecord> updateHistory, BackupConfig backup,@JsonKey(name: 'restic_password_set') bool resticPasswordSet,@JsonKey(name: 'restic_password', includeIfNull: false) String? resticPassword
});
@override $BackupConfigCopyWith<$Res> get backup;
}
/// @nodoc
class __$NodeInfoCopyWithImpl<$Res>
implements _$NodeInfoCopyWith<$Res> {
__$NodeInfoCopyWithImpl(this._self, this._then);
final _NodeInfo _self;
final $Res Function(_NodeInfo) _then;
/// Create a copy of NodeInfo
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? hostname = null,Object? description = freezed,Object? updateHistory = null,Object? backup = null,Object? resticPasswordSet = null,Object? resticPassword = freezed,}) {
return _then(_NodeInfo(
hostname: null == hostname ? _self.hostname : hostname // ignore: cast_nullable_to_non_nullable
as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
as String?,updateHistory: null == updateHistory ? _self._updateHistory : updateHistory // ignore: cast_nullable_to_non_nullable
as List<UpdateRecord>,backup: null == backup ? _self.backup : backup // ignore: cast_nullable_to_non_nullable
as BackupConfig,resticPasswordSet: null == resticPasswordSet ? _self.resticPasswordSet : resticPasswordSet // ignore: cast_nullable_to_non_nullable
as bool,resticPassword: freezed == resticPassword ? _self.resticPassword : resticPassword // ignore: cast_nullable_to_non_nullable
as String?,
));
}
/// Create a copy of NodeInfo
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$BackupConfigCopyWith<$Res> get backup {
return $BackupConfigCopyWith<$Res>(_self.backup, (value) {
return _then(_self.copyWith(backup: value));
});
}
}
// dart format on
+29
View File
@@ -0,0 +1,29 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'node_info.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_NodeInfo _$NodeInfoFromJson(Map<String, dynamic> json) => _NodeInfo(
hostname: json['hostname'] as String,
description: json['description'] as String?,
updateHistory:
(json['update_history'] as List<dynamic>?)
?.map((e) => UpdateRecord.fromJson(e as Map<String, dynamic>))
.toList() ??
const <UpdateRecord>[],
backup: BackupConfig.fromJson(json['backup'] as Map<String, dynamic>),
resticPasswordSet: json['restic_password_set'] as bool? ?? false,
resticPassword: json['restic_password'] as String?,
);
Map<String, dynamic> _$NodeInfoToJson(_NodeInfo instance) => <String, dynamic>{
'hostname': instance.hostname,
'description': instance.description,
'update_history': instance.updateHistory.map((e) => e.toJson()).toList(),
'backup': instance.backup.toJson(),
'restic_password_set': instance.resticPasswordSet,
'restic_password': ?instance.resticPassword,
};
+21
View File
@@ -0,0 +1,21 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'remote_node.freezed.dart';
part 'remote_node.g.dart';
/// Mirrors `models.RemoteNode` — an entry in this node's registry of
/// sibling NodeMaster hosts (`/nodes/*`).
@freezed
sealed class RemoteNode with _$RemoteNode {
const factory RemoteNode({
@Default('') String id,
required String name,
required String url,
@Default('') String status,
String? description,
@Default(<String>[]) List<String> tags,
@JsonKey(name: 'last_seen') DateTime? lastSeen,
}) = _RemoteNode;
factory RemoteNode.fromJson(Map<String, dynamic> json) => _$RemoteNodeFromJson(json);
}
+295
View File
@@ -0,0 +1,295 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'remote_node.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$RemoteNode {
String get id; String get name; String get url; String get status; String? get description; List<String> get tags;@JsonKey(name: 'last_seen') DateTime? get lastSeen;
/// Create a copy of RemoteNode
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$RemoteNodeCopyWith<RemoteNode> get copyWith => _$RemoteNodeCopyWithImpl<RemoteNode>(this as RemoteNode, _$identity);
/// Serializes this RemoteNode to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is RemoteNode&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.url, url) || other.url == url)&&(identical(other.status, status) || other.status == status)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other.tags, tags)&&(identical(other.lastSeen, lastSeen) || other.lastSeen == lastSeen));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,name,url,status,description,const DeepCollectionEquality().hash(tags),lastSeen);
@override
String toString() {
return 'RemoteNode(id: $id, name: $name, url: $url, status: $status, description: $description, tags: $tags, lastSeen: $lastSeen)';
}
}
/// @nodoc
abstract mixin class $RemoteNodeCopyWith<$Res> {
factory $RemoteNodeCopyWith(RemoteNode value, $Res Function(RemoteNode) _then) = _$RemoteNodeCopyWithImpl;
@useResult
$Res call({
String id, String name, String url, String status, String? description, List<String> tags,@JsonKey(name: 'last_seen') DateTime? lastSeen
});
}
/// @nodoc
class _$RemoteNodeCopyWithImpl<$Res>
implements $RemoteNodeCopyWith<$Res> {
_$RemoteNodeCopyWithImpl(this._self, this._then);
final RemoteNode _self;
final $Res Function(RemoteNode) _then;
/// Create a copy of RemoteNode
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? url = null,Object? status = null,Object? description = freezed,Object? tags = null,Object? lastSeen = freezed,}) {
return _then(_self.copyWith(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable
as String,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
as String?,tags: null == tags ? _self.tags : tags // ignore: cast_nullable_to_non_nullable
as List<String>,lastSeen: freezed == lastSeen ? _self.lastSeen : lastSeen // ignore: cast_nullable_to_non_nullable
as DateTime?,
));
}
}
/// Adds pattern-matching-related methods to [RemoteNode].
extension RemoteNodePatterns on RemoteNode {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _RemoteNode value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _RemoteNode() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _RemoteNode value) $default,){
final _that = this;
switch (_that) {
case _RemoteNode():
return $default(_that);}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _RemoteNode value)? $default,){
final _that = this;
switch (_that) {
case _RemoteNode() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String name, String url, String status, String? description, List<String> tags, @JsonKey(name: 'last_seen') DateTime? lastSeen)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _RemoteNode() when $default != null:
return $default(_that.id,_that.name,_that.url,_that.status,_that.description,_that.tags,_that.lastSeen);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String name, String url, String status, String? description, List<String> tags, @JsonKey(name: 'last_seen') DateTime? lastSeen) $default,) {final _that = this;
switch (_that) {
case _RemoteNode():
return $default(_that.id,_that.name,_that.url,_that.status,_that.description,_that.tags,_that.lastSeen);}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String name, String url, String status, String? description, List<String> tags, @JsonKey(name: 'last_seen') DateTime? lastSeen)? $default,) {final _that = this;
switch (_that) {
case _RemoteNode() when $default != null:
return $default(_that.id,_that.name,_that.url,_that.status,_that.description,_that.tags,_that.lastSeen);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _RemoteNode implements RemoteNode {
const _RemoteNode({this.id = '', required this.name, required this.url, this.status = '', this.description, final List<String> tags = const <String>[], @JsonKey(name: 'last_seen') this.lastSeen}): _tags = tags;
factory _RemoteNode.fromJson(Map<String, dynamic> json) => _$RemoteNodeFromJson(json);
@override@JsonKey() final String id;
@override final String name;
@override final String url;
@override@JsonKey() final String status;
@override final String? description;
final List<String> _tags;
@override@JsonKey() List<String> get tags {
if (_tags is EqualUnmodifiableListView) return _tags;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_tags);
}
@override@JsonKey(name: 'last_seen') final DateTime? lastSeen;
/// Create a copy of RemoteNode
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$RemoteNodeCopyWith<_RemoteNode> get copyWith => __$RemoteNodeCopyWithImpl<_RemoteNode>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$RemoteNodeToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _RemoteNode&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.url, url) || other.url == url)&&(identical(other.status, status) || other.status == status)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other._tags, _tags)&&(identical(other.lastSeen, lastSeen) || other.lastSeen == lastSeen));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,name,url,status,description,const DeepCollectionEquality().hash(_tags),lastSeen);
@override
String toString() {
return 'RemoteNode(id: $id, name: $name, url: $url, status: $status, description: $description, tags: $tags, lastSeen: $lastSeen)';
}
}
/// @nodoc
abstract mixin class _$RemoteNodeCopyWith<$Res> implements $RemoteNodeCopyWith<$Res> {
factory _$RemoteNodeCopyWith(_RemoteNode value, $Res Function(_RemoteNode) _then) = __$RemoteNodeCopyWithImpl;
@override @useResult
$Res call({
String id, String name, String url, String status, String? description, List<String> tags,@JsonKey(name: 'last_seen') DateTime? lastSeen
});
}
/// @nodoc
class __$RemoteNodeCopyWithImpl<$Res>
implements _$RemoteNodeCopyWith<$Res> {
__$RemoteNodeCopyWithImpl(this._self, this._then);
final _RemoteNode _self;
final $Res Function(_RemoteNode) _then;
/// Create a copy of RemoteNode
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? url = null,Object? status = null,Object? description = freezed,Object? tags = null,Object? lastSeen = freezed,}) {
return _then(_RemoteNode(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable
as String,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
as String?,tags: null == tags ? _self._tags : tags // ignore: cast_nullable_to_non_nullable
as List<String>,lastSeen: freezed == lastSeen ? _self.lastSeen : lastSeen // ignore: cast_nullable_to_non_nullable
as DateTime?,
));
}
}
// dart format on
+32
View File
@@ -0,0 +1,32 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'remote_node.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_RemoteNode _$RemoteNodeFromJson(Map<String, dynamic> json) => _RemoteNode(
id: json['id'] as String? ?? '',
name: json['name'] as String,
url: json['url'] as String,
status: json['status'] as String? ?? '',
description: json['description'] as String?,
tags:
(json['tags'] as List<dynamic>?)?.map((e) => e as String).toList() ??
const <String>[],
lastSeen: json['last_seen'] == null
? null
: DateTime.parse(json['last_seen'] as String),
);
Map<String, dynamic> _$RemoteNodeToJson(_RemoteNode instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
'url': instance.url,
'status': instance.status,
'description': instance.description,
'tags': instance.tags,
'last_seen': instance.lastSeen?.toIso8601String(),
};
+24
View File
@@ -0,0 +1,24 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'backup_method.dart';
part 'run_state.freezed.dart';
part 'run_state.g.dart';
/// Mirrors `models.RunState` — the live (in-memory, non-persisted) progress
/// of a single backup target's current or most recent run. Polled from
/// `GET /.../backup/targets/:tid/progress` while a run is in flight.
@freezed
sealed class RunState with _$RunState {
const factory RunState({
@Default(false) bool running,
@JsonKey(name: 'target_id') @Default('') String targetId,
BackupMethod? method,
@Default(0) double percent,
String? eta,
String? message,
@JsonKey(name: 'started_at') DateTime? startedAt,
}) = _RunState;
factory RunState.fromJson(Map<String, dynamic> json) => _$RunStateFromJson(json);
}
+289
View File
@@ -0,0 +1,289 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'run_state.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$RunState {
bool get running;@JsonKey(name: 'target_id') String get targetId; BackupMethod? get method; double get percent; String? get eta; String? get message;@JsonKey(name: 'started_at') DateTime? get startedAt;
/// Create a copy of RunState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$RunStateCopyWith<RunState> get copyWith => _$RunStateCopyWithImpl<RunState>(this as RunState, _$identity);
/// Serializes this RunState to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is RunState&&(identical(other.running, running) || other.running == running)&&(identical(other.targetId, targetId) || other.targetId == targetId)&&(identical(other.method, method) || other.method == method)&&(identical(other.percent, percent) || other.percent == percent)&&(identical(other.eta, eta) || other.eta == eta)&&(identical(other.message, message) || other.message == message)&&(identical(other.startedAt, startedAt) || other.startedAt == startedAt));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,running,targetId,method,percent,eta,message,startedAt);
@override
String toString() {
return 'RunState(running: $running, targetId: $targetId, method: $method, percent: $percent, eta: $eta, message: $message, startedAt: $startedAt)';
}
}
/// @nodoc
abstract mixin class $RunStateCopyWith<$Res> {
factory $RunStateCopyWith(RunState value, $Res Function(RunState) _then) = _$RunStateCopyWithImpl;
@useResult
$Res call({
bool running,@JsonKey(name: 'target_id') String targetId, BackupMethod? method, double percent, String? eta, String? message,@JsonKey(name: 'started_at') DateTime? startedAt
});
}
/// @nodoc
class _$RunStateCopyWithImpl<$Res>
implements $RunStateCopyWith<$Res> {
_$RunStateCopyWithImpl(this._self, this._then);
final RunState _self;
final $Res Function(RunState) _then;
/// Create a copy of RunState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? running = null,Object? targetId = null,Object? method = freezed,Object? percent = null,Object? eta = freezed,Object? message = freezed,Object? startedAt = freezed,}) {
return _then(_self.copyWith(
running: null == running ? _self.running : running // ignore: cast_nullable_to_non_nullable
as bool,targetId: null == targetId ? _self.targetId : targetId // ignore: cast_nullable_to_non_nullable
as String,method: freezed == method ? _self.method : method // ignore: cast_nullable_to_non_nullable
as BackupMethod?,percent: null == percent ? _self.percent : percent // ignore: cast_nullable_to_non_nullable
as double,eta: freezed == eta ? _self.eta : eta // ignore: cast_nullable_to_non_nullable
as String?,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
as String?,startedAt: freezed == startedAt ? _self.startedAt : startedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,
));
}
}
/// Adds pattern-matching-related methods to [RunState].
extension RunStatePatterns on RunState {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _RunState value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _RunState() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _RunState value) $default,){
final _that = this;
switch (_that) {
case _RunState():
return $default(_that);}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _RunState value)? $default,){
final _that = this;
switch (_that) {
case _RunState() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool running, @JsonKey(name: 'target_id') String targetId, BackupMethod? method, double percent, String? eta, String? message, @JsonKey(name: 'started_at') DateTime? startedAt)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _RunState() when $default != null:
return $default(_that.running,_that.targetId,_that.method,_that.percent,_that.eta,_that.message,_that.startedAt);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool running, @JsonKey(name: 'target_id') String targetId, BackupMethod? method, double percent, String? eta, String? message, @JsonKey(name: 'started_at') DateTime? startedAt) $default,) {final _that = this;
switch (_that) {
case _RunState():
return $default(_that.running,_that.targetId,_that.method,_that.percent,_that.eta,_that.message,_that.startedAt);}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool running, @JsonKey(name: 'target_id') String targetId, BackupMethod? method, double percent, String? eta, String? message, @JsonKey(name: 'started_at') DateTime? startedAt)? $default,) {final _that = this;
switch (_that) {
case _RunState() when $default != null:
return $default(_that.running,_that.targetId,_that.method,_that.percent,_that.eta,_that.message,_that.startedAt);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _RunState implements RunState {
const _RunState({this.running = false, @JsonKey(name: 'target_id') this.targetId = '', this.method, this.percent = 0, this.eta, this.message, @JsonKey(name: 'started_at') this.startedAt});
factory _RunState.fromJson(Map<String, dynamic> json) => _$RunStateFromJson(json);
@override@JsonKey() final bool running;
@override@JsonKey(name: 'target_id') final String targetId;
@override final BackupMethod? method;
@override@JsonKey() final double percent;
@override final String? eta;
@override final String? message;
@override@JsonKey(name: 'started_at') final DateTime? startedAt;
/// Create a copy of RunState
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$RunStateCopyWith<_RunState> get copyWith => __$RunStateCopyWithImpl<_RunState>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$RunStateToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _RunState&&(identical(other.running, running) || other.running == running)&&(identical(other.targetId, targetId) || other.targetId == targetId)&&(identical(other.method, method) || other.method == method)&&(identical(other.percent, percent) || other.percent == percent)&&(identical(other.eta, eta) || other.eta == eta)&&(identical(other.message, message) || other.message == message)&&(identical(other.startedAt, startedAt) || other.startedAt == startedAt));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,running,targetId,method,percent,eta,message,startedAt);
@override
String toString() {
return 'RunState(running: $running, targetId: $targetId, method: $method, percent: $percent, eta: $eta, message: $message, startedAt: $startedAt)';
}
}
/// @nodoc
abstract mixin class _$RunStateCopyWith<$Res> implements $RunStateCopyWith<$Res> {
factory _$RunStateCopyWith(_RunState value, $Res Function(_RunState) _then) = __$RunStateCopyWithImpl;
@override @useResult
$Res call({
bool running,@JsonKey(name: 'target_id') String targetId, BackupMethod? method, double percent, String? eta, String? message,@JsonKey(name: 'started_at') DateTime? startedAt
});
}
/// @nodoc
class __$RunStateCopyWithImpl<$Res>
implements _$RunStateCopyWith<$Res> {
__$RunStateCopyWithImpl(this._self, this._then);
final _RunState _self;
final $Res Function(_RunState) _then;
/// Create a copy of RunState
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? running = null,Object? targetId = null,Object? method = freezed,Object? percent = null,Object? eta = freezed,Object? message = freezed,Object? startedAt = freezed,}) {
return _then(_RunState(
running: null == running ? _self.running : running // ignore: cast_nullable_to_non_nullable
as bool,targetId: null == targetId ? _self.targetId : targetId // ignore: cast_nullable_to_non_nullable
as String,method: freezed == method ? _self.method : method // ignore: cast_nullable_to_non_nullable
as BackupMethod?,percent: null == percent ? _self.percent : percent // ignore: cast_nullable_to_non_nullable
as double,eta: freezed == eta ? _self.eta : eta // ignore: cast_nullable_to_non_nullable
as String?,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
as String?,startedAt: freezed == startedAt ? _self.startedAt : startedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,
));
}
}
// dart format on
+35
View File
@@ -0,0 +1,35 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'run_state.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_RunState _$RunStateFromJson(Map<String, dynamic> json) => _RunState(
running: json['running'] as bool? ?? false,
targetId: json['target_id'] as String? ?? '',
method: $enumDecodeNullable(_$BackupMethodEnumMap, json['method']),
percent: (json['percent'] as num?)?.toDouble() ?? 0,
eta: json['eta'] as String?,
message: json['message'] as String?,
startedAt: json['started_at'] == null
? null
: DateTime.parse(json['started_at'] as String),
);
Map<String, dynamic> _$RunStateToJson(_RunState instance) => <String, dynamic>{
'running': instance.running,
'target_id': instance.targetId,
'method': _$BackupMethodEnumMap[instance.method],
'percent': instance.percent,
'eta': instance.eta,
'message': instance.message,
'started_at': instance.startedAt?.toIso8601String(),
};
const _$BackupMethodEnumMap = {
BackupMethod.rsync: 'rsync',
BackupMethod.restic: 'restic',
BackupMethod.external: 'external',
};

Some files were not shown because too many files have changed in this diff Show More