mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
[macOS] Remigrate principal class to NSApplication (#124173)
In #122336 we migrated the principal class from NSApplication to FlutterApplication in the app Info.plist. We removed the need for FlutterApplication in https://github.com/flutter/engine/pull/40929. This reverses the migration for anyone who previously upgraded on the Flutter master branch. Issue: https://github.com/flutter/flutter/issues/30735 ## Pre-launch Checklist - [X] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [X] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [X] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [X] I signed the [CLA]. - [X] I listed at least one issue that this PR fixes in the description above. - [X] I updated/added relevant documentation (doc comments with `///`). - [X] I added new tests to check the change I am making, or this PR is [test-exempt]. - [X] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [test-exempt]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [Features we expect every widget to implement]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat
This commit is contained in:
parent
a8354ff165
commit
e5fc6f65b9
@ -27,6 +27,6 @@
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>FlutterApplication</string>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -27,6 +27,6 @@
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>FlutterApplication</string>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -27,6 +27,6 @@
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>FlutterApplication</string>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -29,6 +29,6 @@
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>FlutterApplication</string>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -27,6 +27,6 @@
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>FlutterApplication</string>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -27,6 +27,6 @@
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>FlutterApplication</string>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -27,6 +27,6 @@
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>FlutterApplication</string>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -27,6 +27,6 @@
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>FlutterApplication</string>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -27,6 +27,6 @@
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>FlutterApplication</string>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -27,6 +27,6 @@
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>FlutterApplication</string>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -27,6 +27,6 @@
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>FlutterApplication</string>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -27,6 +27,6 @@
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>FlutterApplication</string>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -27,6 +27,6 @@
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>FlutterApplication</string>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -27,6 +27,6 @@
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>FlutterApplication</string>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -8,7 +8,13 @@ import '../../globals.dart' as globals;
|
||||
import '../../ios/plist_parser.dart';
|
||||
import '../../xcode_project.dart';
|
||||
|
||||
/// Update the minimum macOS deployment version to the minimum allowed by Xcode without causing a warning.
|
||||
/// Migrate principle class from FlutterApplication to NSApplication.
|
||||
///
|
||||
/// For several weeks, we required macOS apps to use FlutterApplication as the
|
||||
/// app's NSPrincipalClass rather than NSApplication. During that time an
|
||||
/// automated migration migrated the NSPrincipalClass in the Info.plist from
|
||||
/// NSApplication to FlutterApplication. Now that this is no longer necessary,
|
||||
/// we apply the reverse migration for anyone who was previously migrated.
|
||||
class FlutterApplicationMigration extends ProjectMigrator {
|
||||
FlutterApplicationMigration(
|
||||
MacOSProject project,
|
||||
@ -20,29 +26,23 @@ class FlutterApplicationMigration extends ProjectMigrator {
|
||||
@override
|
||||
void migrate() {
|
||||
if (_infoPlistFile.existsSync()) {
|
||||
final String? principleClass =
|
||||
final String? principalClass =
|
||||
globals.plistParser.getStringValueFromFile(_infoPlistFile.path, PlistParser.kNSPrincipalClassKey);
|
||||
if (principleClass == null || principleClass == 'FlutterApplication') {
|
||||
// No NSPrincipalClass defined, or already converted, so no migration
|
||||
if (principalClass == null || principalClass == 'NSApplication') {
|
||||
// No NSPrincipalClass defined, or already converted. No migration
|
||||
// needed.
|
||||
return;
|
||||
}
|
||||
if (principleClass != 'NSApplication') {
|
||||
// Only replace NSApplication values, since we don't know why they might
|
||||
// have substituted something else.
|
||||
logger.printTrace('${_infoPlistFile.basename} has an '
|
||||
'${PlistParser.kNSPrincipalClassKey} of $principleClass, not '
|
||||
'NSApplication, skipping FlutterApplication migration.\nYou will need '
|
||||
'to modify your application class to derive from FlutterApplication.');
|
||||
if (principalClass != 'FlutterApplication') {
|
||||
// If the principal class wasn't already migrated to
|
||||
// FlutterApplication, there's no need to revert the migration.
|
||||
return;
|
||||
}
|
||||
logger.printStatus('Updating ${_infoPlistFile.basename} to use FlutterApplication instead of NSApplication.');
|
||||
final bool success = globals.plistParser.replaceKey(_infoPlistFile.path, key: PlistParser.kNSPrincipalClassKey, value: 'FlutterApplication');
|
||||
logger.printStatus('Updating ${_infoPlistFile.basename} to use NSApplication instead of FlutterApplication.');
|
||||
final bool success = globals.plistParser.replaceKey(_infoPlistFile.path, key: PlistParser.kNSPrincipalClassKey, value: 'NSApplication');
|
||||
if (!success) {
|
||||
logger.printError('Updating ${_infoPlistFile.basename} failed.');
|
||||
}
|
||||
} else {
|
||||
logger.printTrace('${_infoPlistFile.basename} not found, skipping FlutterApplication migration.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,6 @@
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>FlutterApplication</string>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -280,7 +280,7 @@ platform :osx, '10.14'
|
||||
});
|
||||
});
|
||||
|
||||
group('update NSPrincipalClass to FlutterApplication', () {
|
||||
group('update NSPrincipalClass from FlutterApplication to NSApplication', () {
|
||||
late MemoryFileSystem memoryFileSystem;
|
||||
late BufferLogger testLogger;
|
||||
late FakeMacOSProject project;
|
||||
@ -318,7 +318,7 @@ platform :osx, '10.14'
|
||||
macOSProjectMigration.migrate();
|
||||
expect(infoPlistFile.existsSync(), isFalse);
|
||||
|
||||
expect(testLogger.traceText, contains('${infoPlistFile.basename} not found, skipping FlutterApplication migration.'));
|
||||
expect(testLogger.traceText, isEmpty);
|
||||
expect(testLogger.statusText, isEmpty);
|
||||
});
|
||||
|
||||
@ -333,19 +333,7 @@ platform :osx, '10.14'
|
||||
expect(testLogger.statusText, isEmpty);
|
||||
});
|
||||
|
||||
testWithMocks('skipped if already upgraded', () async {
|
||||
fakePlistParser.setProperty(PlistParser.kNSPrincipalClassKey, 'FlutterApplication');
|
||||
final FlutterApplicationMigration macOSProjectMigration = FlutterApplicationMigration(
|
||||
project,
|
||||
testLogger,
|
||||
);
|
||||
infoPlistFile.writeAsStringSync('contents'); // Just so it exists: parser is a fake.
|
||||
macOSProjectMigration.migrate();
|
||||
expect(fakePlistParser.getStringValueFromFile(infoPlistFile.path, PlistParser.kNSPrincipalClassKey), 'FlutterApplication');
|
||||
expect(testLogger.statusText, isEmpty);
|
||||
});
|
||||
|
||||
testWithMocks('Info.plist migrated to use FlutterApplication', () async {
|
||||
testWithMocks('skipped if already de-upgraded (or never migrated)', () async {
|
||||
fakePlistParser.setProperty(PlistParser.kNSPrincipalClassKey, 'NSApplication');
|
||||
final FlutterApplicationMigration macOSProjectMigration = FlutterApplicationMigration(
|
||||
project,
|
||||
@ -353,9 +341,21 @@ platform :osx, '10.14'
|
||||
);
|
||||
infoPlistFile.writeAsStringSync('contents'); // Just so it exists: parser is a fake.
|
||||
macOSProjectMigration.migrate();
|
||||
expect(fakePlistParser.getStringValueFromFile(infoPlistFile.path, PlistParser.kNSPrincipalClassKey), 'FlutterApplication');
|
||||
expect(fakePlistParser.getStringValueFromFile(infoPlistFile.path, PlistParser.kNSPrincipalClassKey), 'NSApplication');
|
||||
expect(testLogger.statusText, isEmpty);
|
||||
});
|
||||
|
||||
testWithMocks('Info.plist migrated to use NSApplication', () async {
|
||||
fakePlistParser.setProperty(PlistParser.kNSPrincipalClassKey, 'FlutterApplication');
|
||||
final FlutterApplicationMigration macOSProjectMigration = FlutterApplicationMigration(
|
||||
project,
|
||||
testLogger,
|
||||
);
|
||||
infoPlistFile.writeAsStringSync('contents'); // Just so it exists: parser is a fake.
|
||||
macOSProjectMigration.migrate();
|
||||
expect(fakePlistParser.getStringValueFromFile(infoPlistFile.path, PlistParser.kNSPrincipalClassKey), 'NSApplication');
|
||||
// Only print once.
|
||||
expect('Updating ${infoPlistFile.basename} to use FlutterApplication instead of NSApplication.'.allMatches(testLogger.statusText).length, 1);
|
||||
expect('Updating ${infoPlistFile.basename} to use NSApplication instead of FlutterApplication.'.allMatches(testLogger.statusText).length, 1);
|
||||
});
|
||||
|
||||
testWithMocks('Skip if NSPrincipalClass is not NSApplication', () async {
|
||||
@ -368,7 +368,7 @@ platform :osx, '10.14'
|
||||
infoPlistFile.writeAsStringSync('contents'); // Just so it exists: parser is a fake.
|
||||
macOSProjectMigration.migrate();
|
||||
expect(fakePlistParser.getStringValueFromFile(infoPlistFile.path, PlistParser.kNSPrincipalClassKey), differentApp);
|
||||
expect(testLogger.traceText, contains('${infoPlistFile.basename} has an ${PlistParser.kNSPrincipalClassKey} of $differentApp, not NSApplication, skipping FlutterApplication migration'));
|
||||
expect(testLogger.traceText, isEmpty);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user