neoagent 2.3.1-beta.53 → 2.3.1-beta.56
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.
- package/flutter_app/lib/main.dart +2 -0
- package/flutter_app/lib/main_app_shell.dart +210 -180
- package/flutter_app/lib/main_runtime.dart +30 -1
- package/flutter_app/lib/main_shared.dart +453 -179
- package/flutter_app/lib/main_theme.dart +79 -24
- package/flutter_app/lib/src/web_app_update_monitor.dart +17 -0
- package/flutter_app/lib/src/web_app_update_monitor_stub.dart +24 -0
- package/flutter_app/lib/src/web_app_update_monitor_web.dart +123 -0
- package/package.json +3 -3
- package/server/http/static.js +41 -1
- package/server/public/.last_build_id +1 -1
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +62678 -62325
- package/server/services/messaging/meshtastic.js +11 -3
- package/server/services/messaging/meshtastic_protocol.js +25 -2
- package/server/services/messaging/meshtastic_protocol.test.js +33 -0
- package/server/services/messaging/meshtastic_tcp_transport.js +2 -2
|
@@ -30,33 +30,60 @@ Color get _danger => _palette.danger;
|
|
|
30
30
|
Color get _info => _palette.info;
|
|
31
31
|
|
|
32
32
|
LinearGradient get _appBackgroundGradient => LinearGradient(
|
|
33
|
-
colors: <Color>[
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
colors: <Color>[
|
|
34
|
+
_bgPrimary,
|
|
35
|
+
Color.lerp(_bgSecondary, _accentAlt, 0.08)!.withValues(alpha: 0.98),
|
|
36
|
+
Color.lerp(_bgPrimary, _accent, 0.05)!,
|
|
37
|
+
],
|
|
38
|
+
stops: const <double>[0, 0.52, 1],
|
|
39
|
+
begin: const Alignment(-0.95, -1),
|
|
40
|
+
end: const Alignment(1, 0.92),
|
|
36
41
|
);
|
|
37
42
|
|
|
38
43
|
LinearGradient get _panelGradient => LinearGradient(
|
|
39
44
|
colors: <Color>[
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
Colors.white.withValues(alpha: 0.08),
|
|
46
|
+
_bgCard.withValues(alpha: 0.9),
|
|
47
|
+
_bgSecondary.withValues(alpha: 0.82),
|
|
42
48
|
],
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
stops: const <double>[0, 0.18, 1],
|
|
50
|
+
begin: const Alignment(-0.85, -1),
|
|
51
|
+
end: const Alignment(1, 1),
|
|
45
52
|
);
|
|
46
53
|
|
|
47
54
|
List<BoxShadow> get _softPanelShadow => <BoxShadow>[
|
|
48
55
|
BoxShadow(
|
|
49
|
-
color: Colors.black.withValues(alpha: 0.
|
|
50
|
-
blurRadius:
|
|
51
|
-
offset: const Offset(0,
|
|
56
|
+
color: Colors.black.withValues(alpha: 0.22),
|
|
57
|
+
blurRadius: 52,
|
|
58
|
+
offset: const Offset(0, 22),
|
|
52
59
|
),
|
|
53
60
|
BoxShadow(
|
|
54
|
-
color: _accent.withValues(alpha: 0.
|
|
55
|
-
blurRadius:
|
|
56
|
-
offset: const Offset(0,
|
|
61
|
+
color: _accent.withValues(alpha: 0.08),
|
|
62
|
+
blurRadius: 30,
|
|
63
|
+
offset: const Offset(0, 8),
|
|
57
64
|
),
|
|
58
65
|
];
|
|
59
66
|
|
|
67
|
+
Color get _glassFill =>
|
|
68
|
+
_bgCard.withValues(alpha: _palette == _darkPalette ? 0.58 : 0.72);
|
|
69
|
+
Color get _glassOverlay =>
|
|
70
|
+
Colors.white.withValues(alpha: _palette == _darkPalette ? 0.08 : 0.24);
|
|
71
|
+
Color get _glassBorder =>
|
|
72
|
+
Colors.white.withValues(alpha: _palette == _darkPalette ? 0.15 : 0.42);
|
|
73
|
+
Color get _glassHighlight =>
|
|
74
|
+
Colors.white.withValues(alpha: _palette == _darkPalette ? 0.18 : 0.4);
|
|
75
|
+
|
|
76
|
+
LinearGradient get _liquidMetalGradient => LinearGradient(
|
|
77
|
+
colors: <Color>[
|
|
78
|
+
_glassOverlay,
|
|
79
|
+
Colors.white.withValues(alpha: 0.02),
|
|
80
|
+
_accentMuted.withValues(alpha: 0.16),
|
|
81
|
+
],
|
|
82
|
+
stops: const <double>[0, 0.44, 1],
|
|
83
|
+
begin: const Alignment(-1, -1),
|
|
84
|
+
end: const Alignment(1, 1),
|
|
85
|
+
);
|
|
86
|
+
|
|
60
87
|
TextStyle _displayTitleStyle([double size = 28]) => GoogleFonts.spaceGrotesk(
|
|
61
88
|
fontSize: size,
|
|
62
89
|
fontWeight: FontWeight.w700,
|
|
@@ -95,35 +122,39 @@ ThemeData _buildNeoAgentTheme(NeoAgentPalette palette, Brightness brightness) {
|
|
|
95
122
|
).apply(bodyColor: palette.textPrimary, displayColor: palette.textPrimary),
|
|
96
123
|
cardTheme: CardThemeData(
|
|
97
124
|
color: palette.bgCard.withValues(
|
|
98
|
-
alpha: brightness == Brightness.dark ? 0.
|
|
125
|
+
alpha: brightness == Brightness.dark ? 0.58 : 0.78,
|
|
99
126
|
),
|
|
100
127
|
shadowColor: Colors.black.withValues(
|
|
101
|
-
alpha: brightness == Brightness.dark ? 0.24 : 0.
|
|
128
|
+
alpha: brightness == Brightness.dark ? 0.24 : 0.12,
|
|
102
129
|
),
|
|
103
130
|
surfaceTintColor: Colors.transparent,
|
|
104
|
-
elevation: brightness == Brightness.dark ?
|
|
131
|
+
elevation: brightness == Brightness.dark ? 10 : 5,
|
|
105
132
|
margin: EdgeInsets.zero,
|
|
106
133
|
shape: RoundedRectangleBorder(
|
|
107
|
-
borderRadius: BorderRadius.circular(
|
|
108
|
-
side: BorderSide(
|
|
134
|
+
borderRadius: BorderRadius.circular(28),
|
|
135
|
+
side: BorderSide(
|
|
136
|
+
color: Colors.white.withValues(
|
|
137
|
+
alpha: brightness == Brightness.dark ? 0.12 : 0.3,
|
|
138
|
+
),
|
|
139
|
+
),
|
|
109
140
|
),
|
|
110
141
|
),
|
|
111
142
|
inputDecorationTheme: InputDecorationTheme(
|
|
112
143
|
filled: true,
|
|
113
144
|
fillColor: palette.bgSecondary.withValues(
|
|
114
|
-
alpha: brightness == Brightness.dark ? 0.
|
|
145
|
+
alpha: brightness == Brightness.dark ? 0.54 : 0.52,
|
|
115
146
|
),
|
|
116
147
|
border: OutlineInputBorder(
|
|
117
148
|
borderRadius: BorderRadius.circular(18),
|
|
118
|
-
borderSide: BorderSide(color: palette.
|
|
149
|
+
borderSide: BorderSide(color: palette.borderLight),
|
|
119
150
|
),
|
|
120
151
|
enabledBorder: OutlineInputBorder(
|
|
121
152
|
borderRadius: BorderRadius.circular(18),
|
|
122
|
-
borderSide: BorderSide(color: palette.
|
|
153
|
+
borderSide: BorderSide(color: palette.borderLight),
|
|
123
154
|
),
|
|
124
155
|
focusedBorder: OutlineInputBorder(
|
|
125
156
|
borderRadius: BorderRadius.circular(18),
|
|
126
|
-
borderSide: BorderSide(color: palette.
|
|
157
|
+
borderSide: BorderSide(color: palette.accentHover, width: 1.4),
|
|
127
158
|
),
|
|
128
159
|
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
|
129
160
|
labelStyle: TextStyle(
|
|
@@ -144,9 +175,17 @@ ThemeData _buildNeoAgentTheme(NeoAgentPalette palette, Brightness brightness) {
|
|
|
144
175
|
: Colors.white,
|
|
145
176
|
disabledBackgroundColor: palette.bgTertiary,
|
|
146
177
|
disabledForegroundColor: palette.textMuted,
|
|
178
|
+
shadowColor: palette.accent.withValues(alpha: 0.3),
|
|
147
179
|
elevation: 0,
|
|
148
180
|
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 16),
|
|
149
|
-
shape: RoundedRectangleBorder(
|
|
181
|
+
shape: RoundedRectangleBorder(
|
|
182
|
+
borderRadius: BorderRadius.circular(18),
|
|
183
|
+
side: BorderSide(
|
|
184
|
+
color: Colors.white.withValues(
|
|
185
|
+
alpha: brightness == Brightness.dark ? 0.14 : 0.26,
|
|
186
|
+
),
|
|
187
|
+
),
|
|
188
|
+
),
|
|
150
189
|
textStyle: GoogleFonts.manrope(
|
|
151
190
|
fontSize: 14,
|
|
152
191
|
fontWeight: FontWeight.w700,
|
|
@@ -157,7 +196,14 @@ ThemeData _buildNeoAgentTheme(NeoAgentPalette palette, Brightness brightness) {
|
|
|
157
196
|
outlinedButtonTheme: OutlinedButtonThemeData(
|
|
158
197
|
style: OutlinedButton.styleFrom(
|
|
159
198
|
foregroundColor: palette.textPrimary,
|
|
160
|
-
side: BorderSide(
|
|
199
|
+
side: BorderSide(
|
|
200
|
+
color: Colors.white.withValues(
|
|
201
|
+
alpha: brightness == Brightness.dark ? 0.12 : 0.26,
|
|
202
|
+
),
|
|
203
|
+
),
|
|
204
|
+
backgroundColor: palette.bgCard.withValues(
|
|
205
|
+
alpha: brightness == Brightness.dark ? 0.2 : 0.5,
|
|
206
|
+
),
|
|
161
207
|
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 16),
|
|
162
208
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(18)),
|
|
163
209
|
textStyle: GoogleFonts.manrope(
|
|
@@ -166,6 +212,15 @@ ThemeData _buildNeoAgentTheme(NeoAgentPalette palette, Brightness brightness) {
|
|
|
166
212
|
),
|
|
167
213
|
),
|
|
168
214
|
),
|
|
215
|
+
pageTransitionsTheme: const PageTransitionsTheme(
|
|
216
|
+
builders: <TargetPlatform, PageTransitionsBuilder>{
|
|
217
|
+
TargetPlatform.android: FadeForwardsPageTransitionsBuilder(),
|
|
218
|
+
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
|
|
219
|
+
TargetPlatform.macOS: CupertinoPageTransitionsBuilder(),
|
|
220
|
+
TargetPlatform.windows: FadeForwardsPageTransitionsBuilder(),
|
|
221
|
+
TargetPlatform.linux: FadeForwardsPageTransitionsBuilder(),
|
|
222
|
+
},
|
|
223
|
+
),
|
|
169
224
|
textButtonTheme: TextButtonThemeData(
|
|
170
225
|
style: TextButton.styleFrom(
|
|
171
226
|
foregroundColor: palette.accentHover,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import 'package:flutter/foundation.dart';
|
|
2
|
+
|
|
3
|
+
import 'web_app_update_monitor_stub.dart'
|
|
4
|
+
if (dart.library.html) 'web_app_update_monitor_web.dart';
|
|
5
|
+
|
|
6
|
+
abstract class WebAppUpdateMonitor implements Listenable {
|
|
7
|
+
bool get isSupported;
|
|
8
|
+
bool get updateAvailable;
|
|
9
|
+
bool get isReloading;
|
|
10
|
+
|
|
11
|
+
void start();
|
|
12
|
+
Future<void> reloadToLatest();
|
|
13
|
+
void dispose();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
WebAppUpdateMonitor createWebAppUpdateMonitor() =>
|
|
17
|
+
createPlatformWebAppUpdateMonitor();
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import 'package:flutter/foundation.dart';
|
|
2
|
+
|
|
3
|
+
import 'web_app_update_monitor.dart';
|
|
4
|
+
|
|
5
|
+
WebAppUpdateMonitor createPlatformWebAppUpdateMonitor() =>
|
|
6
|
+
_UnsupportedWebAppUpdateMonitor();
|
|
7
|
+
|
|
8
|
+
class _UnsupportedWebAppUpdateMonitor extends ChangeNotifier
|
|
9
|
+
implements WebAppUpdateMonitor {
|
|
10
|
+
@override
|
|
11
|
+
bool get isSupported => false;
|
|
12
|
+
|
|
13
|
+
@override
|
|
14
|
+
bool get isReloading => false;
|
|
15
|
+
|
|
16
|
+
@override
|
|
17
|
+
bool get updateAvailable => false;
|
|
18
|
+
|
|
19
|
+
@override
|
|
20
|
+
void start() {}
|
|
21
|
+
|
|
22
|
+
@override
|
|
23
|
+
Future<void> reloadToLatest() async {}
|
|
24
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// ignore_for_file: deprecated_member_use, avoid_web_libraries_in_flutter
|
|
2
|
+
|
|
3
|
+
import 'dart:async';
|
|
4
|
+
import 'dart:convert';
|
|
5
|
+
import 'dart:html' as html;
|
|
6
|
+
|
|
7
|
+
import 'package:flutter/foundation.dart';
|
|
8
|
+
import 'package:http/http.dart' as http;
|
|
9
|
+
|
|
10
|
+
import 'web_app_update_monitor.dart';
|
|
11
|
+
|
|
12
|
+
const String _currentWebBuildId = String.fromEnvironment(
|
|
13
|
+
'NEOAGENT_WEB_BUILD_ID',
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
WebAppUpdateMonitor createPlatformWebAppUpdateMonitor() =>
|
|
17
|
+
_WebPlatformAppUpdateMonitor();
|
|
18
|
+
|
|
19
|
+
class _WebPlatformAppUpdateMonitor extends ChangeNotifier
|
|
20
|
+
implements WebAppUpdateMonitor {
|
|
21
|
+
static const Duration _pollInterval = Duration(minutes: 1);
|
|
22
|
+
|
|
23
|
+
Timer? _pollTimer;
|
|
24
|
+
bool _updateAvailable = false;
|
|
25
|
+
bool _isReloading = false;
|
|
26
|
+
|
|
27
|
+
@override
|
|
28
|
+
bool get isSupported => _currentWebBuildId.trim().isNotEmpty;
|
|
29
|
+
|
|
30
|
+
@override
|
|
31
|
+
bool get updateAvailable => _updateAvailable;
|
|
32
|
+
|
|
33
|
+
@override
|
|
34
|
+
bool get isReloading => _isReloading;
|
|
35
|
+
|
|
36
|
+
@override
|
|
37
|
+
void start() {
|
|
38
|
+
if (!isSupported || _pollTimer != null) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
unawaited(_checkForUpdate());
|
|
42
|
+
_pollTimer = Timer.periodic(
|
|
43
|
+
_pollInterval,
|
|
44
|
+
(_) => unawaited(_checkForUpdate()),
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Future<void> _checkForUpdate() async {
|
|
49
|
+
if (_updateAvailable || _isReloading) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
final buildInfoUri = Uri.base.resolve(
|
|
54
|
+
'/app-build.json?ts=${DateTime.now().microsecondsSinceEpoch}',
|
|
55
|
+
);
|
|
56
|
+
final response = await http.get(
|
|
57
|
+
buildInfoUri,
|
|
58
|
+
headers: const <String, String>{
|
|
59
|
+
'cache-control': 'no-cache, no-store, max-age=0',
|
|
60
|
+
'pragma': 'no-cache',
|
|
61
|
+
},
|
|
62
|
+
);
|
|
63
|
+
if (response.statusCode != 200) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
final payload = jsonDecode(response.body);
|
|
67
|
+
if (payload is! Map) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
final latestBuildId = payload['buildId']?.toString().trim() ?? '';
|
|
71
|
+
if (latestBuildId.isEmpty || latestBuildId == _currentWebBuildId) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
_updateAvailable = true;
|
|
75
|
+
notifyListeners();
|
|
76
|
+
} catch (_) {}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@override
|
|
80
|
+
Future<void> reloadToLatest() async {
|
|
81
|
+
if (!isSupported || _isReloading) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
_isReloading = true;
|
|
85
|
+
notifyListeners();
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
final serviceWorker = html.window.navigator.serviceWorker;
|
|
89
|
+
if (serviceWorker != null) {
|
|
90
|
+
final registrations = await serviceWorker.getRegistrations();
|
|
91
|
+
for (final registration in registrations) {
|
|
92
|
+
await registration.unregister();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
} catch (_) {}
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
final cacheNames = await html.window.caches?.keys();
|
|
99
|
+
if (cacheNames != null) {
|
|
100
|
+
for (final cacheName in cacheNames) {
|
|
101
|
+
await html.window.caches?.delete(cacheName);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
} catch (_) {}
|
|
105
|
+
|
|
106
|
+
final reloadUri = Uri(
|
|
107
|
+
path: Uri.base.path.isEmpty ? '/' : Uri.base.path,
|
|
108
|
+
queryParameters: <String, String>{
|
|
109
|
+
...Uri.base.queryParameters,
|
|
110
|
+
'reload': DateTime.now().microsecondsSinceEpoch.toString(),
|
|
111
|
+
},
|
|
112
|
+
fragment: Uri.base.fragment.isEmpty ? null : Uri.base.fragment,
|
|
113
|
+
);
|
|
114
|
+
html.window.location.replace(reloadUri.toString());
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@override
|
|
118
|
+
void dispose() {
|
|
119
|
+
_pollTimer?.cancel();
|
|
120
|
+
_pollTimer = null;
|
|
121
|
+
super.dispose();
|
|
122
|
+
}
|
|
123
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neoagent",
|
|
3
|
-
"version": "2.3.1-beta.
|
|
3
|
+
"version": "2.3.1-beta.56",
|
|
4
4
|
"description": "Proactive personal AI agent with no limits",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "server/index.js",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"docs:dev": "docusaurus start",
|
|
36
36
|
"docs:build": "docusaurus build",
|
|
37
37
|
"docs:preview": "docusaurus serve build",
|
|
38
|
-
"flutter:run:web": "cd flutter_app && flutter run -d chrome",
|
|
39
|
-
"flutter:build:web": "cd flutter_app && flutter build web --output ../server/public --dart-define=NEOAGENT_BACKEND_URL=${NEOAGENT_BACKEND_URL:-}",
|
|
38
|
+
"flutter:run:web": "cd flutter_app && flutter run -d chrome --dart-define=NEOAGENT_WEB_BUILD_ID=$(node ../scripts/web_build_id.js)",
|
|
39
|
+
"flutter:build:web": "cd flutter_app && flutter build web --output ../server/public --dart-define=NEOAGENT_BACKEND_URL=${NEOAGENT_BACKEND_URL:-} --dart-define=NEOAGENT_WEB_BUILD_ID=$(node ../scripts/web_build_id.js)",
|
|
40
40
|
"manage": "node bin/neoagent.js",
|
|
41
41
|
"test": "node --test",
|
|
42
42
|
"benchmark:tokens": "node scripts/benchmark-token-cost.js",
|
package/server/http/static.js
CHANGED
|
@@ -7,6 +7,35 @@ const { DATA_DIR } = require('../../runtime/paths');
|
|
|
7
7
|
const { requireAuth } = require('../middleware/auth');
|
|
8
8
|
|
|
9
9
|
const FLUTTER_WEB_DIR = path.join(__dirname, '..', 'public');
|
|
10
|
+
const BUILD_ID_PATH = path.join(FLUTTER_WEB_DIR, '.last_build_id');
|
|
11
|
+
|
|
12
|
+
function setNoStoreHeaders(res) {
|
|
13
|
+
res.set('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate');
|
|
14
|
+
res.set('Pragma', 'no-cache');
|
|
15
|
+
res.set('Expires', '0');
|
|
16
|
+
res.set('Surrogate-Control', 'no-store');
|
|
17
|
+
res.set('CDN-Cache-Control', 'no-store');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function readCurrentBuildId() {
|
|
21
|
+
try {
|
|
22
|
+
return fs.readFileSync(BUILD_ID_PATH, 'utf8').trim() || null;
|
|
23
|
+
} catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function setFlutterStaticHeaders(res, filePath) {
|
|
29
|
+
const relativePath = path.relative(FLUTTER_WEB_DIR, filePath).replaceAll('\\', '/');
|
|
30
|
+
if (
|
|
31
|
+
relativePath === 'index.html' ||
|
|
32
|
+
relativePath === 'flutter_bootstrap.js' ||
|
|
33
|
+
relativePath === 'flutter_service_worker.js' ||
|
|
34
|
+
relativePath === 'version.json'
|
|
35
|
+
) {
|
|
36
|
+
setNoStoreHeaders(res);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
10
39
|
|
|
11
40
|
function registerStaticRoutes(app) {
|
|
12
41
|
app.use(
|
|
@@ -27,7 +56,17 @@ function registerStaticRoutes(app) {
|
|
|
27
56
|
express.static(path.join(DATA_DIR, 'screenshots'))
|
|
28
57
|
);
|
|
29
58
|
|
|
30
|
-
app.
|
|
59
|
+
app.get('/app-build.json', (req, res) => {
|
|
60
|
+
setNoStoreHeaders(res);
|
|
61
|
+
res.json({
|
|
62
|
+
buildId: readCurrentBuildId(),
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
app.use(express.static(FLUTTER_WEB_DIR, {
|
|
67
|
+
index: false,
|
|
68
|
+
setHeaders: setFlutterStaticHeaders,
|
|
69
|
+
}));
|
|
31
70
|
app.get(/^\/(?!api|screenshots|telnyx-audio).*/, serveFlutterApp);
|
|
32
71
|
}
|
|
33
72
|
|
|
@@ -40,6 +79,7 @@ function serveFlutterApp(req, res) {
|
|
|
40
79
|
'Flutter web build not found. Run "npm run flutter:build:web" to generate the bundled client.'
|
|
41
80
|
);
|
|
42
81
|
}
|
|
82
|
+
setNoStoreHeaders(res);
|
|
43
83
|
return res.sendFile(entry);
|
|
44
84
|
}
|
|
45
85
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
af264d9a8e6140cadf8a95b90b714112
|
|
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"42d3d75a56efe1a2e9902f52dc8006099c45d9
|
|
|
37
37
|
|
|
38
38
|
_flutter.loader.load({
|
|
39
39
|
serviceWorkerSettings: {
|
|
40
|
-
serviceWorkerVersion: "
|
|
40
|
+
serviceWorkerVersion: "3546406361" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
|
|
41
41
|
}
|
|
42
42
|
});
|