pumaguard 21.post27__py3-none-any.whl → 21.post83__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. pumaguard/presets.py +1 -0
  2. pumaguard/pumaguard-ui/.last_build_id +1 -1
  3. pumaguard/pumaguard-ui/assets/NOTICES +621 -71
  4. pumaguard/pumaguard-ui/assets/fonts/MaterialIcons-Regular.otf +0 -0
  5. pumaguard/pumaguard-ui/flutter_bootstrap.js +1 -1
  6. pumaguard/pumaguard-ui/main.dart.js +28869 -28787
  7. pumaguard/web_routes/dhcp.py +311 -54
  8. pumaguard/web_routes/diagnostics.py +6 -0
  9. pumaguard/web_routes/settings.py +13 -0
  10. pumaguard/web_ui.py +29 -0
  11. {pumaguard-21.post27.dist-info → pumaguard-21.post83.dist-info}/METADATA +1 -1
  12. pumaguard-21.post83.dist-info/RECORD +254 -0
  13. pumaguard-ui/.gitignore +48 -0
  14. pumaguard-ui/.metadata +45 -0
  15. pumaguard-ui/API_REFERENCE.md +717 -0
  16. pumaguard-ui/LICENSE +201 -0
  17. pumaguard-ui/Makefile +36 -0
  18. pumaguard-ui/README.md +371 -0
  19. pumaguard-ui/UI_DEVELOPMENT_CONTEXT.md +427 -0
  20. pumaguard-ui/analysis_options.yaml +28 -0
  21. pumaguard-ui/android/.gitignore +14 -0
  22. pumaguard-ui/android/app/build.gradle.kts +44 -0
  23. pumaguard-ui/android/app/src/debug/AndroidManifest.xml +7 -0
  24. pumaguard-ui/android/app/src/main/AndroidManifest.xml +45 -0
  25. pumaguard-ui/android/app/src/main/kotlin/com/example/pumaguard_ui/MainActivity.kt +5 -0
  26. pumaguard-ui/android/app/src/main/res/drawable/launch_background.xml +12 -0
  27. pumaguard-ui/android/app/src/main/res/drawable-v21/launch_background.xml +12 -0
  28. pumaguard-ui/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  29. pumaguard-ui/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  30. pumaguard-ui/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  31. pumaguard-ui/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  32. pumaguard-ui/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  33. pumaguard-ui/android/app/src/main/res/values/styles.xml +18 -0
  34. pumaguard-ui/android/app/src/main/res/values-night/styles.xml +18 -0
  35. pumaguard-ui/android/app/src/profile/AndroidManifest.xml +7 -0
  36. pumaguard-ui/android/build.gradle.kts +24 -0
  37. pumaguard-ui/android/gradle/wrapper/gradle-wrapper.properties +5 -0
  38. pumaguard-ui/android/gradle.properties +2 -0
  39. pumaguard-ui/android/settings.gradle.kts +26 -0
  40. pumaguard-ui/fonts/README.md +38 -0
  41. pumaguard-ui/fonts/Roboto-Bold.ttf +0 -0
  42. pumaguard-ui/fonts/Roboto-Light.ttf +0 -0
  43. pumaguard-ui/fonts/Roboto-Medium.ttf +0 -0
  44. pumaguard-ui/fonts/Roboto-Regular.ttf +0 -0
  45. pumaguard-ui/fonts/RobotoMono-Bold.ttf +0 -0
  46. pumaguard-ui/fonts/RobotoMono-Medium.ttf +0 -0
  47. pumaguard-ui/fonts/RobotoMono-Regular.ttf +0 -0
  48. pumaguard-ui/fonts/download_fonts.sh +76 -0
  49. pumaguard-ui/ios/.gitignore +34 -0
  50. pumaguard-ui/ios/Flutter/AppFrameworkInfo.plist +26 -0
  51. pumaguard-ui/ios/Flutter/Debug.xcconfig +1 -0
  52. pumaguard-ui/ios/Flutter/Release.xcconfig +1 -0
  53. pumaguard-ui/ios/Runner/AppDelegate.swift +13 -0
  54. pumaguard-ui/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +122 -0
  55. pumaguard-ui/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png +0 -0
  56. pumaguard-ui/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png +0 -0
  57. pumaguard-ui/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png +0 -0
  58. pumaguard-ui/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png +0 -0
  59. pumaguard-ui/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png +0 -0
  60. pumaguard-ui/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png +0 -0
  61. pumaguard-ui/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png +0 -0
  62. pumaguard-ui/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png +0 -0
  63. pumaguard-ui/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png +0 -0
  64. pumaguard-ui/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png +0 -0
  65. pumaguard-ui/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png +0 -0
  66. pumaguard-ui/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png +0 -0
  67. pumaguard-ui/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png +0 -0
  68. pumaguard-ui/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png +0 -0
  69. pumaguard-ui/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png +0 -0
  70. pumaguard-ui/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +23 -0
  71. pumaguard-ui/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png +0 -0
  72. pumaguard-ui/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png +0 -0
  73. pumaguard-ui/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png +0 -0
  74. pumaguard-ui/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +5 -0
  75. pumaguard-ui/ios/Runner/Base.lproj/LaunchScreen.storyboard +37 -0
  76. pumaguard-ui/ios/Runner/Base.lproj/Main.storyboard +26 -0
  77. pumaguard-ui/ios/Runner/Info.plist +49 -0
  78. pumaguard-ui/ios/Runner/Runner-Bridging-Header.h +1 -0
  79. pumaguard-ui/ios/Runner.xcodeproj/project.pbxproj +616 -0
  80. pumaguard-ui/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  81. pumaguard-ui/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  82. pumaguard-ui/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +8 -0
  83. pumaguard-ui/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +101 -0
  84. pumaguard-ui/ios/Runner.xcworkspace/contents.xcworkspacedata +7 -0
  85. pumaguard-ui/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  86. pumaguard-ui/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +8 -0
  87. pumaguard-ui/ios/RunnerTests/RunnerTests.swift +12 -0
  88. pumaguard-ui/lib/main.dart +56 -0
  89. pumaguard-ui/lib/models/camera.dart +45 -0
  90. pumaguard-ui/lib/models/plug.dart +45 -0
  91. pumaguard-ui/lib/models/settings.dart +112 -0
  92. pumaguard-ui/lib/models/status.dart +58 -0
  93. pumaguard-ui/lib/screens/directories_screen.dart +319 -0
  94. pumaguard-ui/lib/screens/home_screen.dart +545 -0
  95. pumaguard-ui/lib/screens/image_browser_screen.dart +1248 -0
  96. pumaguard-ui/lib/screens/server_discovery_screen.dart +390 -0
  97. pumaguard-ui/lib/screens/settings_screen.dart +1162 -0
  98. pumaguard-ui/lib/screens/wifi_settings_screen.dart +671 -0
  99. pumaguard-ui/lib/services/api_service.dart +717 -0
  100. pumaguard-ui/lib/services/camera_events_service.dart +195 -0
  101. pumaguard-ui/lib/services/mdns_service.dart +4 -0
  102. pumaguard-ui/lib/services/mdns_service_impl.dart +282 -0
  103. pumaguard-ui/lib/services/mdns_service_io.dart +1 -0
  104. pumaguard-ui/lib/services/mdns_service_web.dart +106 -0
  105. pumaguard-ui/lib/utils/download_helper.dart +2 -0
  106. pumaguard-ui/lib/utils/download_helper_stub.dart +6 -0
  107. pumaguard-ui/lib/utils/download_helper_web.dart +14 -0
  108. pumaguard-ui/lib/utils/platform_url.dart +10 -0
  109. pumaguard-ui/lib/utils/platform_url_stub.dart +11 -0
  110. pumaguard-ui/lib/utils/platform_url_web.dart +16 -0
  111. pumaguard-ui/linux/.gitignore +1 -0
  112. pumaguard-ui/linux/CMakeLists.txt +128 -0
  113. pumaguard-ui/linux/flutter/CMakeLists.txt +88 -0
  114. pumaguard-ui/linux/flutter/generated_plugin_registrant.cc +15 -0
  115. pumaguard-ui/linux/flutter/generated_plugin_registrant.h +15 -0
  116. pumaguard-ui/linux/flutter/generated_plugins.cmake +24 -0
  117. pumaguard-ui/linux/runner/CMakeLists.txt +26 -0
  118. pumaguard-ui/linux/runner/main.cc +6 -0
  119. pumaguard-ui/linux/runner/my_application.cc +148 -0
  120. pumaguard-ui/linux/runner/my_application.h +21 -0
  121. pumaguard-ui/macos/.gitignore +7 -0
  122. pumaguard-ui/macos/Flutter/Flutter-Debug.xcconfig +1 -0
  123. pumaguard-ui/macos/Flutter/Flutter-Release.xcconfig +1 -0
  124. pumaguard-ui/macos/Flutter/GeneratedPluginRegistrant.swift +16 -0
  125. pumaguard-ui/macos/Runner/AppDelegate.swift +13 -0
  126. pumaguard-ui/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +68 -0
  127. pumaguard-ui/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png +0 -0
  128. pumaguard-ui/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png +0 -0
  129. pumaguard-ui/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png +0 -0
  130. pumaguard-ui/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png +0 -0
  131. pumaguard-ui/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png +0 -0
  132. pumaguard-ui/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png +0 -0
  133. pumaguard-ui/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png +0 -0
  134. pumaguard-ui/macos/Runner/Base.lproj/MainMenu.xib +343 -0
  135. pumaguard-ui/macos/Runner/Configs/AppInfo.xcconfig +14 -0
  136. pumaguard-ui/macos/Runner/Configs/Debug.xcconfig +2 -0
  137. pumaguard-ui/macos/Runner/Configs/Release.xcconfig +2 -0
  138. pumaguard-ui/macos/Runner/Configs/Warnings.xcconfig +13 -0
  139. pumaguard-ui/macos/Runner/DebugProfile.entitlements +12 -0
  140. pumaguard-ui/macos/Runner/Info.plist +32 -0
  141. pumaguard-ui/macos/Runner/MainFlutterWindow.swift +15 -0
  142. pumaguard-ui/macos/Runner/Release.entitlements +8 -0
  143. pumaguard-ui/macos/Runner.xcodeproj/project.pbxproj +705 -0
  144. pumaguard-ui/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  145. pumaguard-ui/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +99 -0
  146. pumaguard-ui/macos/Runner.xcworkspace/contents.xcworkspacedata +7 -0
  147. pumaguard-ui/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  148. pumaguard-ui/macos/RunnerTests/RunnerTests.swift +12 -0
  149. pumaguard-ui/pubspec.lock +882 -0
  150. pumaguard-ui/pubspec.yaml +125 -0
  151. pumaguard-ui/test/models/camera_test.dart +515 -0
  152. pumaguard-ui/test/models/plug_test.dart +499 -0
  153. pumaguard-ui/test/models/settings_test.dart +903 -0
  154. pumaguard-ui/test/models/status_test.dart +707 -0
  155. pumaguard-ui/test/screens/image_browser_grouping_test.dart +555 -0
  156. pumaguard-ui/test/services/api_service_cameras_test.dart +580 -0
  157. pumaguard-ui/test/services/api_service_image_browser_test.dart +512 -0
  158. pumaguard-ui/test/widget_test.dart.skip +38 -0
  159. pumaguard-ui/web/favicon.png +0 -0
  160. pumaguard-ui/web/icons/Icon-192.png +0 -0
  161. pumaguard-ui/web/icons/Icon-512.png +0 -0
  162. pumaguard-ui/web/icons/Icon-maskable-192.png +0 -0
  163. pumaguard-ui/web/icons/Icon-maskable-512.png +0 -0
  164. pumaguard-ui/web/index.html +38 -0
  165. pumaguard-ui/web/manifest.json +35 -0
  166. pumaguard-ui/windows/.gitignore +17 -0
  167. pumaguard-ui/windows/CMakeLists.txt +108 -0
  168. pumaguard-ui/windows/flutter/CMakeLists.txt +109 -0
  169. pumaguard-ui/windows/flutter/generated_plugin_registrant.cc +14 -0
  170. pumaguard-ui/windows/flutter/generated_plugin_registrant.h +15 -0
  171. pumaguard-ui/windows/flutter/generated_plugins.cmake +24 -0
  172. pumaguard-ui/windows/runner/CMakeLists.txt +40 -0
  173. pumaguard-ui/windows/runner/Runner.rc +121 -0
  174. pumaguard-ui/windows/runner/flutter_window.cpp +71 -0
  175. pumaguard-ui/windows/runner/flutter_window.h +33 -0
  176. pumaguard-ui/windows/runner/main.cpp +43 -0
  177. pumaguard-ui/windows/runner/resource.h +16 -0
  178. pumaguard-ui/windows/runner/resources/app_icon.ico +0 -0
  179. pumaguard-ui/windows/runner/runner.exe.manifest +14 -0
  180. pumaguard-ui/windows/runner/utils.cpp +65 -0
  181. pumaguard-ui/windows/runner/utils.h +19 -0
  182. pumaguard-ui/windows/runner/win32_window.cpp +288 -0
  183. pumaguard-ui/windows/runner/win32_window.h +102 -0
  184. pumaguard-21.post27.dist-info/RECORD +0 -83
  185. {pumaguard-21.post27.dist-info → pumaguard-21.post83.dist-info}/WHEEL +0 -0
  186. {pumaguard-21.post27.dist-info → pumaguard-21.post83.dist-info}/entry_points.txt +0 -0
  187. {pumaguard-21.post27.dist-info → pumaguard-21.post83.dist-info}/licenses/LICENSE +0 -0
  188. {pumaguard-21.post27.dist-info → pumaguard-21.post83.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,101 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Scheme
3
+ LastUpgradeVersion = "1510"
4
+ version = "1.3">
5
+ <BuildAction
6
+ parallelizeBuildables = "YES"
7
+ buildImplicitDependencies = "YES">
8
+ <BuildActionEntries>
9
+ <BuildActionEntry
10
+ buildForTesting = "YES"
11
+ buildForRunning = "YES"
12
+ buildForProfiling = "YES"
13
+ buildForArchiving = "YES"
14
+ buildForAnalyzing = "YES">
15
+ <BuildableReference
16
+ BuildableIdentifier = "primary"
17
+ BlueprintIdentifier = "97C146ED1CF9000F007C117D"
18
+ BuildableName = "Runner.app"
19
+ BlueprintName = "Runner"
20
+ ReferencedContainer = "container:Runner.xcodeproj">
21
+ </BuildableReference>
22
+ </BuildActionEntry>
23
+ </BuildActionEntries>
24
+ </BuildAction>
25
+ <TestAction
26
+ buildConfiguration = "Debug"
27
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29
+ customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
30
+ shouldUseLaunchSchemeArgsEnv = "YES">
31
+ <MacroExpansion>
32
+ <BuildableReference
33
+ BuildableIdentifier = "primary"
34
+ BlueprintIdentifier = "97C146ED1CF9000F007C117D"
35
+ BuildableName = "Runner.app"
36
+ BlueprintName = "Runner"
37
+ ReferencedContainer = "container:Runner.xcodeproj">
38
+ </BuildableReference>
39
+ </MacroExpansion>
40
+ <Testables>
41
+ <TestableReference
42
+ skipped = "NO"
43
+ parallelizable = "YES">
44
+ <BuildableReference
45
+ BuildableIdentifier = "primary"
46
+ BlueprintIdentifier = "331C8080294A63A400263BE5"
47
+ BuildableName = "RunnerTests.xctest"
48
+ BlueprintName = "RunnerTests"
49
+ ReferencedContainer = "container:Runner.xcodeproj">
50
+ </BuildableReference>
51
+ </TestableReference>
52
+ </Testables>
53
+ </TestAction>
54
+ <LaunchAction
55
+ buildConfiguration = "Debug"
56
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
57
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
58
+ customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
59
+ launchStyle = "0"
60
+ useCustomWorkingDirectory = "NO"
61
+ ignoresPersistentStateOnLaunch = "NO"
62
+ debugDocumentVersioning = "YES"
63
+ debugServiceExtension = "internal"
64
+ enableGPUValidationMode = "1"
65
+ allowLocationSimulation = "YES">
66
+ <BuildableProductRunnable
67
+ runnableDebuggingMode = "0">
68
+ <BuildableReference
69
+ BuildableIdentifier = "primary"
70
+ BlueprintIdentifier = "97C146ED1CF9000F007C117D"
71
+ BuildableName = "Runner.app"
72
+ BlueprintName = "Runner"
73
+ ReferencedContainer = "container:Runner.xcodeproj">
74
+ </BuildableReference>
75
+ </BuildableProductRunnable>
76
+ </LaunchAction>
77
+ <ProfileAction
78
+ buildConfiguration = "Profile"
79
+ shouldUseLaunchSchemeArgsEnv = "YES"
80
+ savedToolIdentifier = ""
81
+ useCustomWorkingDirectory = "NO"
82
+ debugDocumentVersioning = "YES">
83
+ <BuildableProductRunnable
84
+ runnableDebuggingMode = "0">
85
+ <BuildableReference
86
+ BuildableIdentifier = "primary"
87
+ BlueprintIdentifier = "97C146ED1CF9000F007C117D"
88
+ BuildableName = "Runner.app"
89
+ BlueprintName = "Runner"
90
+ ReferencedContainer = "container:Runner.xcodeproj">
91
+ </BuildableReference>
92
+ </BuildableProductRunnable>
93
+ </ProfileAction>
94
+ <AnalyzeAction
95
+ buildConfiguration = "Debug">
96
+ </AnalyzeAction>
97
+ <ArchiveAction
98
+ buildConfiguration = "Release"
99
+ revealArchiveInOrganizer = "YES">
100
+ </ArchiveAction>
101
+ </Scheme>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Workspace
3
+ version = "1.0">
4
+ <FileRef
5
+ location = "group:Runner.xcodeproj">
6
+ </FileRef>
7
+ </Workspace>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>IDEDidComputeMac32BitWarning</key>
6
+ <true/>
7
+ </dict>
8
+ </plist>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>PreviewsEnabled</key>
6
+ <false/>
7
+ </dict>
8
+ </plist>
@@ -0,0 +1,12 @@
1
+ import Flutter
2
+ import UIKit
3
+ import XCTest
4
+
5
+ class RunnerTests: XCTestCase {
6
+
7
+ func testExample() {
8
+ // If you add code to the Runner application, consider adding tests here.
9
+ // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10
+ }
11
+
12
+ }
@@ -0,0 +1,56 @@
1
+ import 'package:flutter/material.dart';
2
+ import 'package:provider/provider.dart';
3
+ import 'screens/home_screen.dart';
4
+ import 'services/api_service.dart';
5
+ import 'version.dart';
6
+
7
+ void main() {
8
+ runApp(const PumaGuardApp());
9
+ }
10
+
11
+ class PumaGuardApp extends StatelessWidget {
12
+ const PumaGuardApp({super.key});
13
+
14
+ @override
15
+ Widget build(BuildContext context) {
16
+ return Provider<ApiService>(
17
+ create: (_) => ApiService(),
18
+ child: MaterialApp(
19
+ title: 'PumaGuard $appVersion',
20
+ debugShowCheckedModeBanner: false,
21
+ theme: ThemeData(
22
+ useMaterial3: true,
23
+ fontFamily: 'Roboto',
24
+ colorScheme: ColorScheme.fromSeed(
25
+ seedColor: const Color(0xFF8B4513), // Brown/puma color
26
+ brightness: Brightness.light,
27
+ ),
28
+ cardTheme: CardThemeData(
29
+ elevation: 2,
30
+ shape: RoundedRectangleBorder(
31
+ borderRadius: BorderRadius.circular(12),
32
+ ),
33
+ ),
34
+ appBarTheme: const AppBarTheme(centerTitle: true, elevation: 0),
35
+ ),
36
+ darkTheme: ThemeData(
37
+ useMaterial3: true,
38
+ fontFamily: 'Roboto',
39
+ colorScheme: ColorScheme.fromSeed(
40
+ seedColor: const Color(0xFF8B4513),
41
+ brightness: Brightness.dark,
42
+ ),
43
+ cardTheme: CardThemeData(
44
+ elevation: 2,
45
+ shape: RoundedRectangleBorder(
46
+ borderRadius: BorderRadius.circular(12),
47
+ ),
48
+ ),
49
+ appBarTheme: const AppBarTheme(centerTitle: true, elevation: 0),
50
+ ),
51
+ themeMode: ThemeMode.system,
52
+ home: const HomeScreen(),
53
+ ),
54
+ );
55
+ }
56
+ }
@@ -0,0 +1,45 @@
1
+ class Camera {
2
+ final String hostname;
3
+ final String ipAddress;
4
+ final String macAddress;
5
+ final String lastSeen;
6
+ final String status;
7
+
8
+ Camera({
9
+ required this.hostname,
10
+ required this.ipAddress,
11
+ required this.macAddress,
12
+ required this.lastSeen,
13
+ required this.status,
14
+ });
15
+
16
+ factory Camera.fromJson(Map<String, dynamic> json) {
17
+ return Camera(
18
+ hostname: json['hostname'] as String? ?? '',
19
+ ipAddress: json['ip_address'] as String? ?? '',
20
+ macAddress: json['mac_address'] as String? ?? '',
21
+ lastSeen: json['last_seen'] as String? ?? '',
22
+ status: json['status'] as String? ?? 'unknown',
23
+ );
24
+ }
25
+
26
+ Map<String, dynamic> toJson() {
27
+ return {
28
+ 'hostname': hostname,
29
+ 'ip_address': ipAddress,
30
+ 'mac_address': macAddress,
31
+ 'last_seen': lastSeen,
32
+ 'status': status,
33
+ };
34
+ }
35
+
36
+ bool get isConnected => status == 'connected';
37
+
38
+ String get displayName => hostname.isNotEmpty ? hostname : ipAddress;
39
+
40
+ String get cameraUrl {
41
+ if (ipAddress.isEmpty) return '';
42
+ // Return URL without scheme - let caller add http:// or https://
43
+ return ipAddress;
44
+ }
45
+ }
@@ -0,0 +1,45 @@
1
+ class Plug {
2
+ final String hostname;
3
+ final String ipAddress;
4
+ final String macAddress;
5
+ final String lastSeen;
6
+ final String status;
7
+
8
+ Plug({
9
+ required this.hostname,
10
+ required this.ipAddress,
11
+ required this.macAddress,
12
+ required this.lastSeen,
13
+ required this.status,
14
+ });
15
+
16
+ factory Plug.fromJson(Map<String, dynamic> json) {
17
+ return Plug(
18
+ hostname: json['hostname'] as String? ?? '',
19
+ ipAddress: json['ip_address'] as String? ?? '',
20
+ macAddress: json['mac_address'] as String? ?? '',
21
+ lastSeen: json['last_seen'] as String? ?? '',
22
+ status: json['status'] as String? ?? 'unknown',
23
+ );
24
+ }
25
+
26
+ Map<String, dynamic> toJson() {
27
+ return {
28
+ 'hostname': hostname,
29
+ 'ip_address': ipAddress,
30
+ 'mac_address': macAddress,
31
+ 'last_seen': lastSeen,
32
+ 'status': status,
33
+ };
34
+ }
35
+
36
+ bool get isConnected => status == 'connected';
37
+
38
+ String get displayName => hostname.isNotEmpty ? hostname : ipAddress;
39
+
40
+ String get plugUrl {
41
+ if (ipAddress.isEmpty) return '';
42
+ // Return URL without scheme - let caller add http:// or https://
43
+ return ipAddress;
44
+ }
45
+ }
@@ -0,0 +1,112 @@
1
+ import 'camera.dart';
2
+ import 'plug.dart';
3
+
4
+ class Settings {
5
+ final double yoloMinSize;
6
+ final double yoloConfThresh;
7
+ final int yoloMaxDets;
8
+ final String yoloModelFilename;
9
+ final String classifierModelFilename;
10
+ final String deterrentSoundFile;
11
+ final double fileStabilizationExtraWait;
12
+ final bool playSound;
13
+ final int volume;
14
+ final List<Camera> cameras;
15
+ final List<Plug> plugs;
16
+
17
+ Settings({
18
+ required this.yoloMinSize,
19
+ required this.yoloConfThresh,
20
+ required this.yoloMaxDets,
21
+ required this.yoloModelFilename,
22
+ required this.classifierModelFilename,
23
+ required this.deterrentSoundFile,
24
+ required this.fileStabilizationExtraWait,
25
+ required this.playSound,
26
+ required this.volume,
27
+ required this.cameras,
28
+ required this.plugs,
29
+ });
30
+
31
+ factory Settings.fromJson(Map<String, dynamic> json) {
32
+ // Parse cameras list
33
+ List<Camera> camerasList = [];
34
+ if (json['cameras'] is List) {
35
+ camerasList = (json['cameras'] as List)
36
+ .map(
37
+ (cameraJson) => Camera.fromJson(cameraJson as Map<String, dynamic>),
38
+ )
39
+ .toList();
40
+ }
41
+
42
+ // Parse plugs list
43
+ List<Plug> plugsList = [];
44
+ if (json['plugs'] is List) {
45
+ plugsList = (json['plugs'] as List)
46
+ .map((plugJson) => Plug.fromJson(plugJson as Map<String, dynamic>))
47
+ .toList();
48
+ }
49
+
50
+ return Settings(
51
+ yoloMinSize: (json['YOLO-min-size'] as num?)?.toDouble() ?? 0.01,
52
+ yoloConfThresh: (json['YOLO-conf-thresh'] as num?)?.toDouble() ?? 0.25,
53
+ yoloMaxDets: json['YOLO-max-dets'] as int? ?? 10,
54
+ yoloModelFilename: json['YOLO-model-filename'] as String? ?? '',
55
+ classifierModelFilename:
56
+ json['classifier-model-filename'] as String? ?? '',
57
+ deterrentSoundFile: json['deterrent-sound-file'] as String? ?? '',
58
+ fileStabilizationExtraWait:
59
+ (json['file-stabilization-extra-wait'] as num?)?.toDouble() ?? 2.0,
60
+ playSound: json['play-sound'] as bool? ?? false,
61
+ volume: json['volume'] as int? ?? 80,
62
+ cameras: camerasList,
63
+ plugs: plugsList,
64
+ );
65
+ }
66
+
67
+ Map<String, dynamic> toJson() {
68
+ return {
69
+ 'YOLO-min-size': yoloMinSize,
70
+ 'YOLO-conf-thresh': yoloConfThresh,
71
+ 'YOLO-max-dets': yoloMaxDets,
72
+ 'YOLO-model-filename': yoloModelFilename,
73
+ 'classifier-model-filename': classifierModelFilename,
74
+ 'deterrent-sound-file': deterrentSoundFile,
75
+ 'file-stabilization-extra-wait': fileStabilizationExtraWait,
76
+ 'play-sound': playSound,
77
+ 'volume': volume,
78
+ 'cameras': cameras.map((camera) => camera.toJson()).toList(),
79
+ 'plugs': plugs.map((plug) => plug.toJson()).toList(),
80
+ };
81
+ }
82
+
83
+ Settings copyWith({
84
+ double? yoloMinSize,
85
+ double? yoloConfThresh,
86
+ int? yoloMaxDets,
87
+ String? yoloModelFilename,
88
+ String? classifierModelFilename,
89
+ String? deterrentSoundFile,
90
+ double? fileStabilizationExtraWait,
91
+ bool? playSound,
92
+ int? volume,
93
+ List<Camera>? cameras,
94
+ List<Plug>? plugs,
95
+ }) {
96
+ return Settings(
97
+ yoloMinSize: yoloMinSize ?? this.yoloMinSize,
98
+ yoloConfThresh: yoloConfThresh ?? this.yoloConfThresh,
99
+ yoloMaxDets: yoloMaxDets ?? this.yoloMaxDets,
100
+ yoloModelFilename: yoloModelFilename ?? this.yoloModelFilename,
101
+ classifierModelFilename:
102
+ classifierModelFilename ?? this.classifierModelFilename,
103
+ deterrentSoundFile: deterrentSoundFile ?? this.deterrentSoundFile,
104
+ fileStabilizationExtraWait:
105
+ fileStabilizationExtraWait ?? this.fileStabilizationExtraWait,
106
+ playSound: playSound ?? this.playSound,
107
+ volume: volume ?? this.volume,
108
+ cameras: cameras ?? this.cameras,
109
+ plugs: plugs ?? this.plugs,
110
+ );
111
+ }
112
+ }
@@ -0,0 +1,58 @@
1
+ class Status {
2
+ final String status;
3
+ final String version;
4
+ final int directoriesCount;
5
+ final String host;
6
+ final int port;
7
+ final int uptimeSeconds;
8
+
9
+ Status({
10
+ required this.status,
11
+ required this.version,
12
+ required this.directoriesCount,
13
+ required this.host,
14
+ required this.port,
15
+ required this.uptimeSeconds,
16
+ });
17
+
18
+ factory Status.fromJson(Map<String, dynamic> json) {
19
+ return Status(
20
+ status: json['status'] as String? ?? 'unknown',
21
+ version: json['version'] as String? ?? '0.0.0',
22
+ directoriesCount: json['directories_count'] as int? ?? 0,
23
+ host: json['host'] as String? ?? 'localhost',
24
+ port: json['port'] as int? ?? 5000,
25
+ uptimeSeconds: json['uptime_seconds'] as int? ?? 0,
26
+ );
27
+ }
28
+
29
+ Map<String, dynamic> toJson() {
30
+ return {
31
+ 'status': status,
32
+ 'version': version,
33
+ 'directories_count': directoriesCount,
34
+ 'host': host,
35
+ 'port': port,
36
+ 'uptime_seconds': uptimeSeconds,
37
+ };
38
+ }
39
+
40
+ bool get isRunning => status == 'running';
41
+
42
+ String get uptimeFormatted {
43
+ final days = uptimeSeconds ~/ 86400;
44
+ final hours = (uptimeSeconds % 86400) ~/ 3600;
45
+ final minutes = (uptimeSeconds % 3600) ~/ 60;
46
+ final seconds = uptimeSeconds % 60;
47
+
48
+ if (days > 0) {
49
+ return '${days}d ${hours}h ${minutes}m';
50
+ } else if (hours > 0) {
51
+ return '${hours}h ${minutes}m ${seconds}s';
52
+ } else if (minutes > 0) {
53
+ return '${minutes}m ${seconds}s';
54
+ } else {
55
+ return '${seconds}s';
56
+ }
57
+ }
58
+ }