Skip to content

Commit f78119c

Browse files
committed
SDK loading changes:
* Fix initial load being force-waited even when a local publish model exists. * Make slug loading use firebase storage instead. * Fix logging and stopwatching issues. * Fix skipped layoutID from DataManager
1 parent 412d72f commit f78119c

File tree

7 files changed

+134
-99
lines changed

7 files changed

+134
-99
lines changed

lib/src/codelessly.dart

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -298,11 +298,12 @@ class Codelessly {
298298
if (!kIsWeb) {
299299
if (_firestore != null) return;
300300
log('[SDK] [INIT] Initializing Firestore instance with project ID: $firebaseProjectId');
301-
302301
final Stopwatch stopwatch = Stopwatch()..start();
302+
303+
303304
_firestore = Firestore(firebaseProjectId);
304-
stopwatch.stop();
305305

306+
stopwatch.stop();
306307
final elapsed = stopwatch.elapsed;
307308
log('[SDK] [INIT] Firestore instance initialized in ${elapsed.inMilliseconds}ms or ${elapsed.inSeconds}s');
308309
}
@@ -399,14 +400,10 @@ class Codelessly {
399400
cacheManager: this.cacheManager,
400401
authManager: this.authManager,
401402
networkDataRepository: kIsWeb
402-
? WebDataRepository(
403-
cloudFunctionsBaseURL:
404-
_config!.firebaseCloudFunctionsBaseURL,
405-
)
403+
? WebDataRepository(config: _config!)
406404
: FirebaseDataRepository(
407405
firestore: firestore,
408-
cloudFunctionsBaseURL:
409-
_config!.firebaseCloudFunctionsBaseURL,
406+
config: _config!,
410407
),
411408
localDataRepository:
412409
LocalDataRepository(cacheManager: this.cacheManager),
@@ -420,14 +417,10 @@ class Codelessly {
420417
cacheManager: this.cacheManager,
421418
authManager: this.authManager,
422419
networkDataRepository: kIsWeb
423-
? WebDataRepository(
424-
cloudFunctionsBaseURL:
425-
_config!.firebaseCloudFunctionsBaseURL,
426-
)
420+
? WebDataRepository(config: _config!)
427421
: FirebaseDataRepository(
428422
firestore: firestore,
429-
cloudFunctionsBaseURL:
430-
_config!.firebaseCloudFunctionsBaseURL,
423+
config: _config!,
431424
),
432425
localDataRepository:
433426
LocalDataRepository(cacheManager: this.cacheManager),
@@ -440,12 +433,10 @@ class Codelessly {
440433
cacheManager: this.cacheManager,
441434
authManager: this.authManager,
442435
networkDataRepository: kIsWeb
443-
? WebDataRepository(
444-
cloudFunctionsBaseURL: _config!.firebaseCloudFunctionsBaseURL,
445-
)
436+
? WebDataRepository(config: _config!)
446437
: FirebaseDataRepository(
447438
firestore: firestore,
448-
cloudFunctionsBaseURL: _config!.firebaseCloudFunctionsBaseURL,
439+
config: _config!,
449440
),
450441
localDataRepository:
451442
LocalDataRepository(cacheManager: this.cacheManager),

lib/src/constants.dart

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@ const String defaultFirebaseCloudFunctionsBaseURL = String.fromEnvironment(
88
defaultValue: prodFirebaseCloudFunctionsBaseURL,
99
);
1010

11-
const String defaultFirebaseApiKey = String.fromEnvironment(
12-
'firebase_api_key',
13-
defaultValue: prodApiKey,
14-
);
15-
1611
const String defaultBaseURL = String.fromEnvironment(
1712
'base_url',
1813
defaultValue: prodBaseUrl,
@@ -21,7 +16,6 @@ const String defaultBaseURL = String.fromEnvironment(
2116
const String prodFirebaseProjectId = 'codeless-app';
2217
const String prodFirebaseCloudFunctionsBaseURL =
2318
'https://us-central1-codeless-app.cloudfunctions.net';
24-
const String prodApiKey = 'AIzaSyBR92IoT_1kwBYOLBbPvln48DwaXTeTrxk';
2519
const String prodBaseUrl = 'https://app.codelessly.com';
2620

2721
const defaultErrorMessage =

lib/src/data/data_manager.dart

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ class DataManager {
5050

5151
StreamSubscription<SDKPublishModel?>? _publishModelDocumentListener;
5252

53-
String? slug;
53+
/// The slug for the project as defined in the editor's publish settings.
54+
late String? slug = config.slug;
5455

5556
/// Creates a new instance of [DataManager] with the given [config].
5657
DataManager({
@@ -97,21 +98,22 @@ class DataManager {
9798
if (config.slug != null && (_publishModel == null || slug != config.slug)) {
9899
final Stopwatch bundleStopWatch = Stopwatch()..start();
99100
try {
100-
slug = config.slug;
101+
if (_publishModel == null) {
102+
log('[DataManager] No local publish model found, but a slug was specified!');
103+
} else {
104+
log('[DataManager] Slug changed from $slug to ${config.slug}.');
105+
}
106+
log('[DataManager] Downloading complete publish bundle for slug $slug.');
101107

102-
log('[DataManager] No local publish model, but a slug was specified!');
103-
log('[DataManager] Downloading complete publish bundle for slug ${config.slug}.');
108+
slug = config.slug;
104109

105-
_publishModel =
106-
await networkDataRepository.downloadCompletePublishBundle(
107-
slug: config.slug!,
110+
final bool success = await fetchCompletePublishBundle(
111+
slug: slug!,
108112
source: config.publishSource,
109113
);
110114

111-
if (_publishModel != null) {
115+
if (success) {
112116
log('[DataManager] Complete publish model from slug is downloaded. Emitting.');
113-
emitPublishModel();
114-
savePublishModel();
115117

116118
loadFontsFromPublishModel();
117119

@@ -279,7 +281,11 @@ class DataManager {
279281
assert(_publishModel != null, 'Publish model cannot be null here.');
280282

281283
log('[DataManager] About to load all fonts that are present in the current publish model.');
282-
log('[DataManager] Fonts: ${_publishModel!.fonts.values.map((font) => font.fullFontName).join(', ')}');
284+
if (_publishModel!.fonts.isNotEmpty) {
285+
log('[DataManager] Fonts: ${_publishModel!.fonts.values.map((font) => font.fullFontName).join(', ')}');
286+
} else {
287+
log('[DataManager] No fonts to load.');
288+
}
283289

284290
for (final SDKPublishFont font in _publishModel!.fonts.values) {
285291
getOrFetchFontBytesAndSaveAndLoad(font);
@@ -915,24 +921,33 @@ class DataManager {
915921

916922
Future<bool> fetchCompletePublishBundle({
917923
required String slug,
924+
required PublishSource source,
918925
}) async {
919926
final Stopwatch stopwatch = Stopwatch()..start();
920927

921-
final SDKPublishModel? model =
922-
await networkDataRepository.downloadCompletePublishBundle(
923-
slug: slug,
924-
source: config.publishSource,
925-
);
926-
927-
log('[DataManager] Downloaded complete publish bundle in ${stopwatch.elapsedMilliseconds}ms or ${stopwatch.elapsed.inSeconds}s.');
928+
SDKPublishModel? model;
929+
try {
930+
model = await networkDataRepository.downloadCompletePublishBundle(
931+
slug: slug,
932+
source: source,
933+
);
934+
} catch (e) {
935+
log('[DataManager] Failed to download complete publish bundle.');
936+
return false;
937+
} finally {
938+
stopwatch.stop();
939+
log('[DataManager] Publish bundle download stopwatch done in ${stopwatch.elapsedMilliseconds}ms or ${stopwatch.elapsed.inSeconds}s.');
940+
}
928941

929942
if (model != null) {
943+
log('[DataManager] Successfully downloaded complete publish bundle. Emitting it.');
930944
_publishModel = model;
931945
emitPublishModel();
932946
savePublishModel();
933947
return true;
934948
}
935949

950+
log('[DataManager] Failed to download complete publish bundle in ${stopwatch.elapsedMilliseconds}ms or ${stopwatch.elapsed.inSeconds}s.');
936951
return false;
937952
}
938953

lib/src/data/firebase_data_repository.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ class FirebaseDataRepository extends NetworkDataRepository {
1010

1111
/// Creates a new [FirebaseDataRepository] instance with the given [firestore]
1212
/// instance.
13-
FirebaseDataRepository(
14-
{required this.firestore, required super.cloudFunctionsBaseURL});
13+
FirebaseDataRepository({required this.firestore, required super.config});
1514

1615
@override
1716
Stream<SDKPublishModel?> streamPublishModel({

lib/src/data/network_data_repository.dart

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'dart:async';
12
import 'dart:convert';
23
import 'dart:developer';
34
import 'dart:typed_data';
@@ -11,11 +12,11 @@ import '../logging/error_handler.dart';
1112
/// need to utilize to offer a complete usage experience of a [Codelessly]
1213
/// layout.
1314
abstract class NetworkDataRepository {
14-
final String cloudFunctionsBaseURL;
15+
/// The [CodelesslyConfig] instance that is used to configure the SDK.
16+
final CodelesslyConfig config;
1517

16-
NetworkDataRepository({required this.cloudFunctionsBaseURL}) {
17-
log('[NetworkDataRepo] created with cloudFunctionsBaseURL: $cloudFunctionsBaseURL');
18-
}
18+
/// Creates a new instance of [NetworkDataRepository].
19+
NetworkDataRepository({required this.config});
1920

2021
/// Calls a cloud function that searches for the project associated with the
2122
/// given unique slug and returns a completely populated [SDKPublishModel]
@@ -25,12 +26,12 @@ abstract class NetworkDataRepository {
2526
required PublishSource source,
2627
}) async {
2728
log('[NetworkDataRepo] Downloading publish bundle with slug: $slug and source: $source');
28-
final http.Response result = await http.post(
29-
Uri.parse('$cloudFunctionsBaseURL/getPublishBundleBySlugRequest'),
30-
headers: <String, String>{'Content-Type': 'application/json'},
31-
body: jsonEncode({'slug': slug, 'source': source.serverPath}),
32-
encoding: utf8,
33-
);
29+
30+
final url =
31+
'https://firebasestorage.googleapis.com/v0/b/${config.firebaseProjectId}.appspot.com/o/${Uri.encodeComponent('${source.serverPath}/$slug.json')}?alt=media';
32+
33+
log('[NetworkDataRepo] Downloading publish bundle from url: $url');
34+
final http.Response result = await http.get(Uri.parse(url));
3435

3536
if (result.statusCode != 200) {
3637
log('[NetworkDataRepo] Error downloading publish bundle.');
@@ -43,13 +44,49 @@ abstract class NetworkDataRepository {
4344
return null;
4445
}
4546

46-
final Map<String, dynamic> modelDoc = jsonDecode(result.body);
47+
final Map<String, dynamic> modelDoc =
48+
jsonDecode(utf8.decode(result.bodyBytes));
49+
4750
final SDKPublishModel model = SDKPublishModel.fromJson(modelDoc);
4851

4952
log('[NetworkDataRepo] Finished downloading publish bundle with slug: $slug and source: $source.');
5053
return model;
5154
}
5255

56+
/// Calls a cloud function that searches for the project associated with the
57+
/// given unique slug and returns a completely populated [SDKPublishModel]
58+
/// instance.
59+
// Future<SDKPublishModel?> downloadCompletePublishBundle({
60+
// required String slug,
61+
// required PublishSource source,
62+
// }) async {
63+
// log('[NetworkDataRepo] Downloading publish bundle with slug: $slug and source: $source');
64+
// final http.Response result = await http.post(
65+
// Uri.parse(
66+
// '${config.firebaseCloudFunctionsBaseURL}/getPublishBundleBySlugRequest'),
67+
// headers: <String, String>{'Content-Type': 'application/json'},
68+
// body: jsonEncode({'slug': slug, 'source': source.serverPath}),
69+
// encoding: utf8,
70+
// );
71+
//
72+
// if (result.statusCode != 200) {
73+
// log('[NetworkDataRepo] Error downloading publish bundle.');
74+
// log('[NetworkDataRepo] Status code: ${result.statusCode}');
75+
// log('[NetworkDataRepo] Message: ${result.body}');
76+
// CodelesslyErrorHandler.instance.captureException(CodelesslyException(
77+
// 'Error downloading publish bundle from slug [$slug]',
78+
// stacktrace: StackTrace.current,
79+
// ));
80+
// return null;
81+
// }
82+
//
83+
// final Map<String, dynamic> modelDoc = jsonDecode(result.body);
84+
// final SDKPublishModel model = SDKPublishModel.fromJson(modelDoc);
85+
//
86+
// log('[NetworkDataRepo] Finished downloading publish bundle with slug: $slug and source: $source.');
87+
// return model;
88+
// }
89+
5390
/// Streams a given [projectID]'s associated [SDKPublishModel] from the
5491
/// network with preferably live updates.
5592
Stream<SDKPublishModel?> streamPublishModel({

lib/src/data/web_data_repository.dart

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,17 @@ import '../logging/error_handler.dart';
1313
/// Since Firedart is not compatible with Flutter Web, this implementation
1414
/// utilizes the http package instead.
1515
class WebDataRepository extends NetworkDataRepository {
16+
1617
/// Creates a [WebDataRepository] instance.
17-
WebDataRepository({required super.cloudFunctionsBaseURL}) {
18-
log('[WebDataRepo] created with cloudFunctionsBaseURL: $cloudFunctionsBaseURL');
19-
}
18+
WebDataRepository({required super.config});
2019

2120
@override
2221
Stream<SDKPublishModel?> streamPublishModel({
2322
required String projectID,
2423
required PublishSource source,
2524
}) async* {
2625
final Response result = await post(
27-
Uri.parse('$cloudFunctionsBaseURL/getPublishModelRequest'),
26+
Uri.parse('${config.firebaseCloudFunctionsBaseURL}/getPublishModelRequest'),
2827
headers: <String, String>{'Content-Type': 'application/json'},
2928
body: jsonEncode({
3029
'projectID': projectID,
@@ -55,7 +54,7 @@ class WebDataRepository extends NetworkDataRepository {
5554
required PublishSource source,
5655
}) async {
5756
final Response result = await post(
58-
Uri.parse('$cloudFunctionsBaseURL/getLayoutModelRequest'),
57+
Uri.parse('${config.firebaseCloudFunctionsBaseURL}/getLayoutModelRequest'),
5958
headers: <String, String>{'Content-Type': 'application/json'},
6059
body: jsonEncode({
6160
'projectID': projectID,
@@ -90,7 +89,7 @@ class WebDataRepository extends NetworkDataRepository {
9089
}) async {
9190
try {
9291
final Response result = await post(
93-
Uri.parse('$cloudFunctionsBaseURL/getFontModelRequest'),
92+
Uri.parse('${config.firebaseCloudFunctionsBaseURL}/getFontModelRequest'),
9493
headers: <String, String>{'Content-Type': 'application/json'},
9594
body: jsonEncode({
9695
'projectID': projectID,
@@ -126,7 +125,7 @@ class WebDataRepository extends NetworkDataRepository {
126125
}) async {
127126
try {
128127
final Response result = await post(
129-
Uri.parse('$cloudFunctionsBaseURL/getPublishedApiRequest'),
128+
Uri.parse('${config.firebaseCloudFunctionsBaseURL}/getPublishedApiRequest'),
130129
headers: <String, String>{'Content-Type': 'application/json'},
131130
body: jsonEncode({
132131
'projectID': projectID,
@@ -164,7 +163,7 @@ class WebDataRepository extends NetworkDataRepository {
164163
}) async {
165164
try {
166165
final Response result = await post(
167-
Uri.parse('$cloudFunctionsBaseURL/getPublishedLayoutVariablesRequest'),
166+
Uri.parse('${config.firebaseCloudFunctionsBaseURL}/getPublishedLayoutVariablesRequest'),
168167
headers: <String, String>{'Content-Type': 'application/json'},
169168
body: jsonEncode({
170169
'projectID': projectID,
@@ -204,7 +203,7 @@ class WebDataRepository extends NetworkDataRepository {
204203
log('[WebDataRepo] Downloading conditions for $layoutID');
205204
try {
206205
final Response result = await post(
207-
Uri.parse('$cloudFunctionsBaseURL/getPublishedLayoutConditionsRequest'),
206+
Uri.parse('${config.firebaseCloudFunctionsBaseURL}/getPublishedLayoutConditionsRequest'),
208207
headers: <String, String>{'Content-Type': 'application/json'},
209208
body: jsonEncode({
210209
'projectID': projectID,

0 commit comments

Comments
 (0)