exec method
Run command.
The contents of katana.yaml
and the arguments of the command are passed to context
.
コマンドを実行します。
context
にkatana.yaml
の内容やコマンドの引数が渡されます。
Implementation
@override
Future<void> exec(ExecContext context) async {
final firebase = context.yaml.getAsMap("firebase");
final messaging = firebase.getAsMap("messaging");
final channelId = messaging.get("channel_id", "");
final notificationIcon = messaging.get("android_notification_icon", "");
if (channelId.isEmpty) {
error(
"Channel ID is not specified in [firebase]->[messaging]->[channel_id]. Please specify any ID.",
);
return;
}
label("Add processing to the Gradle file.");
final gradle = AppGradle();
await gradle.load();
if (!gradle.loadProperties.any((e) => e.name == "configProperties")) {
gradle.loadProperties.add(
GradleLoadProperties(
path: "config.properties",
name: "configProperties",
file: "configPropertiesFile",
),
);
}
if (!(gradle.android?.defaultConfig.resValues.any(
(e) => e.startsWith("'string', 'notification_channel_id'"),
) ??
false)) {
gradle.android?.defaultConfig.resValues.add(
"'string', 'notification_channel_id', configProperties['notificationChannelId']",
);
}
await gradle.save();
label("Edit config.properties.");
final properties = File("android/config.properties");
if (properties.existsSync()) {
final contents = await properties.readAsLines();
if (!contents.any((e) => e.startsWith("notificationChannelId"))) {
contents.add("notificationChannelId=$channelId");
}
await properties.writeAsString(contents.join("\n"));
} else {
await properties.writeAsString(
"notificationChannelId=$channelId",
);
}
if (notificationIcon.isNotEmpty) {
label("Create notification icon.");
final iconFile = File(notificationIcon);
if (!iconFile.existsSync()) {
error("Icon file not found in $notificationIcon.");
return;
}
final iconImage = decodeImage(iconFile.readAsBytesSync())!;
if (iconImage.width != 1024 || iconImage.height != 1024) {
error("Icon files should be 1024 x 1024.");
return;
}
for (final tmp in _sizeListNotificationIcon.entries) {
label("Resize & Save to ${tmp.key}");
final dir = Directory(tmp.key.parentPath());
if (!dir.existsSync()) {
await dir.create(recursive: true);
}
final file = File(tmp.key);
if (file.existsSync()) {
await file.delete();
}
final resized = adjustColor(
copyResize(
iconImage,
height: tmp.value,
width: tmp.value,
interpolation: Interpolation.average,
),
mids: ColorUint8.rgb(255, 255, 255),
blacks: ColorUint8.rgb(255, 255, 255),
whites: ColorUint8.rgb(255, 255, 255),
);
await file.writeAsBytes(encodePng(resized, level: 9));
}
}
label("Edit AndroidManifest.xml.");
final file = File("android/app/src/main/AndroidManifest.xml");
if (!file.existsSync()) {
throw Exception(
"AndroidManifest does not exist in `android/app/src/main/AndroidManifest.xml`. Do `katana create` to complete the initial setup of the project.",
);
}
final document = XmlDocument.parse(await file.readAsString());
final application = document.findAllElements("application");
final activity = document.findAllElements("activity");
if (application.isEmpty) {
throw Exception(
"The structure of AndroidManifest.xml is broken. Do `katana create` to complete the initial setup of the project.",
);
}
if (notificationIcon.isNotEmpty &&
!application.first.children.any((p0) =>
p0 is XmlElement &&
p0.name.toString() == "meta-data" &&
(p0.attributes.any((item) =>
item.name.toString() == "android:name" &&
item.value ==
"com.google.firebase.messaging.default_notification_icon")))) {
application.first.children.add(
XmlElement(
XmlName("meta-data"),
[
XmlAttribute(
XmlName("android:name"),
"com.google.firebase.messaging.default_notification_icon",
),
XmlAttribute(
XmlName("android:resource"),
"@mipmap/ic_launcher_notification",
),
],
[],
),
);
}
if (!activity.first.children.any((p0) =>
p0 is XmlElement &&
p0.name.toString() == "intent-filter" &&
(p0.findElements("action").firstOrNull?.attributes.any((item) =>
item.name.toString() == "android:name" &&
item.value == "FLUTTER_NOTIFICATION_CLICK") ??
false))) {
activity.first.children.add(
XmlElement(
XmlName("intent-filter"),
[],
[
XmlElement(
XmlName("action"),
[
XmlAttribute(
XmlName("android:name"),
"FLUTTER_NOTIFICATION_CLICK",
),
],
[],
),
XmlElement(
XmlName("category"),
[
XmlAttribute(
XmlName("android:name"),
"android.intent.category.DEFAULT",
),
],
[],
),
],
),
);
}
if (!application.first.children.any(
(p0) =>
p0 is XmlElement &&
p0.name.toString() == "meta-data" &&
p0.attributes.any(
(p1) =>
p1.name.toString() == "android:name" &&
p1.value ==
"com.google.firebase.messaging.default_notification_channel_id",
),
)) {
application.first.children.add(
XmlElement(
XmlName("meta-data"),
[
XmlAttribute(
XmlName("android:name"),
"com.google.firebase.messaging.default_notification_channel_id",
),
XmlAttribute(
XmlName("android:value"),
"@string/notification_channel_id",
),
],
[],
),
);
}
await file.writeAsString(
document.toXmlString(pretty: true, indent: " ", newLine: "\n"),
);
label("Edit Runner.entitlements.");
await XCode.createRunnerEntitlements();
final entitlements = File("ios/Runner/Runner.entitlements");
if (entitlements.existsSync()) {
final document = XmlDocument.parse(await entitlements.readAsString());
final dict = document.findAllElements("dict").firstOrNull;
if (dict == null) {
throw Exception(
"Could not find `dict` element in `ios/Runner/Runner.entitlements`. File is corrupt.",
);
}
final node = dict.children.firstWhereOrNull((p0) {
return p0 is XmlElement &&
p0.name.toString() == "key" &&
p0.innerText == "aps-environment";
});
if (node == null) {
dict.children.addAll(
[
XmlElement(
XmlName("key"),
[],
[XmlText("aps-environment")],
),
XmlElement(
XmlName("string"),
[],
[XmlText("development")],
),
],
);
}
await entitlements.writeAsString(
document.toXmlString(pretty: true, indent: "\t", newLine: "\n"),
);
}
await addFlutterImport(
[
"masamune_notification_firebase",
],
);
label("Add firebase-messaging-sw.js");
final swFile = File("web/firebase-messaging-sw.js");
if (!swFile.existsSync()) {
await swFile.writeAsString("console.log('Empty');");
}
if (Directory("firebase/functions").existsSync()) {
label("Add firebase functions");
final functions = Fuctions();
await functions.load();
if (!functions.functions.any((e) => e.startsWith("sendNotification"))) {
functions.functions.add("sendNotification()");
}
await functions.save();
context.requestFirebaseDeploy(FirebaseDeployPostActionType.functions);
// await command(
// "Deploy firebase functions.",
// [
// firebaseCommand,
// "deploy",
// "--only",
// "functions",
// ],
// workingDirectory: "firebase",
// );
}
}