Skip to content

Commit 9f55bf0

Browse files
biozalCopilot
andauthored
Update Quickstart for Flutter/Dart to v5 (#237)
* feature: updated MacOS, iOS, and Windows to run v5 along with API changes and README update * fix: lint ran in main.dart * fix: updated for preview 4 * updated to 5.0.0-preview-r * Updated to RC1 - fix CI/CD Issues * updated to fix test failing with update to dotenv * fix Android builds based on minSdkVersion * fixing the ios tests * Updated for RC3 * updated Flutter * flutter version manager config * Updated for version 5 * Updated README * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * updated pubspec to 3.24.0 flutter releawse --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
1 parent e8ae5c4 commit 9f55bf0

20 files changed

Lines changed: 381 additions & 143 deletions

File tree

.fvmrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"flutter": "3.32.8"
3+
}

.github/browserstack-devices.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ flutter:
3838
- "Google Pixel 6-12.0" # Android 12 support
3939
ios:
4040
devices:
41-
- "iPhone 13-15" # iOS 15 support
41+
- "iPhone 13-16" # iOS 16 support (min deployment target is 15.6)
4242
- "iPhone 14-16" # iOS 16 current
4343
- "iPhone 12-17" # iOS 17 latest
4444

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,6 @@ packages/
3434
Pods/
3535
target/
3636
xcuserdata
37+
38+
# FVM Version Cache
39+
.fvm/

flutter_app/README.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,25 @@ This is a basic task application that demonstrates how to use Ditto's peer-to-pe
77
## Prerequisites
88

99
- Dart SDK installed
10-
- Flutter SDK installed (tested on 3.24)
11-
- Java Virtual Machine (JVM) 11 installed
10+
- Flutter SDK installed (tested on 3.29/3.32)
11+
- Java Virtual Machine (JVM) 11 or greater installed
1212
- Git command line installed (Windows requirement)
1313
- XCode installed (for iOS development)
1414
- Android Studio installed (for managing the Android SDK)
1515
- Android SDK installed
1616
- IDE of choice (Android Studio, VS Code, etc)
1717

18+
### Flutter Version Manager
19+
If you need to test on multiple versions of Flutter, it's recommended to use `fvm` (Flutter Version Manager). You can find documentation [here](https://fvm.app/documentation/getting-started/overview).
20+
21+
### MacOS Development
22+
This has been tested with XCode 26.2 on MacOS 26.6 with Flutter 3.29.3 && 3.32.8.
23+
24+
### Windows Development
25+
To build the Windows version of this Flutter app requires Visual Studio 2022 specifically be
26+
installed and configured with C++ and CMake installed from the Visual Studio Installer. This has
27+
been tested with Flutter version 3.29.3 on Windows.
28+
1829
## Getting Started
1930

2031
### 1. Clone the Repository
@@ -78,7 +89,7 @@ Please choose one (or "q" to quit):
7889
> If you are going to use a physical iPhone, you will need to update the Team under Signing & Capabilities in XCode. You can open the ios/Runner.xcodeproj file in XCode and then set your team from the Runner Target -> Signing & Capabilities tab.
7990
>
8091
81-
- Ensure that cocoapods is up to date
92+
- Ensure that cocoapods is up to date (or you can use Homebrew with `brew install cocoapods`)
8293

8394
```bash
8495
gem install cocoapods

flutter_app/android/build.gradle

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,25 @@ subprojects {
1515
project.evaluationDependsOn(':app')
1616
}
1717

18+
// Ditto v5 requires minSdkVersion 24+ (ditto-internal-rustls:5.0.0).
19+
// Flutter plugins default their own androidTest minSdkVersion to 23, which
20+
// breaks the manifest merger. Bump every Android subproject (notably
21+
// :ditto_live) to match.
22+
subprojects {
23+
afterEvaluate { project ->
24+
if (project.plugins.hasPlugin('com.android.application') ||
25+
project.plugins.hasPlugin('com.android.library')) {
26+
project.android {
27+
defaultConfig {
28+
if (minSdkVersion == null || minSdkVersion.apiLevel < 24) {
29+
minSdkVersion 24
30+
}
31+
}
32+
}
33+
}
34+
}
35+
}
36+
1837
tasks.register("clean", Delete) {
1938
delete rootProject.buildDir
2039
}

flutter_app/integration_test/app_test.dart

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,15 @@ void main() {
1717
(WidgetTester tester) async {
1818
// Initialize app
1919
await app.main();
20-
await tester.pumpAndSettle(const Duration(seconds: 5));
20+
// Allow up to 10 seconds for Ditto to initialise and the first sync
21+
// exchange to complete. pumpAndSettle returns as soon as the UI is
22+
// idle, so on fast devices this resolves much sooner.
23+
await tester.pumpAndSettle(const Duration(seconds: 10));
2124

22-
// Tap "OK" button if Bluetooth permission dialog appears (iOS)
23-
final okButton = find.text('OK');
24-
if (okButton.evaluate().isNotEmpty) {
25-
await tester.tap(okButton);
26-
await tester.pumpAndSettle(const Duration(seconds: 2));
27-
}
28-
29-
// Tap "Allow" button if local network permission dialog appears (iOS)
30-
final allowButton = find.text('Allow');
31-
if (allowButton.evaluate().isNotEmpty) {
32-
await tester.tap(allowButton);
33-
await tester.pumpAndSettle(const Duration(seconds: 2));
34-
}
25+
// NOTE: iOS system permission dialogs (Bluetooth, Local Network) are
26+
// native UIAlertControllers and cannot be found or tapped via Flutter's
27+
// widget-tree finders. They are handled at the XCTest layer in
28+
// ios/RunnerTests/RunnerTests.m via addUIInterruptionMonitor.
3529

3630
// Verify app title is present
3731
expect(find.text('Ditto Tasks'), findsOneWidget);
@@ -45,21 +39,33 @@ void main() {
4539
// Verify clear button is present
4640
expect(find.byIcon(Icons.clear), findsOneWidget);
4741

48-
// Wait for sync to complete
49-
await Future.delayed(const Duration(seconds: 5));
50-
await tester.pumpAndSettle();
51-
52-
// Look for the test document that should be synced from Ditto cloud
42+
// Look for the test document that should be synced from Ditto cloud.
43+
// The playground can accumulate many documents from previous CI runs,
44+
// so we poll rather than waiting a fixed amount of time.
5345
const testTitle = String.fromEnvironment('TASK_TO_FIND');
5446

5547
if (testTitle.isEmpty) {
5648
throw Exception('TASK_TO_FIND environment variable must be set. '
5749
'Build with: --dart-define=TASK_TO_FIND=<task_title>');
5850
}
5951

60-
expect(find.text(testTitle), findsOneWidget,
52+
// Poll every 500 ms for up to 45 seconds to give the cloud sync
53+
// enough time to deliver and write all documents to the local store.
54+
const syncTimeout = Duration(seconds: 45);
55+
final deadline = DateTime.now().add(syncTimeout);
56+
bool taskFound = false;
57+
58+
while (DateTime.now().isBefore(deadline)) {
59+
await tester.pump(const Duration(milliseconds: 500));
60+
if (find.text(testTitle).evaluate().isNotEmpty) {
61+
taskFound = true;
62+
break;
63+
}
64+
}
65+
66+
expect(taskFound, isTrue,
6167
reason:
62-
'Should find test document with title: $testTitle synced from Ditto cloud');
68+
'Should find test document with title: $testTitle synced from Ditto cloud within ${syncTimeout.inSeconds}s');
6369
});
6470
});
6571
}

flutter_app/ios/Podfile.lock

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
PODS:
2-
- ditto_live (4.14.3):
3-
- DittoFlutter (= 4.14.3)
2+
- ditto_live (5.0.0):
3+
- DittoFlutter (= 5.0.0)
44
- Flutter
5-
- DittoFlutter (4.14.3)
5+
- DittoFlutter (5.0.0)
66
- Flutter (1.0.0)
77
- integration_test (0.0.1):
88
- Flutter
@@ -36,9 +36,9 @@ EXTERNAL SOURCES:
3636
:path: ".symlinks/plugins/permission_handler_apple/ios"
3737

3838
SPEC CHECKSUMS:
39-
ditto_live: 01cde75b8b98f45b65c13dfad5b4667e1bcf0306
40-
DittoFlutter: 1745a5b3152fb758f1604f5f9a26fb3d64362dba
41-
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
39+
ditto_live: f038d915f2ad9206d180d3fd8b231d149b71e3f2
40+
DittoFlutter: 90c4bcdf128b0a14bf8f6f923369e7a6ddccd27d
41+
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
4242
integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e
4343
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
4444
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d

flutter_app/ios/Runner.xcodeproj/project.pbxproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@
494494
DEVELOPMENT_TEAM = 3T2VMFZPPQ;
495495
ENABLE_BITCODE = NO;
496496
INFOPLIST_FILE = Runner/Info.plist;
497+
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
497498
LD_RUNPATH_SEARCH_PATHS = (
498499
"$(inherited)",
499500
"@executable_path/Frameworks",
@@ -685,6 +686,7 @@
685686
DEVELOPMENT_TEAM = 3T2VMFZPPQ;
686687
ENABLE_BITCODE = NO;
687688
INFOPLIST_FILE = Runner/Info.plist;
689+
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
688690
LD_RUNPATH_SEARCH_PATHS = (
689691
"$(inherited)",
690692
"@executable_path/Frameworks",
@@ -710,6 +712,7 @@
710712
DEVELOPMENT_TEAM = 3T2VMFZPPQ;
711713
ENABLE_BITCODE = NO;
712714
INFOPLIST_FILE = Runner/Info.plist;
715+
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
713716
LD_RUNPATH_SEARCH_PATHS = (
714717
"$(inherited)",
715718
"@executable_path/Frameworks",

flutter_app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
buildConfiguration = "Debug"
2727
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
2828
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29+
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
2930
shouldUseLaunchSchemeArgsEnv = "YES">
3031
<MacroExpansion>
3132
<BuildableReference
@@ -51,9 +52,10 @@
5152
</Testables>
5253
</TestAction>
5354
<LaunchAction
54-
buildConfiguration = "Release"
55+
buildConfiguration = "Debug"
5556
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
5657
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
58+
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
5759
launchStyle = "0"
5860
useCustomWorkingDirectory = "NO"
5961
ignoresPersistentStateOnLaunch = "NO"

flutter_app/ios/Runner/Info.plist

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,13 @@
5252
<string>Uses WiFi to connect and sync with nearby devices.</string>
5353
<key>NSBonjourServices</key>
5454
<array>
55-
<string>_http-alt._tcp.</string>
55+
<string>_http-alt._tcp.</string>
56+
</array>
57+
<!-- Required by the Ditto SDK for BLE sync to operate in the background -->
58+
<key>UIBackgroundModes</key>
59+
<array>
60+
<string>bluetooth-central</string>
61+
<string>bluetooth-peripheral</string>
5662
</array>
5763
</dict>
5864
</plist>

0 commit comments

Comments
 (0)